根据我的阅读,Linux终端(默认设置)缓冲输入,仅在收到EOF
或'\n'
后发送。
当我循环c = getchar();
并检查每个c
是否为EOF
时(结束然后休息)我需要执行CTRL-D 两次才能停止读取,因为终端总是消耗第一个EOF
(我知道可以将终端更改为原始终端,但这可能有点矫枉过正)。
但是,当我检查c
'\n'
(也发送输入)时,它将不被消耗。
示例:
'a'
,'b'
,'c'
,'\n'
'a'
,'b'
,'c'
'a'
,'b'
,'c'
,EOF
'a'
,'b'
,'c'
,'\n'
,EOF
这不是很不一致吗?或者它背后有什么理由吗?
我想解析包含空格的输入,因此无法检查'\n'
但是EOF
- 是否可以在不将终端更改为原始的情况下进行?
我也试过了feof(stdin)
,但显然这不起作用:/
答案 0 :(得分:3)
你误解了Ctrl-D的作用。 Ctrl-D不发送EOF - 它将终端缓冲区的当前内容发送到文件描述符,因此它将在下一次read
调用时返回。
另一方面,EOF是read
调用返回0个字符的时间。所以当终端缓冲区为空时,ctrl-D ONLY会导致EOF。
答案 1 :(得分:2)
这不是它的工作原理。 ^D
发送当前缓冲的行,所以如果你没有在换行后立即点击它,你的程序将看不到空读,也不会知道输入已经结束。所以你需要另一个^D
来发送任何内容。但是你的程序永远不会看到^D
。
实际上,您可以使用stty
更改终端的EOF
字符,以便例如^N
结束输入;你的程序运行完全相同,因为它不依赖于EOF键盘字符的值。
PS。由于您尝试编写C程序:输入调用在尝试读取文件时返回EOF
,并获取空缓冲区(0个字符)。实际上,EOF
不是您想象的^D
,而是-1
:选择此值是因为它不适合一个字节,而{{1}可以合法地返回任何可能的字节(是的,偶数read()
)。这就是'\04' aka ^D
的签名表示返回getchar()
。