You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言读取文件时为什么需要使用feof函数做两次检查?

示例代码(出自《C Programming Absolute Beginner's Guide (3rd Edition)》)
/* 该程序读取第28章第一个示例生成的图书信息文件,将文件的每一行输出到屏幕 */

#include <stdio.h>
#include <stdlib.h>
FILE * fptr;
main()
{
    char fileLine[100]; // 存储读取的每一行内容
    
    fptr = fopen("C:\users\DeanWork\Documents\BookInfo.txt","r");
    if (fptr != 0)
    {
        while (!feof(fptr))
        {
            fgets(fileLine, 100, fptr);
            if (!feof(fptr))
            {
                puts(fileLine);
            }
        }
    }
    else
    {
        printf("\n打开文件失败\n");
    }
    
    fclose(fptr); // 任何情况下都要关闭打开的文件
    return(0);
}
问题解答

问题:上述代码中已经在while循环条件处通过while(!feof(fptr))判断文件未到结束位置,为什么调用fgets读取行内容后,还需要新增if(!feof(fptr))做二次检查?


核心原因是feof()的运行逻辑和直觉认知不同:

  • feof()不会提前预判下一次读取是否会碰到文件末尾,只有当你已经执行了一次读取操作、且这次操作因为碰到文件末尾读取失败后,feof()才会返回真。

我们可以模拟完整的读取流程理解这个设计:
假设文件共有2行有效内容,整个读取过程如下:

  1. 刚打开文件时EOF标志为假,第一次进入while (!feof(fptr))循环
  2. 调用fgets成功读取第1行内容,EOF标志仍为假
  3. 二次feof判断为真,输出第1行内容
  4. 回到while循环判断,feof仍为假,第二次进入循环
  5. 调用fgets成功读取第2行内容,EOF标志仍为假
  6. 二次feof判断为真,输出第2行内容
  7. 回到while循环判断,因为上一次fgets读取成功,EOF标志还没有被触发,第三次进入循环
  8. 调用fgets尝试读取,此时已经没有有效内容,fgets返回NULL,同时将EOF标志置为真
  9. 二次feof判断为假,跳过输出逻辑,不会输出无效的缓冲区内容
  10. 回到while循环判断,feof为真,退出循环

如果没有这层二次检查,第8步之后会直接执行puts(fileLine),此时缓冲区要么残留上一次读取的内容导致最后一行重复输出,要么是不确定的垃圾值,最终输出结果异常。

另外这种两次判断feof的写法比较冗余,更推荐直接把fgets的返回值作为循环判断条件,代码更简洁也不容易出错:

while (fgets(fileLine, 100, fptr) != NULL) {
    puts(fileLine);
}

内容的提问来源于stack exchange,提问作者user8314628

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 18:45:00