我总是使用这种方法
int c;
while ((c = fgetc(fp))!=EOF)
{
printf("%c", c);
}
因为在我看来它更具可读性和健壮性。但是对于我的一个回答链接,chux评论说
if (fof (fp))比int c;while ((c = fgetc(fp))!=EOF)
while(1)
{
c = fgetc(fp);
if ( feof(fp) )
{
break ;
}
printf("%c", c);
}
比第一个版本更健壮。那么我应该使用哪个版本呢?请告诉我为什么那个版本更好。
编辑
In question为什么" while (!feof (file)) "总是错的?有人问为什么控制回路中的feof()总是错的。但是正确的检查feof()
状态总是错误的?解释是值得赞赏的。
我通常这样编写输入循环:
int c;
while (c = fgetc(fp), c != EOF) {
/* do something with c here */
}
/* check if EOF came from an end-of-file or an error */
if (ferror(fp)) {
/* error handling here */
}
一般不应该使用这样的循环条件:
while (!feof(fp)) {
/* do stuff */
}
或
for (;;) {
c = fgetc(fp);
if (feof(fp))
break;
}
因为遇到IO错误时会中断。在本例中,fgetc
返回EOF
,但没有设置文件结束标志。您的代码可能会进入无限循环,因为错误条件通常会持续存在,直到采取外部操作。
正确的方法是检查fgetc()
的结果:如果它等于EOF
,通常可以停止读取进一步的数据,因为在IO错误和文件结束条件的情况下,通常不可能读取进一步的数据。然后,您应该检查是否发生了错误,并采取适当的措施。
2有趣的问题
ferror()
ferror()
反映了流的错误指示器的状态。当发生罕见的输入错误时设置此标志,并保持设置,直到清除-参见clearerr()
。如果一个读输入错误,然后代码再次读取而不清除, ferror()
仍然报告为true,即使下面的读没有错误。
当fgetc()
返回EOF
时,可能是由于文件结束(常见)或罕见的输入错误。最好检查feof()
而不是ferror()
来区分。ferror()
可能是真的,因为先前的错误,而不是现在的情况-这肯定是文件结束。
int c;
c = fgetc(file);
if (c == EOF) {
if (feof(file)) puts("end-of-file");
else puts("input error");
}
Wide char
:测试错误条件的问题出现了,因为c中的一个角落案例
fgetc()
返回一个int
。取值范围为unsigned char
~ EOF
(某个负数)。
int ch;
while ((ch = fgetc(fp)) != EOF) {
// do something with ch
}
if (ferror(fp)) Handle_InputError();
if (feof(fp)) Handle_EndOffFile(); // Usually nothing special
然而C允许unsigned char
的取值范围比int
的正数更大。将unsigned char
转换为int
有一个实现定义的行为,该行为可能导致unsigned char
值被转换为负的int
-并且与EOF
匹配。
这样的平台很少见,也不是2015年的主流。大多数将使用UCHAR_MAX <= INT_MAX
,并且通常使用上述样式。由于上述代码的数量,这些平台是否会变得普遍值得怀疑,因为这些代码依赖于EOF
与转换为int
的unsigned char
不同。
代码是否需要处理UCHAR_MAX > INT_MAX
,然后
int c;
for (;;)
{
c = fgetc(file);
if (c == EOF) {
if (feof(file)) break;
if (ferror(file)) break;
// fall through if both if's fail.
}
// do stuff with c
}
在while (!feof (file))中流行的引用总是错误的?突出显示在检查问题之前使用fgetc(in)
结果时经常犯的错误。在使用fgetc()
的结果之前,其他答案中的两个代码都检查错误条件。
第二个代码处理所有的情况,包括那些可能只适用于电脑坐在一些长期被遗忘的垃圾堆。
建议的改进并不更好,甚至更不健壮。
如本文所述,如果发生读错误(没有eof),它将进入一个无限循环。在这种情况下,feof
将返回0
,而fgetc
返回EOF
。
您的版本没有此问题。
此外,你的版本更短,更简单,更标准。