如果你不检查 C 语言中的 feof 会怎样?

What happens if you don't check feof in C?

提问人:programme3219873 提问时间:8/9/2022 最后编辑:Jonathan Lefflerprogramme3219873 更新时间:8/9/2022 访问量:227

问:

在读/写操作期间,是否绝对有必要检查?feof()

我问的原因是因为我有一个执行读/写一次的程序,下面是代码:

while (1) {

      data = read_file_data(file);
      write_file_data(data, filename);

      if (feof(file)) 
          print(read error)
}

这只是伪代码,但是是否有必要在这样的情况下进行检查,其中读取将发生一次?目前,我认为只有在您像这样在上面的阅读之后再读一次才有必要:feof()

while (1) {

      data = read_file_data(file);
      write_file_data(data, filename);

      if (feof(file))       // feof error occurred oops
          print(read error)

      data = read_file_data(file); // reading after error    
}

最后,即使在发生错误(阅读过去)后,阅读的后果是什么?EOF reachedEOF

C 文件 指针 File-IO FEOF

评论

2赞 Eugene Sh. 8/9/2022
检查为什么 “while( !feof(file) )” 总是错的?feof()
0赞 Steve Friedl 8/9/2022
您可以通过多种方式检测文件结束情况,但很少是最佳使用方式。您的函数是否通过一次获取一个字符直接检查 EOF,或者从任何其他从文件读取函数中查找文件末尾返回值?feof()read_data_file()
0赞 klutt 8/9/2022
有点不清楚。你的意思是这是eof检查还是不是?ferror(file)
2赞 Eric Postpischil 8/9/2022
您应该检查每次读取和每次写入是否成功完成。如果没有,您应该处理该问题(也许通过终止程序,并向用户发送消息)。执行此操作时,通常不需要单独检查 fie 结束,除非您希望区分由于文件结束导致的失败和由于某些 I/O 错误导致的失败。单独检查文件末尾是无用的,因为它不能告诉你下一次读取(或写入)是成功还是失败(好吧,有时它可以告诉你它会失败,但它不能保证成功)。
2赞 Eric Postpischil 8/9/2022
此外,若要检查每个读取或写入调用是否成功完成,请通过例程返回的信息进行检查。某些例程返回的 a 是字符代码或 .否则,返回他们成功转移的项目数。有些人可能会将信息放在您指向的地方。无论采用哪种方法,都应使用它来检测错误,而不是单独调用。并将其内置到您的子例程中 - 让他们将状态信息转发给调用者,除非他们自己完全处理。intEOFfeof

答:

6赞 Steve Summit 8/9/2022 #1

在读/写操作期间,是否绝对有必要检查feof()?

哈哈在正常操作期间,检测 EOF 的最佳方法是检查您正在使用的特定输入调用的返回值。输入调用总是会失败,因此应始终检查其返回值。对于 和 尤其如此,许多初级程序员(不幸的是,许多初级编程教程)显然忽略了检查。scanffgets

很少需要显式调用。如果出现以下情况,您可能需要致电:feoffeof

  • 输入调用刚刚返回 0 或 ,但您想知道这是由于实际的文件结尾还是更严重的错误。EOF
  • 您使用了输入调用,例如无法指示 EOF 或错误。getw()
  • (罕见,可以说是糟糕的形式)您已经连续进行了一长串输入调用,并且您不希望其中任何一个都具有 EOF,因此您不想明确检查所有输入,但决定在最后使用一个包罗万象的调用进行检查。feof()

要知道的另一件事是,它只告诉你你确实点击了文件末尾——即过去时。它不能预测未来;它不会告诉您您尝试进行的下一个输入调用将命中 EOF。它告诉您,您之前拨打的电话确实命中了 EOF。参见 为什么“while( !feof(file) )”总是错的?feof()

另请参阅如何在使用 fread() 和 fwrite 时检测读/写错误?


即使发生 EOF 达到错误(读取超过 EOF)后读取的后果是什么?

这是个好问题。答案是,“视情况而定”,由于不可预测性可能是一个真正的问题,因此您最好的选择通常是不要尝试阅读过去的 EOF。

当我第一次学习 C 语言时,如果你得到了 EOF,但尝试再读一些,如果 EOF 以某种方式“消失”了,你的下一次阅读可能会成功。如果您从键盘上阅读,并且用户通过键入 control-D 来指示 EOF,那么 EOF 像这样“消失”可能是很常见的。但是,如果他们在键入 control-D 后输入了更多输入,您可以继续阅读它。

但那是过去的事情了。如今,EOF 是“粘性”的,一旦为流设置了文件结束标志,我认为将来任何读取尝试都应该立即返回 EOF。如今,如果用户点击 control-D 并且您想继续阅读,则必须调用 .clearerr()

我很确定我刚才所说的一切都与每个流的 EOF 标志相邻,并且每个流错误标志也是如此。feof()ferror()

在评论中,@0___ 说“如果你忽略 I/O 错误并继续,你就会调用未定义的行为”。我不认为这是真的,但我没有手边的标准副本可以检查。

4赞 Antti Haapala -- Слава Україні 8/9/2022 #2

调用的原因是要弄清楚输入函数的返回是由于某种实际的 I/O 错误(然后会返回一个非零值,但不会),还是由于输入被耗尽(这不是错误,而是一个条件; 将返回一个非零值)。feofEOFferror()feof()feof()

例如,如果您的程序要消耗所有输入并对其进行处理,那么能够区分您实际上确实读取了所有输入,以及当您只读取一半的输入时有人从驱动器中取出了 U 盘,这可能至关重要。