当前位置: 首页 > 知识库问答 >
问题:

fgetc()可能返回EOF的所有原因是什么?

张晨朗
2023-03-14

当然fgetc()在文件结束或输入错误发生时返回EOF,但这是否意味着没有更多的数据可用?

FILE *inf = ...;
int ch;
while ((ch = fgetc(inf)) != EOF) {
  ;
}
if (feof(inf)) puts("End-of-file");
else if (ferror(inf)) puts("Error");
else puts("???");

使用feof()、feror()进行测试是否足够?

注意:EOF这里是一个宏,它的值为负值,通常是-1。它不是文件结束的同义词。

我发现了一些与这个问题相关的问题,但没有一个列举了所有的可能性。


共有2个答案

燕正卿
2023-03-14

另一个EOF不一定意味着“没有更多数据”的情况是(而不是“正在”)读取磁带。您可以在一个磁带上有多个文件,每个文件的结尾都标有EOF。当您遇到EOF时,您使用clearerr(fp)重置文件流上的EOF和错误状态,然后您可以继续读取磁带上的下一个文件。然而,磁带(在很大程度上)已经走上了渡渡鸟的道路,所以这几乎不再重要。

袁枫涟
2023-03-14

这是我能回答我自己的问题吗?。

就这些吗?这是否意味着没有更多可用的数据?

不,EOF有更多的方法
一个EOF并不一定意味着没有更多的数据-这取决于具体情况。

C库列出了3种情况,其中fgetc()返回EOF

如果设置了流的文件结束指示符,或者流位于文件结束处,则设置流的文件结束指示符,fgetc函数返回EOF。否则,fgetc函数将返回流所指向的输入流中的下一个字符。如果发生读取错误,则设置流的错误指示器,并且fgetc函数返回EOF。C17dr§7.21.7.1 3

调用每个流,比如stdin,都有一个文件结束指示符和错误指示符。

>

设置流的文件结束指示符
流首先检查其文件结束指示符。如果它看到指标已设置,则返回EOF。没有尝试查看是否存在更多的数据。某些类型的流将报告EOF,但是数据将在之前的EOF报告之后到达。直到文件结束指示符被清除,如clearerr(),返回仍然是EOF示例示例

输入错误
未检查流错误指示器。然而,由于某种原因,该函数无法读取文件末尾以外的数据。一个常见的例子是fputc(stdin)。通常输入错误是持久的。有些不是。可能有更多的数据。常见的策略是结束输入。

  // Example where ferror() is true, yet fgetc() does not return EOF  
  FILE *inf = stdin;
  printf("end-of-file:%d error:%d\n", feof(inf), ferror(inf));
  printf("fputc():%d\n", fputc('?', inf));  // EOF reported
  printf("end-of-file:%d error:%d\n", feof(inf), ferror(inf));
  printf("fgetc():%d\n", fgetc(inf));  // User typed in `A`, 'A' reported
  printf("end-of-file:%d error:%d\n", feof(inf), ferror(inf));

输出

end-of-file:0 error:0
fputc():-1
end-of-file:0 error:1
fgetc():65
end-of-file:0 error:1

ferror()为true时,这并不意味着错误只是刚刚发生,只是过去的某个时候。

其他情况

>

FILE *f = fopen("t", "w");
fputc(EOF & 255, f);
fclose(f);
f = fopen("t", "r");
char ch = fgetc(f); // Should be int ch
printf ("%d %d\n", ch == EOF, ch);
printf("end-of-file:%d error:%d\n", feof(f), ferror(f));
fclose(f);

输出

1 -1  // ch == EOF !
end-of-file:0 error:0

>

  • 其中UCHAR_MAX==UINT_MAX的系统。
    (我只在一些旧的图形处理器中遇到过这个,仍然是C允许的。)在这种情况下,fgetc()可能会读取int范围之外的无符号char,因此在函数返回时将其转换为EOF。因此fgetc()返回的字符代码恰好等于EOF。这在C语言的历史中是很奇怪的。主要处理方法是:

      while ((ch = fgetc(inf)) != EOF && !feof(inf) && !ferror(inf)) {
        ;
      }
    

    很少需要这样迂腐的代码。

    >

  • 定义的行为
    当然,当UB发生时,任何事情都是可能的。

      FILE * f = fopen("Some_non_existent_file", "r");
      // Should have tested f == NULL here
      printf("%d\n", fgetc(f) == EOF); // Result may be 1
    

    处理从fgetc()返回的健壮方法。

    FILE *inf = ...;
    if (inf) {  // Add test
      int ch; // USE int !
    
      // Pedantic considerations, usually can be ignored
      #if UCHAR_MAX > INT_MAX
        clearerr(inf); // Clear history of prior flags
        while ((ch = fgetc(inf)) != EOF && !feof(inf) && !ferror(inf)) {
          ;
        }
      #else
        while ((ch = fgetc(inf)) != EOF) {
          ;
        }
      #endif
    
      if (feof(inf)) puts("End-of-file");
      else puts("Error");
    

    如果代码需要在文件结束或错误后查找数据,请调用clearerr()并重复if()块。

  •  类似资料:
    • PHP手册说,如果锁定成功,调用flock将返回TRUE,否则返回FALSE。若文件被其他进程阻塞,那个么flock应该等到它被解锁(因为我们不使用LOCK_NB)。文档中没有超时,超时会中断等待,所以显然flock将无限等待,直到获得锁为止。 但是有时我在我的多线程脚本中从flock()得到FALSE。那是什么原因呢?

    • 为什么代码获取不到API返回的数据? API是免费版本, 每分钟限制45次请求,使用POST请求方式, URL中的fields=58898是返回指定字段. 我在API的网站查询IP没有问题, 但是代码中一直返回空值, requests也没有报错, 所以现在有点不知道从哪里下手了, 请大佬们帮我分析一下, 或者给点思路! 跪谢!

    • 问题内容: 我在雄猫服务器(+ liferay)上收到此异常 我的课是这样的: 我在行上收到此异常, 当队列已满但大小为2 ^ 31时,可能会发生此错误,并且我确定没有那么多命令在等待。 一开始一切都稳定,但在我重新部署战争后,一切开始发生。此类不是战争的一部分,而是放在tomcat / lib中的jar中。 您是否知道为什么会发生这种情况以及如何解决? 问题答案: 从ThreadPoolExec

    • 我有下表: 对于两组中的每一组,我想返回所有可能的值组合。对于组1,例如,可能的组合是(A, B)、(A, C)、(A, D)、(B, C)、(B, D)、(C, D)、(A, B, C)、(B, D, C)、(C, A, B)。类似地,对于组2,它是(A, B)、(A, C)、(B, C)[备注:我不想考虑(1)只有一个值的组合,(2)所有值的组合和(3)没有值的组合。因此,对于n个不同的值,我

    • 问题内容: 检索的对象。此方法可以返回的所有可能值是什么?我可以使用该值来标识数据库中发生的特定错误吗(即,该值可以告诉我是否是PK违例,唯一约束或列值是否很大等)? 同样,该方法应该指示返回的是X / Open(现在称为Open Group)SQL CLI还是SQL99。唯一可能的价值应该是并且我正在获取价值。我想念什么吗? 有没有一种方法可以使用上述方法的组合来确定数据库中发生的特定错误类型?

    • 我有一个使用activeMQ消息的项目。它运行良好,但有时会遇到挂起的消息卡在队列中。它说1000入队,0出队,1000分派。它还说1000条待处理的消息。 “待定消息”的可能原因是什么?