请稍侯

feof()函数陷阱

24 October 2015

先从一个简单的输出开始

一个程序,代码如下:

#include<stdio.h>

int main()
{
    char buff[1024];
    memset(buff, 0, sizeof(buff));
    FILE* f = fopen("a.txt", "r");
    while (!feof(f))
    {
        printf("---not eof\n");
        fgets(buff, sizeof(buff), f);
        printf("buff is -- %s", buff);
    }
    printf("----eof!\n");
    return 0;
}

文件a.txt的内容是这样的:

abcdef

这个程序的输出结果是:

---not eof
buff is -- abcdef
---not eof
buff is -- abcdef
----eof!

好像哪里不对,为什么会输出两边,进入两次循环,原因是这样的:

feof函数的功能是检查一个stream在当前其文件结束标志是否被置位,如果已经置位,返回非零值,否则返回零。一个stream的文件结束标志是由当前时间之前的最后一次相关操作(包括读、seek等操作)设置的。在上述代码while循环中,当fgets在读取文件最后一行后,文件结束标志还并没有被置位,所以下一次while循环判断依然可以进来,此时再一次调用fgets将返回null(这时文件结束标志被置位),而line中的字符串保持不变,依然为上一次的结果,此时再一次打印line,所以出现最后一行被打印输出两次。

解决方法:

第一种

#include<stdio.h>

int main()
{
    char buff[1024];
    memset(buff, 0, sizeof(buff));
    FILE* f = fopen("a.txt", "r");
    fgets(buff, sizeof(buff), f);  // 第一种直接用fgets函数返回结果作while条件判断。
    printf("buff is -- %s", buff);
    while (!feof(f))
    {
        printf("---not eof\n");
        fgets(buff, sizeof(buff), f);
    }
    printf("----eof!\n");
    return 0;
}

第二种

#include<stdio.h>

int main()
{
    char buff[1024];
    memset(buff, 0, sizeof(buff));
    FILE* f = fopen("a.txt", "r");
    fgets(buff, sizeof(buff), f);  // 第一种直接用fgets函数返回结果作while条件判断。
    printf("buff is -- %s", buff);
    while (1)
    {
        printf("---not eof\n");
        fgets(buff, sizeof(buff), f);
        if (!feof(f))
            printf("buff is -- %s", buff);
        else
            break;
    }
    printf("----eof!\n");
    return 0;
}

注意

fgets函数的调用会修改文件结束标志,其他还会修改文件结束标志的类似的函数还有:fgetc、fgets、fread、fseek、getc、getchar、gets等,所以,在使用这些函数的时候也要注意这个问题。