使用getchar()读取输入时,Ctrl-Z行为异常

时间:2017-09-26 19:34:31

标签: c windows eof

我无法理解 Ctrl Z 的工作方式。请原因解释以下输出。

#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  

3 个答案:

答案 0 :(得分:2)

Why doesn't getchar() recognise return as EOF on the console?

的答案之一解释了为什么它不会停留在第一个CTRL-z
  

使用Windows,可以在该行的任何位置输入 CTRL z ,但仍需要后跟换行符。

说明案例1(my + linefeed)=&gt; 3个字符

对于其他输入,很明显停止输入的 CTRL z 是最后一个,后跟换行符。似乎 CTRL z 并不是单独在线上将其后的字符拉到行尾,这将在两种情况下解释6结果。

答案 1 :(得分:1)

行尾(EOL)字符也由getchar()读取并计算,因此它包含在您的计数中。

控制-Z

控制台输入通常(并且在Windows上),行缓冲,这意味着在用户按下Enter之前,您的程序将看不到任何内容。

因此,您可以在任何地方键入^Z,但在按Enter之前,文本不会发送到您的程序的输入缓冲区以供读取。

OS-问题

在Linux(和其他* nixen)上,EOL字符是LF('\n')。 但在Windows上它是一个字符序列:CR LF("\r\n")。

为了使相同的代码在* nix和Windows上都能正常工作,当C打开控制台文件流时,它会在文本模式中完成,否则它与二进制模式相同除了CR LF报告给你只是LF。因此,上面的实验报告了三个字符('m','y'和'\ n')而不是四个字符。

答案 2 :(得分:0)

在Windows命令行上,默认行为是:

  • ^ Z仅在行开头时表现为EOF
  • 如果^ Z在行中的其他位置,那么^ Z之后的字符将从流中删除(包括导致缓冲区被发送到应用程序的换行符),但不会引发EOF条件。但是,^ Z字符本身 仍然由流返回。

此外,控制台不立即对^ Z字符起作用 - 该行仍然是缓冲的,并且在按下返回键之前不会发送到应用程序。

请记住,您的计划会计算换行符,所以:

  • 在示例1中,有一个换行符是3结果
  • 的一部分
  • 在示例2中,第一个^ Z被计算,第一行的后半部分不计算,而且(仅)第二行的换行计算
  • 在示例3中,计算前两个^ Z字符,不计算换行符,并且不计算第一行的后半部分

在Unix系统上,^ D用作控制台上的EOF字符,it's behavior is standardized like so(与Windows的行为略有不同):

  

[EOF是a]输入上的特殊字符,如果是,则识别   ICANON标志已设置。收到后,等待读取的所有字节   立即传递到进程而无需等待换行符,   并且EOF被丢弃。因此,如果没有字节等待(那   是,EOF发生在一行的开头),字节数为零   应从read()返回,表示文件结尾   指示。

主要区别在于,在Unix上,EOF键不等待返回被按下。另一个区别是,在Windows上,如果EOF不在行的开头,则^ Z字符会显示在流中。