2009-06-16 46 views
7

我已经开始阅读“The C Programming Language”(K & R),我对getchar()函数有怀疑。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

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

编辑:

感谢大家的答案,我开始得到它现在...只有一个陷阱:

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

+1

你的第二种方法只是循环直到EOF。 CTRL + D(在典型的unix系统上)不会导致EOF,除非你自己在一行上。写完一个字符后按CTRL + D不会导致EOF – nos 2009-06-16 23:19:41

回答

4

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

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


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

+0

@Carson,正好! EOF必须在它自己的行中。非常感谢! – 2009-06-16 23:14:32

+0

不客气。我也在努力,但也解决了它,这要归功于它:) – 2009-06-16 23:15:18

9

getchar从标准输入获取单个字符,在这种情况下是键盘缓冲区。

在第二个例子中,getchar功能是在一个循环while它继续,直到遇到一个EOF,所以它会不断循环并检索一个字符(和打印的字符屏幕),直到输入变空。

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

呵呵,不要因为问这个问题而感到不舒服 - 当我第一次遇到这个问题时,我感到很困惑。

3

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

2

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

一旦你使用显示的putchar(c)第一个字符(t),你忘了通过分配的下一个字符(o)为变量c,取代了以往的值(t)中的c值。

1

的代码是功能上等同于

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

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

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提升到试图读取的所有人)

0

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

而在第二个代码中,getchar和putchar存在于while循环中。在这种情况下,程序一直读取字符(正如循环所做的那样),直到达到EOF字符(^ D)。在那一点上,它匹配c!= EOF,并且由于条件不满足,它会从循环中出来。现在没有更多的语句可以执行。所以程序在这一点终止。

希望这会有所帮助。