为什么Linux(?) - 终端没有"消费" ' \ n' EOF?

时间:2015-10-24 17:39:19

标签: c terminal stdin eof getchar

根据我的阅读,Linux终端(默认设置)缓冲输入,仅在收到EOF'\n'后发送。

当我循环c = getchar();并检查每个c是否为EOF时(结束然后休息)我需要执行CTRL-D 两次才能停止读取,因为终端总是消耗第一个EOF(我知道可以将终端更改为原始终端,但这可能有点矫枉过正)。

但是,当我检查c '\n'(也发送输入)时,它将不被消耗。

示例:

  • 输入:" abc \ n"
    • 读取的字符为:'a''b''c''\n'
  • 输入:" abc"和Ctrl-D
    • 读取的字符为:'a''b''c'
  • 再次输入:" abc",Ctrl-D和Ctrl-D
    • 读取的字符为:'a''b''c'EOF
  • 输入:" abc",返回和Ctrl-D
    • 读取的字符为:'a''b''c''\n'EOF

这不是很不一致吗?或者它背后有什么理由吗?

我想解析包含空格的输入,因此无法检查'\n'但是EOF - 是否可以在不将终端更改为原始的情况下进行?

我也试过了feof(stdin),但显然这不起作用:/

2 个答案:

答案 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()

的原因