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

2024-04-22

当然fgetc()回报EOF when 文件结尾 or an 输入错误 occurs.
这就是全部吗?这是否意味着没有更多数据可用?

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(), ferror()充足的?

Note: EOF这是一个计算结果为负值的宏int, often -1。这是not的同义词文件结尾.

我已经发现一些问题 https://stackoverflow.com/questions/tagged/c+fgetc 接近这个问题,但没有列举所有可能性。


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

不,还有更多方法EOF.
An EOF并不一定意味着没有更多数据——这取决于情况。

C 库列出了三种情况fgetc()回报EOF.

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

回忆每一个stream, like stdin,有一个文件结束指示符 and 错误指示器.

  • 流刚刚遇到文件结尾

    (最常见)已尝试获取更多数据,但没有成功。

  • 设置流的文件结束指示符

    该流首先检查其文件结束指示符。如果发现指示器已设置,则返回EOF。不会尝试查看是否存在更多数据。某些类型的流将报告EOF,但数据将在之前到达EOF报告。直到文件结束指示符被清除为clearerr(),返回值仍为EOF. 实施例1 https://stackoverflow.com/a/56755955/2410359. 实施例2 https://stackoverflow.com/a/57272367/2410359.

  • 输入错误

    溪流error指标是not检查了。然而,由于某种原因,该函数无法读取文件结尾以外的数据。一个常见的例子是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));
    

    Output

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

    When ferror()是真的,这并不意味着错误刚刚发生,只是在过去的某个时间发生。

其他案例

  • 明显EOF由于不正确地另存为char

    fgetc()返回一个int的值在unsigned char范围和EOF- 负值。
    When fgetc()读取字符代码 255,但将其另存为char在一个系统上char is signed,这通常会导致char具有相同的值EOF,但文件结尾并未发生。

        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);
    

    Output

    1 -1  // ch == EOF !
    end-of-file:0 error:0
    
  • 系统所在UCHAR_MAX == UINT_MAX. Rare.

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

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

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

  • 未定义的行为

    当然当UB https://en.wikipedia.org/wiki/Undefined_behavior发生,一切皆有可能。

          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");

如果代码需要在之后查找数据文件结尾 or error, call clearerr()并重复if() block.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

`fgetc()` 可能返回 `EOF` 的所有原因是什么? 的相关文章

随机推荐

  • Robocopy 将文件复制到远程计算机

    我正在尝试编写一个 robocopy 命令将文件从本地计算机复制到任何一台部署服务器 ROBOCOPY MyService bin release remote computer C services myservice MIR 我收到这个
  • 将 Moment 与 Angular 和 TypeScript 结合使用

    我是 TypeScript 的新手 自从我进行任何认真的 JavaScript 开发以来已经有一段时间了 所以我可能会遗漏一些明显的东西 我正在尝试在带有 TypeScript 的 Angular 1 应用程序中使用 Moment 我正在使
  • 为什么抽象方法不能同步?

    我正在读一本来自 CodeRanch 的线程 http www coderanch com t 455033 java programmer SCJP certification abstract synchronized methods
  • 从后面的代码设置文本框的字体

    如何设置a的字体TextBox from a string在后面的代码中 example txtEditor FontFamily Consolas txtEditor FontFamily new FontFamily Consolas
  • Android Listview添加相同的项目

    我正在开发一个 Android 应用程序 并且正在使用 Android ListView 我从网络服务获取数据并将它们填充到数组列表中 它的大小是 37 然后我尝试用 Arraylist 填充列表视图 但它总是得到相同的元素 最后一个 下面
  • 如何使可能挂起的分叉进程超时?

    我正在编写一个 Perl 脚本 它将写入一些输入并将这些输入发送到外部程序 该程序挂起的可能性虽小但非零 我想将其超时 my pid fork if pid gt 0 eval local SIG ALRM sub die TIMEOUT
  • 在任何项目根目录中都找不到入口文件index.ios.js [“/Users/neo/newProjects/F2”]

    实际行为 从头开始启动 React Native 项目时 我没有启动 而是出现红屏和此错误消息 Cannot Find Entry file index ios js in any of the project root Users neo
  • 将ffmpeg安装到虚拟环境中

    我正在尝试安装ffmpeg以便在 OpenAI 上使用它来录制视频 我已经使用它安装了brew install ffmpeg但不知怎的 当我编译我的代码时 我得到了同样的错误 就像我的包无法识别一样virtualenv我工作的地方 Pyth
  • 无法安装 R 包:CMake 错误

    我正在尝试安装factoextra 但我在 CMake 部分遇到了困难 特别是出现如下错误 CMake Error The source directory tmp does not exist 当我尝试安装其依赖项时也是如此 nloptr
  • ruby yaml ypath 和 xpath 一样吗?

    你好 我有一个像这样的 yaml 文件 data date 2004 06 11 description First description date 2008 01 12 description Another descripion 我如
  • Corda 流的任一侧可以存在于单独的 Cordapp 中吗?

    如果一个节点想要在流的一侧执行自己的特定业务逻辑 如何实现 例如 如果一家公司想要调用内部公司 api 来验证传入的交易数据 它可以在流程中执行此操作吗 如果是这样 是否需要通用地编写流程 以便所有使用相同 Cordapp 和流程 的公司调
  • 读取文件内容并查询数据。蟒蛇3.5.1

    我正在尝试查询我保存在的销售记录data txt文件 每行以逗号分隔
  • 使用 R 将 Excel (.xlsx) 工作表打印/保存为 PDF

    我想打印一个Excel文件到一个pdf操作后的文件 对于操作 我使用了 xlsx包工作正常 有一个功能printSetup但我找不到启动打印的功能 有解决办法吗 library xlsx file lt test xlsx wb lt lo
  • 更改包名称

    我打算通过smali reverse 更改包名 当我打开 apktool yml 时 我看到了这个 强制包 ID 127 我尝试过更改它 但它崩溃了 我为什么要这样做 假设您的目标是重命名 apk 的包名称 则用于类的包名称是无关的 apk
  • THREE.js 导入的模型不应用面部纹理

    我正在尝试导入使用 THREEJS 导出器从搅拌机导出的模型 到目前为止 模型已加载并出现在我的场景中 并且正确应用了材质 汽车应为黄色 玻璃应为透明 但它并没有将我的纹理应用到以 tga 形式保存的汽车上 如果我不将纹理包含在模型所在的服
  • 为什么使用工厂而不是“新”?

    我正在看书其中指出 EMF 编程模型强烈鼓励但不要求 使用工厂来创建对象 而不是简单地使用 new 运算符创建 对象 为什么鼓励使用工厂new 您的答案不必是特定于 EMF 的 只要它与 Java 有关即可 您可以阅读 Effective
  • ng-repeat 没有 HTML 元素(这次真的没有任何)

    我想要得到类似的东西 Line 1 br Line 2 br Line 3 br Line 4 br Line 5 br 使用 ng repeat 各行之间不应有任何分隔符 除了 br 这是一个硬编码的简单指令 br HTML p p ap
  • 如何在 Webpack 中正确使用命名空间 Typescript

    我正在使用 webpack 开发一个新项目 这是我第一次尝试使用这个工具 自从 1 年以来 我一直使用 typescript 针对 angularJS 1 5 进行开发 并且从未遇到过与命名空间相关的任何问题 src App Core Ht
  • 在 Win 7 上安装 Python 2.7 32 位:没有注册表项?

    我已从 python org 下载了 Python 2 7 2 Windows x86 32 位 MSI 并将其安装在 64 位 Windows 7 系统上 一切正常 至少命令行解释器启动并运行 但安装过程不会创建任何PythonWindo
  • `fgetc()` 可能返回 `EOF` 的所有原因是什么?

    当然fgetc 回报EOF when 文件结尾 or an 输入错误 occurs 这就是全部吗 这是否意味着没有更多数据可用 FILE inf int ch while ch fgetc inf EOF if feof inf puts