7

我已经开始阅读“ The C Programming Language ”(K&R)并且我对这个函数有疑问getchar()

例如这段代码:

#include <stdio.h>

main()
{
  int c;

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

键入toomanychars++ (EOF) 仅CTRL打印. 我认为这是意料之中的,因为它是第一个引入的角色。Dt

但是接下来的另一段代码:

#include <stdio.h>

main()
{
  int c;

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

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

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

编辑:

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

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

4

7 回答 7

9

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

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

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

哦,不要因为问这个问题而感到难过——当我第一次遇到这个问题时我也很困惑。

于 2009-06-16T22:54:23.567 回答
5

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

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


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

于 2009-06-16T22:53:41.993 回答
4

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

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

现在,这里的实际情况可能是,这是缓冲的输入(除了输出:-))当您按下键时,它会出现在终端窗口上。但是,终端不会将这些字符发送到您的应用程序,它会缓冲它,直到您使用 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 任何试图从流中读取的人。)

于 2009-06-16T23:03:03.380 回答
3

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

于 2009-06-16T22:55:18.667 回答
2

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

使用显示第一个字符 ( t)后,通过将下一个字符 ( ) 分配给变量,替换前一个值 ( ) putchar(c),您就忘记了 的值。coct

于 2009-06-16T22:57:33.077 回答
1

该代码在功能上等同于

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

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

于 2009-06-16T23:00:53.837 回答
0

对于您更新的问题,在第一个示例中,仅读取一个字符。它永远不会到达 EOF。程序终止,因为在完成 printf 指令后它无事可做。它只读取一个字符。打印它。换行。然后终止,因为它无事可做。它不会读取多个字符。

而在第二个代码中,getchar 和 putchar 存在于 while 循环中。在这种情况下,程序继续一个一个地读取字符(因为它是由循环执行的),直到到达 EOF 字符(^D)。此时,它匹配 c!=EOF 并且由于不满足条件,它退出循环。现在没有更多的语句要执行。所以程序在此时终止。

希望这可以帮助。

于 2011-05-03T06:47:06.287 回答