精华内容
下载资源
问答
  • C语言字符串常用操作函数C语言字符串文件操作常用操作函数标准输入/输出重定向文件操作补充 C语言字符串文件操作常用操作函数 字符串输出 - puts int puts(const char *str) 字符串写入标准输出 stdout 字符...

    C语言字符串常用操作函数

    C语言字符串、文件操作常用操作函数

    • 字符串输出 - puts()

    int puts(const char *str)
    字符串写入到标准输出 stdout

    • 字符串输入 - gets()

    char *gets(char *str)
    标准输入 stdin 读取一行

    • 字符串比较 - strcmp()

    int strcmp(const char *str1, const char *str2)
    字符串进行比较

    1. 如果返回值小于 0,则表示 str1 小于 str2。
    2. 如果返回值大于 0,则表示 str1 大于 str2。
    3. 如果返回值等于 0,则表示 str1 等于 str2。
    • 字符串复制 - strcpy()

    char *strcpy(char *dest, const char *src)
    需要注意的是如果目标数组 dest 不够大,而源字符串的长度又太长,可能会造成缓冲溢出的情况。

    • 字符串连接 - strcat()

    char *strcat(char *dest, const char *src)
    指向的字符串追加到 所指向的字符串的结尾

    • 字符串求长 - strlen()

    size_t strlen(const char *str)

    • 打开指定的文件 - fopen()

    FILE *fopen(const char *filename, const char *mode)
    fopen(文件路径,文件使用方式);

    • 文件关闭 - fclose()

    fclose(文件指针)
    若文件关闭成功则返回0,否则返回非0

    • 文件中读取块数据 - fread()

    size_t fread ( void *ptr, size_t size, size_t count, FILE *fp );
    fread(内存首地址, 数据块大小, 数据块个数, 文件指针)

    • 向文件中写入块数据 - fwrite()

    size_t fwrite ( void * ptr, size_t size, size_t count, FILE *fp );
    fwrite(内存首地址, 数据块大小, 数据块个数, 文件指针)

    fread() 与 fwrite 实例
    #include<stdio.h>
    #define N 2
    struct stu{
        char name[10]; //姓名
        int num;  //学号
        int age;  //年龄
        float score;  //成绩
    }boya[N], boyb[N], *pa, *pb;
    int main(){
        FILE *fp;
        int i;
        pa = boya;
        pb = boyb;
        if( (fp=fopen("d:\\demo.txt", "wb+")) == NULL ){
            printf("Cannot open file, press any key to exit!\n");
            getch();
            exit(1);
        }
        //从键盘输入数据
        printf("Input data:\n");
        for(i=0; i<N; i++,pa++){
            scanf("%s %d %d %f",pa->name, &pa->num,&pa->age, &pa->score);
        }
        //将数组 boya 的数据写入文件
        fwrite(boya, sizeof(struct stu), N, fp);
        //将文件指针重置到文件开头
        rewind(fp);
        //从文件读取数据并保存到数据 boyb
        fread(boyb, sizeof(struct stu), N, fp);
        //输出数组 boyb 中的数据
        for(i=0; i<N; i++,pb++){
            printf("%s  %d  %d  %f\n", pb->name, pb->num, pb->age, pb->score);
        }
        fclose(fp);
        return 0;
    }
    
    //结果
    Input data:
    Tom 2 15 90.5↙
    Hua 1 14 99↙
    Tom  2  15  90.500000
    Hua  1  14  99.000000
    
    • 将位置指针移动到文件开头 - rewind()

    void rewind ( FILE *fp );

    • 将位置指针移动到任意位置 - fseek()

    int fseek ( FILE *fp, long offset, int origin );
    参数说明:

    1. fp 为文件指针,也就是被移动的文件。
    2. offset 为偏移量,也就是要移动的字节数。之所以为 long 类型,是希望移动的范围更大,能处理的文件更大。
    3. origin 为起始位置,也就是从何处开始计算偏移量。C语言规定的起始位置有三种,分别为文件开头、当前位置和文件末尾,每个位置都用对应的常量来表示:
    起始值 常量名 常量值
    文件开头 SEEK_SET 0
    当前位置 SEEK_CUR 1
    文件末尾 SEEK_END 2

    值得说明的是,fseek() 一般用于二进制文件,在文本文件中由于要进行转换,计算的位置有时会出错。

    //例如,把位置指针移动到离文件开头100个字节处:
    fseek(fp, 100, 0);
    
    • 从流 stream 读取格式化输入 - fscanf()

    int fscanf (FILE *fp, const char *format, ……);
    fscanf_s(文件指针, 格式参数, 存入地址, 字节数)

    • 发送格式化输出到流 stream 中 - fprintf()

    int fprintf (FILE *fp, onst char *format, ……);
    fprintf(文件指针, 格式字符, 输出列表);

    • 读取字符串并在字符串末尾添加‘\0’ - fgets()

    char *fgets(char *s,int n,FILE *fp);

    fscanf 和 fprintf 函数实例
    #include<stdio.h>
    #define N 2
    struct stu{
        char name[10];
        int num;
        int age;
        float score;
    } boya[N], boyb[N], *pa, *pb;
    int main(){
        FILE *fp;
        int i;
        pa=boya;
        pb=boyb;
        if( (fp=fopen("D:\\demo.txt","wt+")) == NULL ){
            printf("Cannot open file, press any key exit!");
            getch();
            exit(1);
        }
        //从键盘读入数据,保存到boya
        printf("Input data:\n");
        for(i=0; i<N; i++,pa++){
            scanf("%s %d %d %f", pa->name, &pa->num, &pa->age, &pa->score);   
        }
        pa = boya;
        //将boya中的数据写入到文件
        for(i=0; i<N; i++,pa++){
            fprintf(fp,"%s %d %d %f\n", pa->name, pa->num, pa->age, pa->score);   
        }
        //重置文件指针
        rewind(fp);
        //从文件中读取数据,保存到boyb
        for(i=0; i<N; i++,pb++){
            fscanf(fp, "%s %d %d %f\n", pb->name, &pb->num, &pb->age, &pb->score);
        }
        pb=boyb;
        //将boyb中的数据输出到显示器
        for(i=0; i<N; i++,pb++){
            printf("%s  %d  %d  %f\n", pb->name, pb->num, pb->age, pb->score);
        }
        fclose(fp);
        return 0;
    }
    

    fgets(内存首地址, 字符数, 文件指针);
    最多读n-1个字符,当读到回车换行符、到达文件尾或读满n-1个字符时,就停止读取
    (与gets()不同的是,fgets()从指定的流读取字符串,读到换行符时将换行符也作为字符串的一部分读到字符串中来)

    • 将字符串输出到指针fp所指的文件中 - fputs()

    fputs(_In_z_ const char * _Str, _Inout_ FILE * _File);
    fputs(字符串, 文件指针)
    str是要输出的字符串,fp是文件指针,字符串末尾’\0’不输出
    与puts()不同的是,fputs()不会在写入文件的字符串末尾加上换行符’\n’

    • 以只读或读写方式打开的文件上读字符 - fgetc()

    int fgetc (FILE *fp)

    • 将字符c写到文件指针fp所指的文件 - fputc()

    int fputc(int c, FILE *fp)
    fputc(变量名, 文件指针)
    fp是由函数fopen()返回的文件指针,c是要输出的字符(尽管C定义为int型,但只写入低字节)

    • 将fp的文件位置指针从fromwhere开始移动offset个字节指示下一个要读取的数据的位置 - fseek()

    int fseek(FILE *fp,long offset,int fromwhere)
    offset是一个偏移量,它告诉文件位置指针要跳过多少字节,offset为正时,向后移动,为负时,向前移动,ANSIC要求位移量offset是长整型数据(常量数据后要加L),

    这样当文件的长度大于64k时不至于出问题

    fromwhere用于确定偏移量计算的起始位置,它的可能取值有3种,SEEK_SET或0,代表文件开始处,SEEK_CUR或1,代表文件当前位置,SEEK_END或2,代表文件结尾处,

    通过指定fromwork和offset的值,可使位置指针移动到文件的任意位置,从而实现文件的随机读取,如果函数fseek()调用成功,则返回0值,否则返回非0值

    两种特殊使用方式:

    将读写位置移动到文件开头:fseek(FILE *stream,0,SEEK_SET);
      将读写位置移动到文件尾:fseek(FILE *stream,0,0SEEK_END);

    (fseek() 一般用于二进制文件,在文本文件中由于要进行转换,计算的位置有时会出错)

    • 指针指向文件首字节 - rewind()

    void rewind(FILE *fp)

    • 读取当前文件指针的位置 - ftell()

    long ftell(FILE *fp
    ftell获得该文件指示符此时的偏移量,如果已经是在文件末尾,故能获得文件的大小
    需要注意的是,当用err = fopen_s(&fp, “E:\ww.txt”, “a+”);打开文件后文件指针移到文件末尾,此时文件起始位置还是为文件头部并不是文件末尾)

    • 测试给定流 stream 的错误标识符 - ferror()

    int ferror(FILE *stream)

    • 检测流上的文件结束符 - feof()

    int feof(FILE *fp)
    计算机突然死机或掉电,数据就会丢失,永远也找不回来,再如缓冲区被写入无用的数据时,如果不清除,其后的文件读操作都首先要读取这些无用的数据
    为了解决这个问题C语言提供了fflush()函数

    • 清除缓冲区的内容 - fflush()

    int fflush(FILE *fp)

    • 取当前文件指针位置 - ftell()

    long ftell(FILE *fp)
    (函数ftell()用于相对于文件起始位置的字节偏移量来表示返回的当前位置指针)

    fflush(stdin);刷新标准输入缓冲区,把输入缓冲区里的东西丢弃[非标准]

    fflush(stdout);刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上

    fflush(NULL);将清洗所有的输出流

    由于ANSIC规定函数fflush()处理输出数据流、确保输出缓冲区中的内容文件,但并未对清理输入缓冲区作出任何规定,只是部分编译器增加了此项功能,因此使用fflush(stdin)来清除缓冲区的内容,可能会带来移植性的问题

    (fflush on input stream is an extension to the C standard(fflush 操作输入流是对 C 标准的扩充))

    使用 fflush(stdin)是不正确的,至少是移植性不好的,因为那样的代码在一些环境下可能正常工作,但在另一些环境下则会出错,这导致程序不可移植,所以只能在写入文件的时候使用fflush

    • 文件此时的偏移量之间的大小-lseek()

    例如:
    long length = lseek(fd,0,SEEK_END);//回到文件的末尾,故返回的是文件的大小

    标准输入/输出重定向

    实际上,对于终端设备,系统会自动打开3个标准文件:标准输入、标准输出和标准错误输出,相应的,系统定义了3个特别的文件指针常数:stdin、stdout、stderr,

    分别指向标准输入、标准输出和标准错误文件,这3个文件都以标准终端设备作为输入/输出对象,在默认情况下,标准输入设备时键盘,标注输出设备是屏幕

    fprintf()是printf()的文件操作版,二者的差别在于fprintf()多了一个FILE *类型的参数fp,如果为其提供的第1个参数时stdout,那么它就和printf()完全一样,

    同理可推广到fputc()和putchar()等其他函数,

    例如:

    putchar(c);和fputc(c,stdout);等价

    getchar();和fgetc(stdin);等价

    puts(str)和fputs(str,stdout);等价

    但函数fgets()与gets()不同,从如下函数原型可知其区别在于fgets()还多了一个参数size

    char *fgets(char *s,int size,FILE *stream);

    char *gets(char *s);

    fgets()用其第二个参数size来说明输入缓冲区的大小,使读入的字符数不能超过限定缓冲区的大小,从而达到防止缓冲区溢出攻击的目的,

    假如已定义一个有32字节的缓冲区buffer[32],那么在下面两条读字符串的语句中,后者的安全性更高

    gets(buffer);

    fgets(buffer,sizeof(buffer),stdin);//安全性更高

    虽然系统隐含的I/O是指终端设备,但其实标准输入和标准输出是可以重新定向的,操作系统可以重新定向它们到其他文件或具有文件属性的设备,只有标准错误输出不能进行一般的输出重定向,

    例如,在没有显示器的主机上,把标准输出定向到打印机,各种程序不用做任何改变,输出内容就自动从打印机输出

    这里用“<”表示输入重定向,用“>”表示输出重定向,例如:假设exefile时可执行程序文件名,执行该程序时,需要输入数据,现在如果要从文件file.in中读取数据,而非键盘输入,

    那么在DOS命令提示符下,只要键入如下命令行即可

    C:\exefile<file.in

    于是exefile的标准输入就被“<”重定向到了file.in,c此时程序exefile只会专心致志地从文件file.in中读取数据,而不再理会你此后按下的任何一个按键,

    再如,若键入如下命令行

    C:\exefile>file.out

    于是,exefile的标准输出就被“>”重定向到了文件file.out中,此时程序exefile的所有输出内容都被输出到了文件file.out中,而屏幕上没有任何显示

    文件随机读写

    在移动位置指针之后,就可以用前面介绍的任何一种读写函数进行读写了。由于是二进制文件,因此常用 fread() 和 fwrite() 读写。

    //【示例】从键盘输入三组学生信息,保存到文件中,然后读取第二个学生的信息:
    #include<stdio.h>
    #define N 3
    struct stu{
        char name[10]; //姓名
        int num;  //学号
        int age;  //年龄
        float score;  //成绩
    }boys[N], boy, *pboys;
    int main(){
        FILE *fp;
        int i;
        pboys = boys;
        if( (fp=fopen("d:\\demo.txt", "wb+")) == NULL ){
            printf("Cannot open file, press any key to exit!\n");
            getch();
            exit(1);
        }
        printf("Input data:\n");
        for(i=0; i<N; i++,pboys++){
            scanf("%s %d %d %f", pboys->name, &pboys->num, &pboys->age, &pboys->score);
        }
        fwrite(boys, sizeof(struct stu), N, fp);  //写入三条学生信息
        fseek(fp, sizeof(struct stu), SEEK_SET);  //移动位置指针
        fread(&boy, sizeof(struct stu), 1, fp);  //读取一条学生信息
        printf("%s  %d  %d %f\n", boy.name, boy.num, boy.age, boy.score);
        fclose(fp);
        return 0;
    }
    

    获取一个文件的大小

    1. 使用fopen打开文件,使用fseek和ftell来获取文件的大小

     FILE  *file = fopen(char *filename,"w+");
     if(file == NULL)
     {
     	printf("打开文件失败");
     	return -1;
     }
     fseek(file,0,SEEK_END);//定位到文件的最后面
     long length  = ftell(file);//ftell获得该文件指示符此时的偏移量,此时已经是在文件末尾,故能获得文件的大小
     printf("%ld",length);
    
    1. 如果使用open打开文件,使用lseek来获取文件的大小

    int fd = open(char *filename,int falgs);//这里的参数自行设置
    	if(fd == -1)
    	{
    		printf("文件打开失败\n");
    		return -1;
    	}
    	//lseek函数成功的话,返回的是从文件开始到文件此时的偏移量之间的大小
    	long length = lseek(fd,0,SEEK_END);//回到文件的末尾,故返回的是文件的大小
    	printf("%ld\n",length);//输出这个文件的大小
    	return  0;
    
    1. 使用stat.h

    #include <sys/stat.h>
    #include <stdio.h>
    int main(int argc, char *args[]){
        struct stat sb = {0}; 
        int fd = open("./filename.txt",O_RDONLY);
        fstat(fd,&sb);
    	printf("%d",sb.st_size);//获取文件的长度
    }
    
    1. 只使用stdio

    #include <stdio.h>
    long get_file_size(char *file_name){
        FILE *fp = NULL;
        if((fp = fopen(file_name,"r")) == NULL){
            printf("获取文件失败");
            return -1;
        }
        //从文件末尾偏移,偏移0位
        fseek(fp,0,SEEK_END);
        long file_size = ftell(fp);//ftell()存储当前文件描述符的读取的偏移位置,这里就是文件末尾
        fclose(fp);
        return file_size;
    }
    int main(int argc, char *args[]){
        printf("%ld",get_file_size("./filename.txt"));
    }
    

    C语言的四种拷贝函数

    一、复制字符串 - strcpy()

    char*strcpy(char *dest, const char *src);
    【参数】dest 为目标字符串指针,src为源字符串指针。
    src 和 dest 所指的内存区域不能重叠,且 dest必须有足够的空间放置 src 所包含的字符串(包含结束符NULL)。
    【返回值】成功执行后返回目标数组指针 dest。
    注意:如果参数 dest 所指的内存空间不够大,可能会造成缓冲溢出(bufferOverflow)的错误情况,在编写程序时需要特别留意,或者用strncpy()来取代。

    //例:
    #include <stdio.h>
    #include <string.h>
    
    int  main  ()
    {
            char  str1[]= "Sample string";
            char  str2[ 40];
            char  str3[ 40];
            strcpy  (str2,str1);
            strcpy  (str3, "copy successful");
            printf  ( "str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
            return  0;
    }
    

    运行结果:
    str1: Sample string
    str2: Sample string
    str3: copy successful

    二、复制内存 - memcpy()

    void *memcpy ( void * dest, const void * src, size_t num );
    memcpy() 会复制 src 所指的内存内容的前 num 个字节到 dest所指的内存地址上。

    memcpy()并不关心被复制的数据类型,只是逐字节地进行复制,这给函数的使用带来了很大的灵活性,可以面向任何数据类型进行复制。

    //例:
    #include  <string,h>
    #include  <stdio.h>
    #include  <stdlib.h>
    
    #define  N  ( 10)
    
    int  main()
    {
            char  *p1  =  "abcde";
            char  *p2  =  ( char  *)malloc( sizeof( char)  *  N);
            char  *p3  =  ( char  *)memcpy(p2,  p1,  N);
            printf( "p2 = %s\np3 = %s\n",  p2,  p3);
    
            free(p2);
            p2  =  NULL;
            p3  =  NULL;
            system( "pause");
            return  0;
    }
    

    运行结果:
    p2 = abcde
    p3 = abcde

    三、复制内存内容 - memmove()

    void *memmove(void *dest, const void *src, size_t num);
    memmove() 与 memcpy() 类似都是用来复制 src所指的内存内容前 num 个字节到 dest 所指的地址上。不同的是,memmove() 更为灵活,当src 和 dest所指的内存区域重叠时,memmove() 仍然可以正确的处理,不过执行效率上会比使用 memcpy()略慢些。

    //例:
    #include  <stdio.h>
    #include  <stdlib.h>
    #include  <string.h>
    
    int  main  ()
    {
            char  str[]  =  "memmove can be very useful......";
            memmove  (str+ 20,str+ 15, 11);
            puts  (str);
    
            system( "pause");
            return  0;
    }
    

    运行结果:
    memmove can be very very useful.

    四、复制字符串的前n个字符 - strncpy()

    char *strncpy(char *dest, const char *src, size_t n);
    【参数说明】dest 为目标字符串指针,src 为源字符串指针。

    注意:src 和 dest 所指的内存区域不能重叠,且 dest必须有足够的空间放置n个字符。使用strncpy()最安全方式是使n等于strlen(src)+1,即拷贝整个字符串,同时将’\0’追加到dest。

    //例:
    #include <stdio.h>
    #include  <string.h>
    int  main( void)
    {
            char  dest1[ 20];
            char  src1[]  =  "abc";
            int  n1  =  3;
    
            char  dest2[ 20]  =  "********************";
            char  src2[]  =  "abcxyz";
            int  n2  =  strlen(src2)  +  1;
    
            char  dest3[ 100]  =  "http://see.xidian.edu.cn/cpp/shell/";
            char  src3[ 6]  =  "abcxyz";    // 没有'\0'
            int  n3  =  20;
    
            char  dest4[ 100]  =  "http://see.xidian.edu.cn/cpp/u/yuanma/";
            char  src4[]  =  "abc\0defghigk";
            int  n4  =  strlen(src3);
    
            strncpy(dest1,  src1,  n1);    // n1小于strlen(str1)+1,不会追加'\0'
            strncpy(dest2,  src2,  n2);    // n2等于strlen(str2)+1,恰好可以把src2末尾的'\0'拷贝到dest2
            strncpy(dest3,  src3,  n3);    // n3大于strlen(str3)+1,循环拷贝str3
            strncpy(dest4,  src4,  n4);    // src4中间出现'\0'
    
            printf( "dest1=%s\n",  dest1);
            printf( "dest2=%s, dest2[15]=%c\n",  dest2,  dest2[ 10]);
            printf( "dest3=%s\n",  dest3);
            printf( "dest4=%s, dest4[6]=%d, dest4[20]=%d, dest4[90]=%d\n",  dest4,  dest4[ 6],  dest4[ 20],  dest4[ 90]);
    
            return  0;
    }
    

    C语言插入、删除、更改文件内容

    顺序文件的存储结构决定了它能够高效读取内容,但不能够随意插入、删除和修改内容。例如在文件开头插入100个字节的数据,那么原来文件的所有内容都要向后移动100个字节,这不仅是非常低效的操作,而且还可能覆盖其他文件。因此C语言没有提供插入、删除、修改文件内容的函数,要想实现这些功能,只能自己编写函数。

    以插入数据为例,假设原来文件的大小为 1000 字节,现在要求在500字节处插入用户输入的字符串,那么可以这样来实现:
    (1)创建一个临时文件,将后面500字节的内容复制到临时文件;
    (2)将原来文件的内部指针调整到500字节处,写入字符串;
    (3)再将临时文件中的内容写入到原来的文件(假设字符串的长度为100,那么此时文件内部指针在600字节处)。
    删除数据时,也是类似的思路。假设原来文件大小为1000字节,名称为 demo.mp4,现在要求在500字节处往后删除100字节的数据,那么可以这样来实现:
    (1)创建一个临时文件,先将前500字节的数据复制到临时文件,再将600字节之后的所有内容复制到临时文件;
    (2)删除原来的文件,并创建一个新文件,命名为 demo.mp4;
    (3)将临时文件中的所有数据复制到 demo.mp4。

    修改数据时,如果新数据和旧数据长度相同,那么设置好内部指针,直接写入即可;如果新数据比旧数据长,相当于增加新内容,思路和插入数据类似;如果新数据比旧数据短,相当于减少内容,思路和删除数据类似。实际开发中,我们往往会保持新旧数据长度一致,以减少编程的工作量,所以我们不再讨论新旧数据长度不同的情况。

    文件复制

    
    /**
    * 文件复制函数
    * @param fSource 要复制的原文件
    * @param offsetSource 原文件的位置偏移(相对文件开头),也就是从哪里开始复制
    * @param len 要复制的内容长度,小于0表示复制offsetSource后边的所有内容
    * @param fTarget 目标文件,也就是将文件复制到哪里
    * @param offsetTarget 目标文件的位置偏移,也就是复制到目标文件的什么位置
    * @return 成功复制的字节数
    **/
    long fcopy(FILE *fSource, long offsetSource, long len, FILE *fTarget, long offsetTarget)
    {
    	int bufferLen = 1024*4; // 缓冲区长度
    	char *buffer = (char*)malloc(bufferLen); // 开辟缓存
    	int readCount; // 每次调用fread()读取的字节数
    	long nBytes = 0; //总共复制了多少个字节
    	int n = 0; //需要调用多少次fread()函数
    	int i; //循环控制变量
     
    	fseek(fSource, offsetSource, SEEK_SET);
    	fseek(fTarget, offsetTarget, SEEK_SET);
     
    	if(len<0){ //复制所有内容
    		while( (readCount=fread(buffer, 1, bufferLen, fSource)) > 0 ){
    			nBytes += readCount;
    			fwrite(buffer, readCount, 1, fTarget);
    		}
    	}else{ //复制len个字节的内容
    		n = (int)ceil((double)((double)len/bufferLen));
    		for(i=1; i<=n; i++){
    			if(len-nBytes < bufferLen){ bufferLen = len-nBytes; }
    			readCount = fread(buffer, 1, bufferLen, fSource);
    			fwrite(buffer, readCount, 1, fTarget);
    			nBytes += readCount;
    		}
    	}
    	fflush(fTarget);
    	free(buffer);
    	return nBytes;
    }
    原文链接:https://blog.csdn.net/Neutionwei/article/details/109394920
    

    文件内容插入函数

    /**
    * 向文件中插入内容
    * @param fp 要插入内容的文件
    * @param buffer 缓冲区,也就是要插入的内容
    * @param offset 偏移量(相对文件开头),也就是从哪里开始插入
    * @param len 要插入的内容长度
    * @return 成功插入的字节数
    **/
    int finsert(FILE *fp, long offset, void *buffer, int len)
    {
    	long fileSize = fsize(fp);
    	FILE *fpTemp; //临时文件
     
    	if(offset>fileSize || offset<0 || len<0){ //插入错误
    		return -1;
    	}
     
    	if(offset == fileSize){ //在文件末尾插入
    		fseek(fp, offset, SEEK_SET);
    		if(!fwrite(buffer, len, 1, fp)){
    			return -1;
    		}
    	}
     
    	if(offset < fileSize){ //从开头或者中间位置插入
    		fpTemp = tmpfile();
    		fcopy(fp, 0, offset, fpTemp, 0);
    		fwrite(buffer, len, 1, fpTemp);
    		fcopy(fp, offset, -1, fpTemp, offset+len);
    		freopen(FILENAME, "wb+", fp );
    		fcopy(fpTemp, 0, -1, fp, 0);
    		fclose(fpTemp);
    	}
     
    	return 0;
    	//fsize() 是在《 83-C语言获取文件大小(长度)》自定义的函数,用来获取文件大小(以字节计)。
    	//判断数据的插入位置,如果是在文件末尾,就非常简单,直接用 fwrite() 写入即可。
    //如果从文件开头或中间插入,就得创建临时文件。
    //tmpfile() 函数用来创建一个临时的二进制文件,可以读取和写入数据,相当于 fopen() 函数以"wb+"方式打开文件。该临时文件不会和当前已存在的任何文件重名,并且会在调用 fclose() 后或程序结束后自动删除。
    }
    

    文件内容删除函数

    int fdelete(FILE *fp, long offset, int len)
    {
    	long fileSize = getFileSize(fp);
    	FILE *fpTemp;
     
    	if(offset>fileSize || offset<0 || len<0){ //错误
    		return -1;
    	}
     
    	fpTemp = tmpfile();
    	fcopy(fp, 0, offset, fpTemp, 0); //将前offset字节的数据复制到临时文件
    	fcopy(fp, offset+len, -1, fpTemp, offset); //将offset+len之后的所有内容都复制到临时文件
    	freopen(FILENAME, "wb+", fp ); //重新打开文件
    	fcopy(fpTemp, 0, -1, fp, 0);
     
    	fclose(fpTemp);
    	return 0;
    }
    //freopen() 以"w+"方式打开文件时,如果有同名的文件存在,那么先将文件内容删除,作为一个新文件对待。 
    

    文件操作补充

    因为在Microsoft Visual C++ 2010 Express中使用fopen,fscanf等函数编译器会显示警告,

    This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

    所有在文件操作时将改用fopen_s、fscanf_s等函数

    • fopen_s()函数

    函数原型:errno_t fopen_s( FILE** pFile, const char *filename, const char *mode );

    pFile----文件指针将接收到打开文件指针指向的指针

    infilename----文件名
    
    mode----允许访问的类型
    

    fopen_s()打开文件成功返回0值,否则返回非0值

    须定义另外一个变量errno_t err

    • fscanf_s()函数

    函数原型:fscanf_s(Inout FILE * _File, In_z Scanf_s_format_string const char * _Format, …);

    fscanf_s和fscanf的区别

    在使用形式上fopen_s()比fopen()多使用了一个参数,第四个参数是字节数(注意长度(strlen)和字节数(sizeof)的区别)

    展开全文
  • #include<stdio.h> #include<string.h> int main(){ char str[100];... printf("请输入字符串:"); gets(str); if((fp=fopen("test.txt","w"))==NULL){ printf("error!\n"); exit(...
    #include<stdio.h>
    #include<string.h>
    int main(){
    	char str[100];
    	FILE *fp;
    	int i,j,k;
    	printf("请输入字符串:");
    	gets(str);
    	if((fp=fopen("test.txt","w"))==NULL){
    		printf("error!\n");
    		exit(0);
    	}
    	for(i=0;i<strlen(str);i++)
    		if(str[i]>='a'&&str[i]<='z')
    			str[i]-=32;
    	puts(str);
    	fputs(str,fp);
    	fclose(fp);
    
    }
    
    展开全文
  • 从缓冲区把数据发送屏幕或文件称为刷新缓冲区,C标准规定:当缓冲区被填满,遇到'\n'或需要输入时刷新缓冲区 旧式编译器遇到scanf()也不会强行刷新缓冲区,程序会停在那里不显示任何提示内容,等待用户输入数据 在这种...

    1.printf()何时发送内容到屏幕:

    printf()会先把要输出的内容发送到1个叫缓冲区(Buffer)的中间存储区域,然后缓冲区中的内容再不断被发送到屏幕上
    从缓冲区把数据发送到屏幕或文件称为刷新缓冲区,C标准规定:当缓冲区被填满,遇到'\n'或需要输入时刷新缓冲区
    旧式编译器遇到scanf()也不会强行刷新缓冲区,程序会停在那里不显示任何提示内容,等待用户输入数据
    在这种情况下,可以使用'\n'来刷新缓冲区,但这会导致光标移动到下1行起始位置;还可以用fflush()刷新缓冲区
    

    2.空字符(Null Character):

    C语言使用字符数组来存储字符串,字符串必须以'\0'结尾(会自动补上)
    '\0'是空字符,是非输出控制符,其ASCII码是0
    由于必须以'\0'结尾,字符数组的长度必须至少比要存储的字符串的长度多1
    比如有10个字符的字符串必须存储在长度至少为11的字符数组中
    

    在这里插入图片描述
    3.标准化输入输出函数的标准:

    scanf()printf()被称为标准化输入/输出函数,或简称I/O函数
    最初,C把输入/输出的实行留给了编译器的作者,所以不同编译器提供的I/O函数可能有区别
    不过,C90/C99规定了I/O函数的标准版本
    

    4.转换说明修饰符:

    输出控制符被称为转换说明(Conversion Specification),其中%后面的符号称为转换字符
    通过在%和转换字符间插入转换说明修饰符来修饰基本的转换说明
    
    //注意:
    1.所有下述修饰符都是C99新增的
    2.如果要插入多个修饰符,插入顺序应和下面列出的顺序相同
    
    ①标记
      -:将待打印项左对齐,即从字段的左侧开始打印该项."%-20s"
        //默认是最右侧,左侧用前导空格填充
      +:显示值的符号(如果有)."%+6.2f"
      空格:有符号项若为正,则在前面显示前导空格(不显示符号);若为负,则显示负号并覆盖空格."% 6.2f"
      #:把结果转换为另1种形式
        如果是%o格式,则以0开始
        如果是%x/%X格式,则以0x/0X开始
        对于所有浮点格式,保证了即使后面没有任何数字,也打印1个小数点字符
        对于%g/%G格式,防止结果结尾的0被删除
        如"%#o","%#8.0f","%+#10.3e","%#%g"
      0:对于数值格式.用前导0代替空格填充字段宽度
        对于整数格式,如果出现负号标记或指定了精度,则忽略负号
        如"%010d","%08.3f"
    ②数字:指定最小字段宽度."%4d".数字:指定精度
      对于%e/%E/%f格式,表示小数点后的位数
      对于%g/%G格式,表示有效数字最大位数
      对于%s格式,表示待打印字符的最大数量
      对于整数格式,表示待打印数字的最小位数
      如有必要,使用前导0来达到这个位数
      只使用.相当于.0"%5.2f","%.f"(相当于"%.0f")
    
    //指定字段宽度的一些用法:
    float distance=10.22;
    printf("Count Beppo ran %.2f miles in 3 hours.\n",distance);
    //结果:Count Beppo ran 10.22 miles in 3 hours.
    //指定比字段宽度更小的宽度,以防止出现多余的空格
    printf("Count Beppo ran %10.2f miles in 3 hours.\n",distance);
    //结果:Count Beppo ran      10.22 miles in 3 hours.
    

    5.size_t与ptrdiff_t类型:

    标准只规定了sizeof()的返回值应该是无符号整数,在不同的实现中,可以是unsigned/unsigned long/unsigned long long
    如果要打印sizeof()的返回值,根据环境,需要使用%u/%lu/%llu,这意味着移植程序时需要进行修改,为此,C提供了更好的类型
    stddef.h把size_t定义成sizeof()返回的类型,称为底层类型(Underlying Type),printf()使用z修怖符表示打印相应类型
    同样,C还定义了ptrdiff_t类型和t修饰符来表示系统使用的指针差值的底层有符号整数类型
    

    6.输出时类型不匹配的补充:

    //混淆整型/字符类型:
    
    short a=336;
    printf("%c\n",a);//结果:P
    //超出255时,%c只会查看最后1个字节,并将该字节翻译为字符并显示(见下图)
    //即该值被解释成"以256为模"(modulo 256),相当于除以256后取余数,再把余数翻译成字符
    
    short num=336,mnum=-336;
    printf("%hd,%hu,%hd,%hu\n",num,num,mnum,mnum);//结果:336,336,-336,65200
    //336的补码表示为336;而-336的补码表示为65200,作为unsigned short时被解释为65200
    
    int big=65618;
    printf("%d,%hd\n",big,big);//结果:65618,82
    //这时也进行了求模运算,只查看最后2B
    

    在这里插入图片描述

    //混淆整型与浮点型:
    
    float n1=3.0;
    double n2=3.0;
    long n3=2000000000,n4=1234567890;
    printf("%.1e,%.1e,%.1e,%.1e\n",n1,n2,n3,n4);//结果:3.0e+000,3.0e+000,9.9e-315,-1.$e+000
    //%e让printf()认为n3是double,因此除了查看n3的4B,还需要查看相邻的4B
    //让后将这8B分别解释为小数部分和指数部分
    315,-1.$e+000
    printf("%ld,%ld,%ld,%ld\n",n1,n2,n3,n4);//结果:0,0,2000000000,1234567890
    //不能用%ld输出浮点型
    //注意:再某些环境下,这种情况下n3/n4也会输出错误
    

    7.printf()输出长字符串:

    //方法1:使用多个printf(),除最后1个外,不要加'\n'
    printf("My name is John Smith,");
    printf("I am 10 years old.\n");
    //结果:My name is John Smith,I am 10 years old.
    
    //方法2:使用字符串连接
      //多个str间如果用空白隔开,会被视为1个str
    printf("Here is another way"
    "to print "   "a long str.\n");
    //结果:Here is another wayto print a long str.
    
    //方法3:使用反斜杠(\)来断行
      //下1行必须从该行的最左侧开始,如果缩进,缩进所产生的空白也会被视为字符串的一部分
    int main(void) {
    	printf("Third way to \
    print a long str.\n");
    	return 0;
    }
    //结果:Third way to print a long str.
    

    8.*修饰符:

    //printf()的*修饰符:
    如果不想预先指定字段宽度,而想通过变量指定,使用*修饰符
    int a=5;
    printf("%*d\n",a,a);//结果:    5
    
    //scanf()的*修饰符:
    会跳过使用*修饰符的输入项,将下1个输入项赋给变量
      //需要读取文件的特定列时很有用
    int a;
    scanf("%*d,%d",&a);//输入:3,2
    printf("%d\n",a);//结果:2
    

    9.输入数组元素:

    int index,score[3];
    for (index=0;index<3;index++) {
        printf("input score:");
        scanf("%d",&score[index]);
    }
    printf("output all score:");
    for (index=0;index<3;index++) {
        printf("%d,",score[index]);
    }
    //结果①:
    //input score:9
    //input score:2
    //input score:4
    //output all score:9,2,4,
    //结果②:
    //input score:5 2 9
    //input score:input score:output all score:5,2,9,
    //结果③:
    //input score:4 7 9 3 2
    //input score:input score:output all score:4,7,9,
    
    展开全文
  • 文件结尾,C不关心操作系统是如何检测文件结尾,C在检测到文件结尾之后返回EOF。getchar();——从输入缓冲区读取一个字符,不管字符是什么,都读取。putchar()——打印一个字符,没有换行符。注意put...

    0.getchar()、putchar()

    输入缓冲区,键盘输入是“行缓冲”遇到一个换行符的时候清空缓冲区。

    标准流,stdin和stdout,是标准的输入输出流,键盘输入就是用的stdin。

    文件结尾,C不关心操作系统是如何检测文件结尾,C在检测到文件结尾之后返回EOF。

    getchar();——从输入缓冲区读取一个字符,不管字符是什么,都读取。

    putchar()——打印一个字符,没有换行符。注意putchar只打印一个字符,换行符也算一个字符,想要打印换行符应该是putchat('

    ')。

    跳过剩余的char:

    while(getchar()!='')

    {continue;

    }

    1.scanf()

    返回值——返回正确读取的个数int型。

    这里注意:如果scanf中%d是连着写的如“%d%d%d”,在输入数据时,数据之间不可以用逗号分隔,只能用空白字符(空格或tab键或者回车键)分隔——“2 (空格)3(tab) 4” 或 “2(tab)3(回车)4”等。若是“%d,%d,%d”,则在输入数据时需要加“,”(如果是“.”呢么要在输入数据的时候加“.”)如“2,3,4”。

    函数测试:用户混合输入int数据和字符串数据。注意这里两个输入是用的英文句号"."分开的,所以输入的时候两个数据应该用英文句号隔开否则就不算正确输入。

    函数设计思路:用户输入两种类型的数据:int和字符串,当用户输入的类型错误的时候提示用户错误并请求再次输入。

    #include

    int main(void)

    {intage;char name[20];

    puts("please enter your age and your name");while(scanf("%d.%s",&age,name) != 2)

    {while(getchar()!='')//清空输入缓冲区

    {continue;

    }

    puts("age and name,please anain!");

    }while(getchar()!='')//清空输入缓冲区

    {continue;

    }

    printf("hi %s,",name);

    printf("you are %d years old",age);

    getchar();//等待

    return 0;

    }

    程序中有两个专门清空缓冲区的while循环,(1)用户输入错误的时候输入缓冲区域会留下错误输入的数据,这些数据会连同下一次输入一起作为输入数据,因此必须要清除掉。(2)如果用户输入正确,由于scanf()函数读取之后会留下换行符'

    '在输入缓冲区中,同样影响下一次输入,因此也要清除掉,其实这里最好用一个getchar(),用getchar()效率更高,我这是偷懒复制的。

    2.printf()

    #include

    intmain(void)

    {inti, j;

    i=10;

    j=20;

    printf("i=%d;j=%d", i, j);return 0;

    }

    注意printf()不输出换行符,想要换行需要这样:

    printf("i=%d;j=%d", i, j);

    3.gets()

    读取输入缓冲区中所有的字符,遇到换行符

    的时候停止,并且把

    丢弃然后在读入数据的尾部加上 。

    gets()读取成功之后返回字符串的指针,如果读取失败则返回NULL。

    用gets的好处是不用和用scanf一样在后边跟着一个清理

    的getchar()。如下:

    #include

    int main(void)

    {char name[20];

    puts("please enter your name");while(gets(name)==NULL)

    {

    puts("name,please anain!");

    }

    printf("hi %s",name);

    getchar();//等待

    return 0;

    }

    但是gets()函数步检查容量是否超过参数的容量,特别容易发生溢出,上面的例子name[]容量只有20,一旦用户输入超过20个字符的容量,name数组后面的内存数据就会被覆盖,因此这是非常不安全的。

    C11标准中已经删除了gets()函数,用gets_s()函数代替。

    4.gets_s()

    大写的尴尬。

    9d78098bd799b7d00ae83ba2f57e0870.png

    5.fgets()

    fgets()函数有三个参数,第一个是读取的字符串要写入的变量,第二个是读取多少个字符(n-1个,例如第二个参数写3那么函数读取2个字符,字符数据大于2就会报错),第三个参数是数据源,如果是从键盘读取那么就是stdin(标准输入流)。

    fgets()函数不会把

    丢掉并在字符串尾部添加 ,而是原封不动的把所有东西全部写入到变量中(

    也是)。

    与gets()一样fgets()也是返回输入字符串指针(成功读取的话),读取失败会返回NULL。

    把gets()函数改成如下;

    #include

    int main(void)

    {char name[20];

    puts("please enter your name");while(fgets(name,20,stdin)==NULL)

    {

    puts("name,please anain!");

    }

    printf("hi %s,how old are you?",name);

    getchar();//等待

    return 0;

    }

    就会有如下输出:

    548c1078f92f3012cd4d2d7106979819.png

    很尴尬,因为fgets()函数连同

    一起读取到了数组name中,输出的时候也一起输出了,所以“,how old are you ?”就被换行了。

    6.puts()

    puts()函数使用很简单,他只有一个参数,字符串地址。

    与printf()不同,puts()函数自动添加一个

    到字符串尾部,也就是说:自动换行。

    还是看上面的代码:

    #include

    int main(void)

    {char name[20];

    puts("please enter your name");while(fgets(name,20,stdin)==NULL)

    {

    puts("name,please anain!");

    }

    printf("hi %s,how old are you?",name);

    getchar();//等待

    return 0;

    }

    注意main()函数内的第二行,尾部并没有换行符

    。但是输出的时候:

    88d05b171e00885ef666894b7fb8fea0.png

    自动换行了。

    注意puts()的参数是一个地址,如果想要输出name中的字符串的话:

    puts(name);

    注意:puts()遇到空字符 就会停止输出。

    如下:

    0779ff61a911e85b78c046f183b882ef.png

    d没有了。大写的尴尬!!!

    但这还不是最严重的,puts()只有遇到空字符 才会结束输出,那么,如果字符串中没有空字符呢?

    这时puts就不知道应该在哪里停止输出了,所以会造成程序的不稳定,如下我重新修改了下数组数据,删掉了 :

    28a10c95b6217902c9f51db6fbbccf02.png

    程序在e后面多了一个方框。

    注意如果字符串中没有 ,printf也会蒙圈的:

    929daa54cd57b234045672334f0a404f.png

    7.fputs()

    fputs()需要指定输出流:

    且fputs()并不会像puts()一样自动添加换行符。

    f216a09d324a3c25a39c6db9b3ec7708.png

    注意:如果name数组最后一个元素不是 的话还是会出错的。

    8.总结

    gets()与put()搭配,输入的时候把

    替换成 (其实是去掉之后再加上,意思差不多),输出的时候添加

    fgets()与fput()搭配,输入的时候原封不动的把

    读取,输出的时候不自动添加

    参考:https://www.cnblogs.com/qingergege/p/5925811.html

    展开全文
  • C语言字符串排序

    千次阅读 2020-03-29 12:48:44
    函数 ReadDat()实现从文件 IN.DAT 中读取一篇英文文章存入到字符串数组 xx 中,请编制函数 SortCharD(),其函数的...writeDat()把结果 xx 输出到文件 OUT2.DAT 中。 例:原文:dAe,BfC CCbbAA 结果:fedCBA bbCC...
  • fwrite fread fscanf fprintf 都是属于C函数用于文件读写,前两者对二进制文件读写,后... fprintf() 格式化的写入,写入到文件中    10:9.9,xxxx,1.jpg#    fprintf(fp,"%d:%.2f,%s,%s#",10,...
  • #include<stdio.h> int main(){ FILE *fp; char s[50]; int i; if((fp=fopen("test1.dat","w"))==NULL){ printf("error!... printf("请输入字符串:"); gets(s); fprintf(fp,"%s",s); fclose...
  • C语言中没有单独定义字符串的变量类型,而是采用字符数组的形式来定义及存储。 字符串与字符数组一个很大的区别是字符串以字符‘\0’来结尾,因此采用for循环计算字符数组的长度时,常常会把字符‘\0’统计结果...
  • #include<stdio.h>...printf("请输入字符串:\n"); for (i = 0; i < 20; i++) { gets(str[i]); } if ((fopen_s(&fp,"C:\Users\Reol\source\repos\String binary file\test.txt",
  • 很多时候我们需要写入数据到文件中时都觉得很困扰,因为格式乱七八槽的,可读性太差了,于是我们就想有没有什么函数可以格式化的从文件中输入和输出呢,还真有。下面我将讲解一下fscanf和fprintf与sprintf()的强大...
  • 请编制函数 jsSort(),其函数的功能是:以行为单位对字符串按给定的条件进 行排序,排序后的结果仍按行重新存入字符串数组 xx 中,后调用函数 WriteDat()把结果 xx 输出到文件 out.dat 中。 条件:从字符串中间...
  • #include<stdio.h> #include<stdlib.h> #include<string.h> #define N 20 int main() ...//为了易于理解,以下分为三个对文件操作方式 ... printf("//创建一个文件,将字符输入到文件中//\n"); if(
  • 在一个文本文件查找输入的字符串输出查找结果,是否匹配,匹配了几次,在第几行第几个字符匹配的. 主要就是,匹配位置这里有一些问题.
  • C语言练习】字符串合并排序

    千次阅读 2020-06-10 00:56:08
    字符串中字符排序:按照题目要求的输入输出样例编写,输入或粘贴程序代码,勿以附件形式提交代码文件。 【问题描述】 假定有两个由小写字母构成的字符串str_1、str_2,编写程序,将两个字符串合并至str_1中(不使用...
  • 一、字符串的输入和输出函数-集锦 ???? 1 - gets和puts gets函数------格式char *gets(char *s); 1、可以接收空格,直到出现换行符或读到文件结尾为止。 char arr[1]; gets(arr); printf("%s", arr); // 输入...
  • 本文介绍了在Linux系统中,使用C语言中的popen执行了一个终端命令后,将终端输出重定向一个文件流中,再使用fgets获取终端输出的每一行,并使用strstr提取其中的关键字符串,然后使用sscanf获取到字符串后面的...
  • #include <stdio.h>...10.4 从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存。输入的字符串以"!"结束。 */ FILE *fp; char filename[20];//存储文...
  • C语言 输出

    千次阅读 2017-08-24 20:40:33
    用fputs()把一个字符串写入到文件中 int fputs (char string, FILE fp) ; 功能:把字符串string写入到文件fp中 若fp为stdout,则为向屏幕输出。 printf int printf ( char const format, …… ) ; int ...
  • //上边的h一到字符串的结尾q++指向下一个地址,可还有下一个地址吗? } a[i] = '\0'; } main() { char s[81],*t, *f; void NONO ( ); printf("Enter a string:\n");gets(s); t=f=s; while(*t)t++; ...
  • scanf("%s",x) 返回值:成功读取的变量个数,如果读取到文件末尾或出错则返回EOF。 特征:忽略输入开头的所有空白符号,包括空格,回车,制表,字符串间以空白符号区分,丢弃读入的空白符号,不会存储到字符串变量中...
  • C语言考试题 移动字符串位置

    千次阅读 2013-03-29 20:00:13
    程序test.C的功能是:把s字符串中的所有字符左移一个位置,串中的第一个字符移最后。请考生编写函数chg(char*s)实现程序要求,最后调用函数readwriteDAT()把结果输出到0ut.dat文件中。 ...
  • //例10.3 写入字符串排序后输入指定文件 #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 3 int main() { FILE* fp; char str[3][30], temp[30]; int i, j, k; for ...
  • 0x01从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件"test.dat"中保存。输入的字符串以"!"结束。 0x02有两个磁盘文件“A.dat”和“B.dat”,各存放一行字母,要求把这两个文件...
  • C语言 ——字符数组

    2019-07-23 19:42:31
    字符数组: 当把字符串保存数组中时,...常用的存于string库文件中的一些字符串函数: 1、strcpy:复制字符串。 strncpy(str,src,3); :strncpy的函数的用法就是把src中前三个字符串复制str数组中。 2、...
  • 从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件"test"中保存,输入的字符以'!'结束

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 516
精华内容 206
关键字:

c语言输出字符串到文件

c语言 订阅