使用 getchar() 读取输入时 Ctrl-Z 表现异常
Ctrl-Z behaving strangely when reading input with getchar()
我无法理解 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
之前,文本不会发送到程序的输入缓冲区以供读取。
OS-问题
在 Linux(和其他 *nixen)上,EOL 字符是 LF ('\n'
)。
但是在 Windows 上是一个字符序列:CR LF ("\r\n"
).
为了使相同的代码在 *nix 和 Windows 上工作,当 C 打开控制台文件流时,它在 文本模式 中这样做在其他方面与 binary mode 相同,除了 CR LF 被报告给你只是 LF。因此,您上面的实验报告了三个字符('m'、'y' 和“\n”)而不是四个。
“Why doesn't getchar() recognise return as EOF on the console?
的一个答案中解释了为什么它不会在第一个 CTRL-z
处停止
With Windows, the CTRLz can be entered anywhere on the line, but still needs to be followed by a newline.
情况 1(my
+ 换行符)=> 3 个字符
对于其他输入,很明显停止输入的CTRLz是最后一个,后面跟一个换行符。似乎 CTRLz 不是单独在行上将字符转换到行尾,这将解释 6
两种情况下的结果。
在 Windows 命令行上,默认行为是:
- ^Z 只有在行首时才表现为 EOF
- 如果 ^Z 在该行的其他位置,则 ^Z 之后的字符将从流中删除(包括导致缓冲区被发送到应用程序的换行符),但不会引发 EOF 条件。但是 ^Z 字符本身 是 仍然被流 return 编辑。
此外,控制台不会立即对 ^Z 字符执行操作 - 该行仍处于缓冲状态,并且在按下 return 键之前不会发送到应用程序。
请记住,您的程序会计算换行符,因此:
- 在示例 1 中有一个换行符是
3
结果的一部分
- 在例子2中,第一个^Z被计算在内,第一行的后半部分不被计算,并且(仅)第二行的换行被计算
- 例3中前两个^Z字符被统计,换行不被统计,第一行的后半部分不被统计
在 Unix 系统上,^D 在控制台上用作 EOF 字符,it's behavior is standardized like so(与 Windows 的行为略有不同):
[EOF is a] Special character on input, which is recognized if the
ICANON flag is set. When received, all the bytes waiting to be read
are immediately passed to the process without waiting for a newline,
and the EOF is discarded. Thus, if there are no bytes waiting (that
is, the EOF occurred at the beginning of a line), a byte count of zero
shall be returned from the read(), representing an end-of-file
indication.
主要区别是在 Unix 上 EOF 键不等待 return 被按下。另一个区别是,在 Windows 上,如果 EOF 不在行的开头,则 ^Z 字符会出现在流中。
我无法理解 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
之前,文本不会发送到程序的输入缓冲区以供读取。
OS-问题
在 Linux(和其他 *nixen)上,EOL 字符是 LF ('\n'
)。
但是在 Windows 上是一个字符序列:CR LF ("\r\n"
).
为了使相同的代码在 *nix 和 Windows 上工作,当 C 打开控制台文件流时,它在 文本模式 中这样做在其他方面与 binary mode 相同,除了 CR LF 被报告给你只是 LF。因此,您上面的实验报告了三个字符('m'、'y' 和“\n”)而不是四个。
“Why doesn't getchar() recognise return as EOF on the console?
的一个答案中解释了为什么它不会在第一个CTRL-z
处停止
With Windows, the CTRLz can be entered anywhere on the line, but still needs to be followed by a newline.
情况 1(my
+ 换行符)=> 3 个字符
对于其他输入,很明显停止输入的CTRLz是最后一个,后面跟一个换行符。似乎 CTRLz 不是单独在行上将字符转换到行尾,这将解释 6
两种情况下的结果。
在 Windows 命令行上,默认行为是:
- ^Z 只有在行首时才表现为 EOF
- 如果 ^Z 在该行的其他位置,则 ^Z 之后的字符将从流中删除(包括导致缓冲区被发送到应用程序的换行符),但不会引发 EOF 条件。但是 ^Z 字符本身 是 仍然被流 return 编辑。
此外,控制台不会立即对 ^Z 字符执行操作 - 该行仍处于缓冲状态,并且在按下 return 键之前不会发送到应用程序。
请记住,您的程序会计算换行符,因此:
- 在示例 1 中有一个换行符是
3
结果的一部分 - 在例子2中,第一个^Z被计算在内,第一行的后半部分不被计算,并且(仅)第二行的换行被计算
- 例3中前两个^Z字符被统计,换行不被统计,第一行的后半部分不被统计
在 Unix 系统上,^D 在控制台上用作 EOF 字符,it's behavior is standardized like so(与 Windows 的行为略有不同):
[EOF is a] Special character on input, which is recognized if the ICANON flag is set. When received, all the bytes waiting to be read are immediately passed to the process without waiting for a newline, and the EOF is discarded. Thus, if there are no bytes waiting (that is, the EOF occurred at the beginning of a line), a byte count of zero shall be returned from the read(), representing an end-of-file indication.
主要区别是在 Unix 上 EOF 键不等待 return 被按下。另一个区别是,在 Windows 上,如果 EOF 不在行的开头,则 ^Z 字符会出现在流中。