为什么getchar()只在行首识别EOF?

6
这个例子来自K&R书籍。
#include<stdio.h>


main()
{
    long nc;

    nc = 0;
    while(getchar() != EOF)
        ++nc;
    printf("%ld\n", nc);
}

enter image description here

你能解释一下为什么它会这样工作吗?谢谢。

^Z^Z也不起作用(除非它在一行的开头)

enter image description here


看不到例子..你能在这里发布代码吗? - Rohit Jain
4
这是 Windows 命令行的“特性”。在 Unix 系统中,你可以通过按两次 Ctrl+D 键来在一行的末尾输入 EOF,也可以尝试按两次 Ctrl+Z 键(或从文件重定向输入)。 - Fred Foo
无论如何,连续按两次或更多次 Ctrl+Z 都不起作用。 - Vorgin
我知道这完全不相关,打扰了,但如果只用纯文本就足够的话,最好不要浪费图像空间,在这种情况下,SO也可以很好地进行语法高亮 :) - legends2k
4个回答

1

传统的UNIX解释tty EOF字符是在读取缓存在烹饪tty行缓冲区内的任何内容后使阻塞read返回。在新行的开头,这意味着read返回0(读取零字节),巧合的是,0大小的read是普通文件上检测到文件结束条件的方式。

这就是为什么在一行中的第一个EOF只是强制开始读取该行,而不是使C运行时库检测到文件结束的原因。两个EOF字符连续出现会产生0大小的读取,因为第二个强制应用程序读取一个空缓冲区。

$ 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<CR> <=== 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上,kernel32调用甚至系统调用都没有对^Z进行特殊处理)。这就是为什么它可能会在输入行的中间检测到^Z^Z后面的EOF。


不会的。如果在这行之前有其他字符,^Z^Z或更多就无法起作用。 - Vorgin

0
程序只会在输入的实际末尾读取EOF。如果您的终端/操作系统/任何其他东西只允许文件在行的开头结束,那么您将在那里找到它们。我认为这是对老式终端的回溯,其中数据仅一次传输一行(据我所知,这可以追溯到打孔卡片阅读器)。
尝试从预先准备了EOF中线的文件中读取数据。您甚至可能会发现某些编辑器使此变得困难!您的程序应该可以正常处理此类输入。

0

EOF 表示“文件结束”。换行符(当您按下回车键时发生的情况)不是文件的结尾,而是行的结尾,因此换行符不会终止此循环。

根据操作系统的不同,EOF 字符只有在它是一行中的第一个字符时才能起作用,即在 Enter 后的第一个字符。由于控制台输入通常是面向行的,因此系统可能也无法识别 EOF 字符,直到您跟随其后输入了 Enter


0

我碰巧和你有同样的问题。当我想结束函数getchar()时,我必须输入2个EOF或输入一个<ENTER>加上一个EOF

这里是我搜索到的更简单的答案:

如果终端中有字符输入,EOF将起到停止此输入的作用,这将引起新的输入;而如果没有输入发生,或者换句话说,当getchar()正在等待新的回车(例如您刚刚完成输入或EOF),您即将输入的EOF等于“文件结尾”,这将导致程序停止执行函数getchar()。

PS:这个问题发生在使用getchar()时。我认为这个答案更容易理解,但可能对你来说不是这样,因为它是从中文翻译过来的...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接