【问题标题】:EOF on macos and centos different resultmacOS 和 centos 上的 EOF 不同的结果
【发布时间】:2019-07-07 02:55:32
【问题描述】:

我正在使用EOF跳出'while'循环,并想通过'scanf'输入一些数字。循环外的'scanf'在macos上不起作用。

我试过在macos和centos上运行这段代码。centos上的结果就是我需要的。

#include <stdio.h>
#include <stdlib.h>
int main(){
 int i;
 //ctrl+d=EOF
 while(scanf("%d",&i) != EOF){
  printf("?");
 }
 printf("\nloopend\n");
 //those 'scanf' are ignored on macos.
 scanf("%d",&i);
 scanf(" %d",&i);
 scanf("%d ",&i);
 printf("\nend\n");
}

输入(不带','): 1,\n,ctrl+d

输出(centos):

1
?
loopend
//waiting for input here

输出(macos):

1
?
loopend

end
//the program ended directly

【问题讨论】:

  • 为什么是scanf("%d",&amp;i) != EOF 而不是scanf("%d",&amp;i) == 1
  • 尝试在循环后调用clearerr(stdin);
  • 请不要测试scanfEOF 的返回值。请测试scanf的返回值,了解您希望扫描的项目数。
  • @MM 谢谢! clearerr(stdin) 正是我所需要的。
  • @SteveSummit 谢谢!实际上我希望一个不是正常数字的符号结束循环。

标签: c macos centos


【解决方案1】:

MacOS 行为正确。根据C standard §7.21.7.1/3fgetc库函数),文件结束指示是粘性的;一旦fgetc 看到 EOF,它必须设置文件的文件结束指示符,这将导致后续调用返回EOF,直到文件结束指示符被清除,例如clearerr()

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

由于其他输入函数,包括scanf,应该像通过重复调用fgetc 来实现一样,因此EOF 也应该对它们具有粘性。如果您想在收到 EOF 返回后继续阅读,您应该在流上调用 clearerr()。 (或其他重置指标的东西,例如seek()。)

多年来,标准 C 库的 Gnu 实现并没有遵循标准。它只报告了一次 EOF,让下一个 fgetc 等待终端和管道等设备上的更多输入。 2006 年报告的错误是 finally fixed in v2.28,于 2018 年 8 月发布,尽管它可能还不是 Centos 发行版的一部分。

[注意:this answer 中对此行为进行了更长的讨论,包括现在已经过时的抱怨(我)和一些关于该问题的历史讨论的链接。]

无论如何,可移植代码应该调用clearerr() 一直很清楚,因为 BSD 派生的标准库实现(包括 MacOS)遵循上面引用的标准。

【讨论】:

  • 我完全同意 GNU 库是异常的——它是终端输入(获得该行为所必需的)并不重要。一旦看到 EOF,它应该保持“可见”,直到并且除非进行了 clearerr() 调用。
  • @jonathan。是的,我多年来一直在抱怨这个问题。但显然 glibc 终于修复了,所以我编辑了答案。
  • 如果最后修复了,那么“was aberrant”比“is aberrant”更合适。 2.28 版本于 2018 年 8 月发布;当前版本是 2.29 (2019-01-31)。新版本每 6 个月发布一次。自修复发布以来还不到一年——它只会在前沿系统中可用(遗憾的是,不是我使用的东西)。 (请参阅“已弃用和删除的功能,以及影响兼容性的其他更改”部分中的 sourceware.org/ml/libc-alpha/2018-08/msg00003.html。)
  • @jonathan:正是我在搜索线程时发现的消息,其中 glibc 维护者顽固地坚持认为行为不会改变。很惊喜,尽管它不再与我所做的任何事情真正相关。
  • @jonathanleffler yup 记录了内核功能,正如我本周在管理人员中读到的那样......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-24
  • 2022-01-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多