保证getchar最终会收到换行符或EOF吗?

问题描述

我想从stdin读取字符,直到出现以下情况之一:

  • 遇到行尾标记(我认为是正常情况)
  • 发生EOF情况,或
  • 发生错误。

我如何保证上述事件之一最终会发生?换句话说,如果没有发生错误(就getchar而言),我如何保证\n最终将返回EOFferror(stdin)

// (How) can we guarantee that the LABEL'ed statement will be reached?
int done = 0;
while (!0) if (
        (c = getchar()) == EOF || ferror(stdin) || c == '\n') break;
LABEL: done = !0;

如果stdin连接到总是 传递 '\n'以外的字符的设备,则不会发生上述情况。答案似乎与设备的属性有关。在哪里可以找到这些详细信息(可能是在编译器,设备固件或设备硬件中)?

尤其是,我想知道是否可以保证键盘输入是由行尾标记或文件结束条件终止的。对于存储在光盘/ SSD上的文件也是如此。

典型用例:用户在键盘上输入文本。程序读取前几个字符,并丢弃所有剩余的字符,直到行尾标记或文件结尾(因为某些缓冲区已满或之后的所有内容均为注释,等等)。

我正在使用 C89 ,但是我很好奇答案是否取决于所使用的C标准。

解决方法

你不能。

让我运行您的程序,然后在键盘的“ X”键上放一个砝码,然后去夏威夷度假。在那条路上,我被闪电击中而死。

除了'x'之外,没有其他输入。

或者,我可以决定键入Moby Dick的完整故事,而无需按Enter键。这可能需要几天时间。您的程序应该等多久才能决定也许我永远不会完成输入?

想要 要做什么?

,

查看评论中的所有讨论,看来您找错了地方:

这与键盘驱动程序或包装stdin无关。

您使用的编程语言也不是问题。

这取决于软件输入的目的。
基本上,作为程序员,您需要了解所需或需要多少输入,然后决定何时停止读取输入,即使仍然有有效的输入。

请注意,不仅有些设备可以在不触发EOF或行尾条件的情况下永久发送输入,而且有些程序可以永远快乐地读取输入。

这是设计使然。

常见示例可以在POSIX风格的OS(例如Linux)命令行工具中找到。 这是一个简单的示例:

cat /dev/urandom | hexdump

这将在您的计算机运行期间或直到您按下 Ctrl + C

时打印随机数

尽管cat将在没有更多内容可打印时(EOF或任何读取错误)将停止工作,但它不会期望这样的结束,因此除非您正在使用的实现中存在错误,否则应该很高兴永远运行。

所以真正的问题是: 您的程序什么时候需要停止阅读字符,为什么?

,

如果将stdin连接到始终提供“ \ n”以外的字符的设备,则不会发生上述情况。

例如/dev/zero之类的设备。是的,stdin可以连接到永不提供换行符或到达EOF且永远不会报告错误状况的设备。

答案似乎与设备的属性有关。

确实如此。

在哪里可以找到这些详细信息(可能是编译器,设备固件或设备硬件的两倍)?

通常,这是设备驱动程序的问题。而且在某些情况下(例如/dev/zero示例)就已经存在了。通常,驱动程序会执行对底层硬件敏感的操作,但原则上不必这样做。

尤其是,我想知道是否可以保证键盘输入是由行尾标记或文件结束条件终止的。

不。一般而言,只有且仅当按下键时,终端设备才会发送行结束标记。如果终端断开连接(但程序继续),或者用户明确导致发送了文件结束,则可能会发出文件结束条件的信号(例如,在Linux或Mac上键入或)。这些事件实际上都不需要在任何给定的程序运行中发生,而后者却很常见。

类似地,存储在光盘/ SSD上的文件。

通常,您可以依靠从普通文件中读取的数据来在文件本身中包含换行符的地方包含换行符。如果文件以文本模式打开,则系统特定的文本行终止符也将转换为换行符(如果不同)。文件没有必要包含任何这些文件,因此从常规文件读取程序可能永远不会看到换行符。

当文件位置在或超过文件数据的位置时,尝试读取时可以依靠EOF发出信号。

典型用例:用户在键盘上输入文本。程序读取前几个字符,并丢弃所有剩余的字符,直到行尾标记或文件结尾(因为某些缓冲区已满或之后的所有内容均为注释,等等)。

我认为你太努力了。

在某些情况下,读取行尾可能是合理的事情。如果该程序旨在支持交互使用,则期望最终会到达换行符是合理的。但是,尝试确保不能将无效数据馈送到您的程序是一个失败的原因。您的目标应该是接受合理可能的最广泛的输入,并在显示其他输入时优雅地失败。

如果您需要以逐行模式读取输入,则一定要这样做,并记录下来。如果仅每行的前 n 个字符对程序有意义,则也应记录下来。然后,如果您的程序永远不会在用户将其输入连接到位于其上而不是您上的/dev/zero上时终止。

另一方面,请尝试避免施加任意约束,尤其是在事物大小上。如果事物的大小没有自然限制,那么您引入的任何人为限制都将是不够的。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...