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

如何解决保证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上时终止。

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-