2009-06-16 45 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,並且由於條件不滿足,它會從循環中出來。現在沒有更多的語句可以執行。所以程序在這一點終止。

希望這會有所幫助。