检查fgetc()的EOF和错误的更好方法是什么?



我总是使用这种方法

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与转换为intunsigned 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

您的版本没有此问题。

此外,你的版本更短,更简单,更标准。

最新更新