zoukankan      html  css  js  c++  java
  • C语言文件操作解析(三)

                                                          C语言文件操作解析(三)

           在前面已经讨论了文件打开操作,下面说一下文件的读写操作。文件的读写操作主要有4种,字符读写、字符串读写、块读写以及格式化读写。

    一.字符读写

        字符读写主要使用两个函数fputc和fgetc,两个函数的原型是:

        int fputc(int ch,FILE *fp);若写入成功则返回写入的字符,否则返回-1

        int fgetc(FILE *fp);  若读取成功则返回读取的字符,否则返回-1

    注意:1)对于fputc函数和fgetc函数,每次操作,fputc只能写入1个字节的数据,无论参数ch多大,只将其低8位的数据写入到文件中;fgetc 每次只能返回一个字节的数据。

            2)对于fgetc函数,若读取成功则返回读取到的字符,否则返回-1.这里面返回-1(即EOF)有两种情况:一种是读到文件结束已经没有任何字符可供读取了,另一种是读取出错。由于通常情况下,在文本文件中可显字符是不可能出现ASCII码为-1的字符,因此可以通过fgetc的返回结果判断文件是否结束(读取不出错的情况下)。但是在二进制文件中则不能这么判断了,因为二进制文件中很可能就含有FF这样的数据,如果将存储fgetc读取结果的变量ch定义为char型,则不能判断二进制文件是否结束,但是如果定义为int型,则同样可以判断,因为即使读取的字符是FF,但是由于ch是int型,则事实上ch=0x000000FF,并不等于-1,因此可以判断文件是否结束。(注意以上所述只在文件读取不出错的情况下成立,若文件读取出错,是不能这么判断文件是否结束,必须通过feof()函数来判断)

    测试程序:

    #include<stdio.h>
    #include<stdlib.h>

    int main(void)
    {
    FILE *fp;
    int ch;
    if((fp=fopen("test.txt","wb+"))==NULL)
    {
    printf("can not open file\n");
    exit(0);
    }
    fputc(-1,fp); //-1的二进制为FF
    fputc(385,fp); //385二进制为110000001
    rewind(fp);
    ch=fgetc(fp);
    while(feof(fp)==0)
    {
    printf("%d\n",ch);
    ch=fgetc(fp);
    }
    fclose(fp);
    return 0;
    }

    执行结果为:

    255
    129
    Press any key to continue

    由于fputc每次只写入一个字节的数据,因此虽然第二次想写入385,但是只将其低8位数据写入,所以输出结果为129.

    若将上述程序中的ch定义为char型,则执行结果为:

    -1
    -127
    Press any key to continue

    原因上面已经解释了.

    二.字符串读写

        字符串读写主要涉及到两个函数fputs和fgets,这两个函数的原型是:

        int fputs(const char *s,FILE *fp);

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

        对于fputs函数,将字符串写入文件,若写入成功则返回一个非负值,否则返回-1;

        对于fgets函数,从文件中读取不超过n-1个字符到字符数组中(若文件中字符少于n-1个,则只读取文件中存在的字符),系统在字符数组末尾自动添加一个'\0',返回字符数组的首地址。

    注意:1)对于fgets函数,在读取过程中,若读取到字符'\n',则读取过程提前结束。

    测试程序:

    #include<stdio.h>
    #include<stdlib.h>

    int main(void)
    {
    FILE *fp;
    char s[10];
    if((fp=fopen("test.txt","wb+"))==NULL)
    {
    printf("can not open file\n");
    exit(0);
    }
    fputc('A',fp);
    fputc('B',fp);
    fputc('\n',fp);
    fputc('C',fp);
    rewind(fp);
    fgets(s,5,fp);
    printf("%s\n",s);
    fclose(fp);
    return 0;
    }

    执行结果为:

    AB

    Press any key to continue

    由此可知当读取到换行符'\n'时便停止读取了。

    三.块读写

        块读写主要涉及到两个函数fread和fwrite,这两个函数的原型是:

        unsigned int fread(void *buffer,unsigned int size,unsigned int n,FILE *fp);

       从文件读取一组数据存放在首地址为buffer的内存空间中,size为一个数据块的大小,n为要读取的数据块的个数,若读取成功,则返回读取的数据的数据块的个数,否则返回0.

        unsigned int fwrite(const void *buffer,unsigned int size,unsigned int n,FILE *fp);

        向文件中写入数据,写入成功返回写入数据块的个数,否则返回0.

        块读写一般用于结构体。

    注意:1)块读写常用于结构体。

           2)fread和fwrite一般成对出现,如果对文件进行写操作用的是fwrite,则用fread读取,否则可能会得到意想不到的结果。

    测试程序:

    #include<stdio.h>
    #include<stdlib.h>

    typedef struct node
    {
    char name[20];
    double score;
    int age;
    }Student;

    int main(void)
    {
    FILE *fp;
    int i;
    Student s1[3]={{"liudehua",85.5,45},{"zhangxueyou",79.3,47},{"guofucheng",83.4,43}};
    Student s2[3];
    if((fp=fopen("test.txt","wb+"))==NULL)
    {
    printf("can not open file\n");
    exit(0);
    }
    printf("%d\n",fwrite(s1,sizeof(Student),3,fp));
    //printf("%d\n",fwrite(s1,sizeof(s1),1,fp)); //注意和上一句的区别
    rewind(fp);
    printf("%d\n",fread(s2,sizeof(Student),3,fp));
    for(i=0;i<3;i++)
    {
    printf("%s %lf %d\n",s2[i].name,s2[i].score,s2[i].age);
    }
    fclose(fp);
    return 0;
    }

    执行结果为:

    3
    3
    liudehua 85.500000 45
    zhangxueyou 79.300000 47
    guofucheng 83.400000 43
    Press any key to continue

    四.格式化读写

      格式化读写主要涉及到两个函数:fscanf和fprintf,两个函数的原型是

      int fscanf(FILE *fp,const char *format[,argument]....);

      用于从文件格式化读取数据,若读取成功,则返回读取的数据个数,否则返回-1

      int fprintf(FILE *fp,const char *format[,argument]....);

      用于向文件格式化写入数据,若写入成功,则返回写入的字符个数,否则返回-1

    注意:1)格式化读写和其他几种读写有很大的不同。格式化读写是以我们人所能识别的格式将数据写入文件,即若以格式化方式写入一个整型数值65,则其实是写入的两个字符'6'和'5',即占2字节,而不是4字节,但是若以块写方式写入,则其占4字节。即在使用格式化读写时系统自动进行了一些转换。

          2)fprintf和fscanf函数一般成对出现,若数据是用fprintf进行写入的,则最好使用fscanf进行读取。

          3)在使用fprintf函数写入时,若文件是以文本方式打开,如果参数format中包含了'\n',则最后文件中会被写入换行符;而若文件以二进制方式打开,则文件中不会被写入换行符,这点区别在上一篇博客中已经提到。

    测试程序:

    #include<stdio.h>
    #include<stdlib.h>

    typedef struct node
    {
    char name[20];
    double score;
    int age;
    }Student;

    int main(void)
    {
    FILE *fp;
    int i;
    Student s1[3]={{"liudehua",85.5,45},{"zhangxueyou",79.3,47},{"guofucheng",83.4,43}};
    Student s2[3];
    if((fp=fopen("test.txt","wb+"))==NULL)
    {
    printf("can not open file\n");
    exit(0);
    }
    for(i=0;i<3;i++)
    {
    printf("%d\n",fprintf(fp,"%s %lf %d\n",s1[i].name,s1[i].score,s1[i].age));
    }
    rewind(fp);
    for(i=0;i<3;i++)
    {
    printf("%d\n",fscanf(fp,"%s %lf %d",s2[i].name,&s2[i].score,&s2[i].age));
    }
    for(i=0;i<3;i++)
    {
    printf("%s %lf %d\n",s2[i].name,s2[i].score,s2[i].age);
    }
    fclose(fp);
    return 0;
    }

    执行结果:

    22
    25
    24
    3
    3
    3
    liudehua 85.500000 45
    zhangxueyou 79.300000 47
    guofucheng 83.400000 43
    Press any key to continue

    文件test.txt中的内容是:

    若将打开方式改成"wt+",则文件中的内容为:

    而若以fread和fwrite方式进行读写时,其结果如下:

    测试程序:

    #include<stdio.h>
    #include<stdlib.h>

    typedef struct node
    {
    char name[20];
    double score;
    int age;
    }Student;

    int main(void)
    {
    FILE *fp;
    Student s1[3]={{"liudehua",85.5,45},{"zhangxueyou",79.3,47},{"guofucheng",83.4,43}};
    if((fp=fopen("test.txt","wt+"))==NULL)
    {
    printf("can not open file\n");
    exit(0);
    }
    fwrite(s1,sizeof(s1),1,fp);
    fclose(fp);
    return 0;
    }

    则文件中的内容为:

    从这里就可以看出格式化读写跟其他方式的区别。

    测试程序:

    #include<stdio.h>
    #include<stdlib.h>

    int main(void)
    {
    FILE *fp;
    int n=32768;
    if((fp=fopen("test.txt","wt+"))==NULL)
    {
    printf("can not open file\n");
    exit(0);
    }
    fwrite(&n,sizeof(int),1,fp);
    fclose(fp);
    return 0;
    }

    执行后,用二进制方式打开文件:

    而32768的二进制为00000000100000000000000即00 80 00 00,内容占4个字节。

    #include<stdio.h>
    #include<stdlib.h>

    int main(void)
    {
    FILE *fp;
    int n=32768;
    if((fp=fopen("test.txt","wt+"))==NULL)
    {
    printf("can not open file\n");
    exit(0);
    }
    fprintf(fp,"%d",n);
    fclose(fp);
    return 0;
    }

    执行的结果:

    即用fprintf写入的是51,50,55,54,56,即跟字符'3','2','7','6','8'各自对应的整数值,内容占5个字节。
     

  • 相关阅读:
    apache安全—用户访问控制
    hdu 3232 Crossing Rivers 过河(数学期望)
    HDU 5418 Victor and World (可重复走的TSP问题,状压dp)
    UVA 11020 Efficient Solutions (BST,Splay树)
    UVA 11922 Permutation Transformer (Splay树)
    HYSBZ 1208 宠物收养所 (Splay树)
    HYSBZ 1503 郁闷的出纳员 (Splay树)
    HDU 5416 CRB and Tree (技巧)
    HDU 5414 CRB and String (字符串,模拟)
    HDU 5410 CRB and His Birthday (01背包,完全背包,混合)
  • 原文地址:https://www.cnblogs.com/dolphin0520/p/2200454.html
Copyright © 2011-2022 走看看