`getchar()`在哪里存储用户输入?

时间:2009-06-16 22:51:04

标签: c loops io kernighan-and-ritchie

我开始阅读“The C Programming Language”(K& R),我对getchar()功能有疑问。

例如这段代码:

#include <stdio.h>

main()
{
  int c;

  c = getchar();
  putchar(c);
  printf("\n");   
}

键入toomanychars + CTRL + D (EOF)仅打印t。我认为这是预期的,因为它是第一个引入的角色。

然后是另一段代码:

#include <stdio.h>

main()
{
  int c;

  while((c = getchar()) != EOF) 
    putchar(c);
}

键入toomanychars + CTRL + D (EOF)会打印toomanychars

我的问题是,如果我只有一个char变量,为什么会这样?其余的字符存储在哪里?

修改

感谢大家的答案,我现在开始明白......只有一个问题:

第一个程序在给出 CTRL + D 时退出,而第二个程序打印整个字符串然后等待更多用户输入。为什么它等待另一个字符串并且不像第一个字符串那样退出?

7 个答案:

答案 0 :(得分:9)

getchar从标准输入中获取单个字符,在本例中为键盘缓冲区。

在第二个示例中,getchar函数位于while循环中,一直持续到遇到EOF,因此它将继续循环并检索一个字符(并打印字符)屏幕)直到输入变空。

getchar的连续调用将获得来自输入的连续字符。

哦,问这个问题也不错 - 当我第一次遇到这个问题时,我很困惑。

答案 1 :(得分:5)

它将输入流视为文件。就好像你打开了一个包含文本“toomanychars”的文件,并一次读取或输出一个字符。

在第一个例子中,在没有while循环的情况下,就像你打开一个文件并读取第一个字符,然后输出它。但是,第二个示例将继续读取字符,直到它获得文件结束信号(在您的情况下为ctrl+D),就像从磁盘上的文件读取一样。


在回复您更新的问题时,您使用的操作系统是什么?我在我的Windows XP笔记本电脑上运行它并且工作正常。如果我按下回车键,它会打印出我到目前为止的内容,换行,然后继续。 (在您按下回车键之前,getchar()函数不会返回,这是在调用输入缓冲区时没有任何内容的情况下)。当我按CTRL+Z(Windows中的EOF)时,程序终止。请注意,在Windows中,EOF必须位于其自己的行上才能在命令提示符中计为EOF。我不知道这种行为是否在Linux或任何你可能正在运行的系统中被模仿。

答案 2 :(得分:4)

这里的东西是缓冲的。例如putchar写入的stdout FILE *可能是line.buffered。当程序结束(或遇到换行符)时,这样的FILE *将被fflush()编辑,你会看到输出。

在某些情况下,您正在查看的实际终端可能会缓冲输出直到换行,或者直到终端本身被指示刷新它的缓冲区,这可能是当前前台程序退出时的情况,因为它想要呈现新提示。

现在,这里的实际情况可能是,它是缓冲的输入(除了输出:-))当你按下它时,它会出现在你的终端窗口上。但是终端不会将这些字符发送到您的应用程序,它将缓冲它,直到您使用Ctrl + D指示它是输入结束,并且可能也是换行符。 这是另一个版本,可以思考:

int main() {
  int c;
   while((c = getchar()) != EOF) {
     if(c != '\n')
        putchar(c);
   }
    return 0;
}

尝试为您的程序输入一个句子,然后按Enter键。如果你发表评论,也要这样做 if(c!='\ n')也许您可以确定您的输入,输出或两者是否以某种方式缓冲。 如果你运行上面这样会变得更有趣: ./mytest | ./mytest

(另请注意,CTRD + D不是字符,也不是EOF。但在某些系统上,它会导致关闭输入流,这会再次将EOF提升给试图从流中读取的任何人。)

答案 3 :(得分:3)

您的第一个程序只读取一个字符,将其打印出来然后退出。你的第二个程序有一个循环。它会一直读取一个字符并将其打印出来,直到它读取一个EOF字符。在任何给定时间只存储一个字符。

答案 4 :(得分:2)

您只使用变量c一次包含一个字符。

使用t显示第一个字符(putchar(c))后,您会通过将下一个字符(c)分配给o来忘记c的值变量t,替换之前的值({{1}})。

答案 5 :(得分:1)

代码在功能上等同于

main(){
  int c;
  c = getchar();
  while(c != EOF) {
    putchar(c);
    c = getchar();
  }
}

您可能会发现此版本更易于理解。将赋值放在条件中的唯一原因是避免必须两次输入'c = getchar()'。

答案 6 :(得分:0)

对于您更新的问题,在第一个示例中,只读取一个字符。它永远不会达到EOF。程序终止,因为在完成printf指令后没有任何操作可做。它只读一个字符。打印出来。放入换行符。然后终止,因为它没有更多的事要做。它不会读取多个字符。

然而,在第二个代码中,getchar和putchar存在于while循环中。在此,程序继续逐个读取字符(因为它是通过循环这样做),直到达到EOF字符(^ D)。此时,它匹配c!= EOF,并且由于条件不满足,因此它从循环中出来。现在没有更多的语句可以执行了。所以程序终止了。

希望这有帮助。