• feof()判断文件结束的问题


    我在编写学生成绩管理系统时用到了写文件和读文件,发现读文件总会显示出乱码,调试发现是因为用feof()做判断,在读文件最后时fread()多读取了一次。我一开始的解决办法是每次读取完文件,都把最后一个节点(每一行数据都读取放到链表的节点里)free掉。但这种方法明显不是那么好。

    feof(fp)用来测试fp所指向的文件当前状态是否为“文件结束”。如果文件结束,则返回1,否则返回0。适合于二进制文件和文本文件。
    但是,在实际使用feof时却发生了问题:文件实际已经结束时feof还要再判断一次才返回1
    测试代码如下:

     1 #include <stdio.h>
     2 int main()
     3 {
     4     char ch = 0;
     5     int i = 0;
     6     FILE* fp;
     7     // 建立空文件
     8     fp = fopen("Info.txt", "w");
     9     if(NULL == fp)
    10     {
    11         printf("Cannot open file!\n");
    12         return 0;
    13     }
    14     fclose(fp);
    15     // 读取空文件
    16     fp = fopen("Info.txt", "r");
    17     if(NULL == fp)
    18     {
    19         printf("Cannot open file!\n");
    20         return 0;
    21     }
    22     while(!feof(fp))
    23     {
    24         ch = fgetc(fp);
    25         i++;
    26     }
    27     fclose(fp);
    28     printf("fread times: %d\n"
    29             "note: %c\n", i, ch);
    30     return 0;
    31 }

    得到i为1,ch为空,说明feof()确实在文件为空状态时判断有误。

    上网搜索有人说先读再判断就不会有问题了,但试了一下还是不行。对此,C FAQ-12.3的解释是“在C语言中,只有输入例程试图读并失败以后才能得到文件结束符。...fgets()在遇到文件结束符的时候返回NULL。实际上,在任何情况下,都完全没必要使用feof()。”

    把while(!feof(fp)){}换成while(!fgets(str, 0, fp)){}确实能保证判断正确。但是,如果我在函数体里面还有其他读操作如fread()的话则会出现影响。所以,最好的解决办法是利用fseek()和ftell()配合来判断文件指针位置:

    1 fseek(fp, 0L, SEEK_END);//文件指针置于结尾
    2 len1 = ftell(fp);//获取结尾指针值
    3 fseek(fp, 0L, SEEK_SET);//文件指针至于开头
    4 len2 = ftell(fp);//获取开头指针值
    5 while(len2 != len1)//循环判断
    6 {
    7     //do something
    8     len2 = ftell(fp);
    9 }

    结果正确,无副作用。

    其实还有另一种解决办法,就是每次写文件时在开头写入节点数,这样下次读文件时就知道要读取多少数据了。

    ChinaUnix上也有一篇帖子对于这个问题讨论得很详细,但是提供的方法不适合我当时的情况:http://bbs.chinaunix.net/thread-957347-1-1.html

     

  • 相关阅读:
    cp
    usr/sbin/inetd
    mysql
    Iptables的规则语法
    CentOS系统安装过程中配置软RAID-0或RAID-1
    25道shell面试题
    虚拟机
    进入单用户模式
    正则表达式
    js操作div的显隐
  • 原文地址:https://www.cnblogs.com/jacobchen/p/2481267.html
Copyright © 2020-2023  润新知