为什么getchar()仅在行的开头识别EOF?
这个例子来自K&R书
#include main() { long nc; nc = 0; while(getchar() != EOF) ++nc; printf("%ld\n", nc); }
你能解释一下为什么它会这样运作吗? 谢谢。
^ Z ^ Z也不起作用(除非它在一行的开头)
tty EOF
字符的传统UNIX解释是在读取在烹饪的tty行缓冲区内缓冲的内容之后使阻塞read
返回。 在新行的开头,它表示read
返回0(读取零字节),顺便说一下,0大小的read
是检测普通文件上文件结束条件的方式。
这就是为什么行中间的第一个 EOF
强制read
行的开头,而不是让C运行时库检测到文件的结尾。 一行中的两个 EOF
字符产生0大小的读取,因为第二个EOF
字符强制应用程序read
空缓冲区。
$ cat foo[press ^D]foo <=== after ^D, input printed back before EOL, despite cooked mode. No EOF detected foo[press ^D]foo[press ^D] <=== after first ^D, input printed back, and on second ^D, cat detects EOF $ cat Some first line <=== input Some first line <=== the line is read and printed [press ^D] <=== at line start, ^D forces 0-sized read to happen, cat detects EOF
我假设您的C运行时库模仿上面描述的语义(在Windows上调用级别没有特别处理^Z
,更不用说Windows上的系统调用)。 这就是为什么即使在输入线的中间它也可能在^Z^Z
之后检测到EOF。
程序将仅在输入的实际结束时读取EOF
。 如果您的终端/操作系统/任何只允许文件在一行开头结束,那么您就可以找到它们。 我相信这是老式终端的倒退,数据一次只传输一行(据我所知,它可以追溯到穿孔读卡器)。
尝试从您使用EOF中线准备的文件中读取数据。 你甚至可能会发现有些编辑会让这很困难! 你的程序应该可以正常工作作为输入。
EOF表示“文件结束”。 换行符(当你按Enter键时会发生这种情况)不是文件的结尾,它是一行的结尾,所以换行符不会终止此循环。
根据操作系统的不同, EOF
字符只有在一行中的第一个字符(即Enter
后面的第一个字符)才有效。 由于控制台输入通常是面向行的,因此系统在您按Enter
之后才会识别EOF
字符。
我碰巧和你有同样的问题。 当我想结束函数getchar()
,我必须输入2 EOF
或输入
加上EOF
。
这是我搜索这个问题的一个更简单的答案:
如果终端中有字符进入,EOF将起到阻止此进入的作用,这将引起新的进入; 而如果没有进入,或者换句话说,当getchar()等待新的输入(例如你刚刚完成输入或EOF)时,你现在要输入的EOF等于“结束”文件“,这将导致程序停止执行函数getchar()。
PS:当你使用getchar()
时会出现问题。 我认为这个答案更容易理解,但也许不适合你,因为它是从中文翻译出来的……