那个回复已经说清楚了,就是feof的一个坑,得仔细看feof的文档。
而且,文件最后一行的行尾正好有个换行字符时,才能出现这个问题。VC2019里测试也是这样。
一、假如最后一行的内容是:
!library functions and macros\n
1、fgets()会把这行(包括\n)的内容都读取,然后文件指针指向了\n的下一个字符的位置(假想有那么个位置,虽然已经超出了文件范围)。但此时并不会设置"文件结束了"的标记。
2、所以feof( )为false,进入下一次的getc/ungetc/fgets;
3、这次的fgets()发现指针到了文件范围外,会返回失败(但你的代码没判断getc/ungetc/fgets的失败情况),同时设置“文件结束了”的标记。打印的是buffer中残留的上次的内容。
4、这次的feof()就是true了。
二、假如最后一行的内容没有\n:
!library functions and macros
1、那么fgets()会一直读取字符直到遇到文件尾,然后会设置“文件结束了”的标记,同时读取了多少内容就返回多少。
2、feof()直接就是true。
因为feof()有这个坑,再加上文件在磁盘上是有可能损坏的,所以涉及到I/O操作(不限于磁盘I/O,还有socket I/O等)的每个函数,都要检查返回值,也就是不能完全信任外设的可靠性。可视为一条"军规"。
不检查返回值是不可取的。
stdio的文件操作是很灵活的,有多种读写方法,针对文本文件、二进制文件,掌握一种然后固定下来就行。
对于超大文件,可以特殊处理,比如用内存映射方式操作。
【 在 howry 的大作中提到: 】
:
: 谢谢您的回复!我用的是gcc环境。我感觉可能是您那边得到的file.txt和ubuntu下创建的file.txt不一样。linux和windows下的换行符不一样。如果我把ubuntu下创建的file.txt放到windows下,还是会出现多一行的情况。不过您的程序的写法确实能避免这个问题。无论在linux和windows下都能得到只输出3行的结果。
: 您有空可以看下这篇帖子
http://www.newsmth.net/nForum/#!article/CProgramming/140155--
修改:z16166 FROM 221.222.173.*
FROM 221.222.173.*