提问人:Prashant Gupta 提问时间:9/27/2017 最后编辑:chqrliePrashant Gupta 更新时间:9/27/2017 访问量:940
Ctrl-Z 在使用 getchar() [duplicate] 读取输入时行为异常
Ctrl-Z behaving strangely when reading input with getchar() [duplicate]
问:
我无法理解它的工作方式。请解释以下输出并说明原因。CtrlZ
#include <stdio.h>
int main (void) {
int ch, i = 0;
while ((ch = getchar()) != EOF)
i++;
printf("\n%d", i);
return 0;
}
输入 1:
my
^Z
输出 1:
3
输入 2:
my^Zmy
my
^Z
输出 2:
6
输入 3:
my^Zmy
my^Z
^Z
输出 3:
6
答:
行尾 (EOL) 字符也由 读取和计数,因此它包含在计数中。getchar()
Ctrl-Z 组合键
控制台输入通常(并且在 Windows 上)行缓冲,这意味着在用户按 之前,您的程序不会看到任何内容。Enter
因此,您可以在任何地方键入,但在您按下之前,文本不会发送到程序的输入缓冲区进行读取。^Z
Enter
操作系统问题
在 Linux(和其他 *nixen)上,EOL 字符是 LF ()。
但在 Windows 上,它是一个字符序列:CR LF ()。'\n'
"\r\n"
为了使相同的代码在 *nix 和 Windows 上都有效,当 C 打开控制台文件流时,它会在文本模式下进行,该模式在其他方面与二进制模式相同,只是 CR LF 仅作为 LF 报告给您。因此,上面的实验报告了三个字符('m'、'y' 和 '\n'),而不是四个。
“为什么它没有在第一个停止,在为什么 getchar() 在控制台上不将 return 识别为 EOF?CTRL-z
在 Windows 中,可以在行上的任何位置输入 ,但仍然需要后跟换行符。CTRLz
这说明了情况 1 ( + 换行符) => 3 个字符my
对于其他输入,很明显,停止输入的是最后一个,后跟换行符。似乎不是唯一的一行,直到行尾才删除它后面的字符,这将解释这两种情况下的结果。CTRLzCTRLz6
在 Windows 命令行上,默认行为为:
- ^Z 仅在行首时表现为 EOF
- 如果 ^Z 位于行中的其他位置,则 ^Z 后面的字符将从流中删除(包括导致缓冲区发送到应用程序的换行符),但不会引发 EOF 条件。但是,^Z 字符本身仍由流返回。
此外,控制台不会立即对 ^Z 字符执行操作 - 该行仍处于缓冲状态,并且在按下返回键之前不会发送到应用程序。
请记住,您的程序会计算换行符,因此:
- 在示例 1 中,有一个换行符是结果的一部分
3
- 在示例 2 中,计算第一个 ^Z,不计算第一行的后半部分,并且计算(仅)第二行的换行符
- 在示例 3 中,计算前两个 ^Z 字符,不计算换行符,不计算第一行的后半部分
在 Unix 系统上,^D 被用作控制台上的 EOF 字符,它的行为是标准化的(与 Windows 的行为略有不同):
[EOF是]输入上的特殊字符,如果 ICANON 标志已设置。接收到时,所有等待读取的字节 立即传递到进程,无需等待换行符, 并且 EOF 被丢弃。因此,如果没有字节等待( 是,EOF 发生在一行的开头),字节计数为零 应从 read() 返回,表示文件结束 指示。
主要区别在于,在 Unix 上,EOF 键不会等待按下回车键。另一个区别是,在 Windows 上,如果 EOF 不在行的开头,则 ^Z 字符将显示在流中。
评论
With Windows, the CTRLz can be entered anywhere on the line, but still needs to be followed by a newline.