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行有效内容,整个读取过程如下:
- 刚打开文件时EOF标志为假,第一次进入
while (!feof(fptr))循环 - 调用
fgets成功读取第1行内容,EOF标志仍为假 - 二次
feof判断为真,输出第1行内容 - 回到while循环判断,
feof仍为假,第二次进入循环 - 调用
fgets成功读取第2行内容,EOF标志仍为假 - 二次
feof判断为真,输出第2行内容 - 回到while循环判断,因为上一次
fgets读取成功,EOF标志还没有被触发,第三次进入循环 - 调用
fgets尝试读取,此时已经没有有效内容,fgets返回NULL,同时将EOF标志置为真 - 二次
feof判断为假,跳过输出逻辑,不会输出无效的缓冲区内容 - 回到while循环判断,
feof为真,退出循环
如果没有这层二次检查,第8步之后会直接执行puts(fileLine),此时缓冲区要么残留上一次读取的内容导致最后一行重复输出,要么是不确定的垃圾值,最终输出结果异常。
另外这种两次判断feof的写法比较冗余,更推荐直接把fgets的返回值作为循环判断条件,代码更简洁也不容易出错:
while (fgets(fileLine, 100, fptr) != NULL) { puts(fileLine); }
内容的提问来源于stack exchange,提问作者user8314628
相关产品推荐
相关产品推荐

