2012-09-29 60 views
7

我難以理解getchar()。在下面的程序如預期getchar工作:使用scanf時getchar不停止

#include <stdio.h> 


int main() 
{ 
    printf("Type Enter to continue..."); 
    getchar(); 
    return 0; 
} 

然而,在下面的程序,getchar不會造成延遲,程序結束:

#include <stdio.h> 

int main() 
{ 
    char command[100]; 
    scanf("%s", command); 
    printf("Type Enter to continue..."); 
    getchar(); 
    return 0; 
} 

我有以下weired解決辦法,其中工程,但我不明白爲什麼:

#include <stdio.h> 

int main() 
{ 
    char command[100]; 
    int i; 
    scanf("%s", command); 
    printf("Type Enter to continue..."); 
    while (getchar() != '\n') { 
     i=0; 
    } 
    getchar(); 
    return 0;  
} 

所以我的問題是:
1.什麼是scanf在做什麼?爲什麼scanf這樣做?
2.我的工作爲什麼在工作?
3.什麼是仿效以下Python代碼的好方法:

raw_input("Type Enter to continue") 

回答

9

您鍵入一個新行後,輸入只發送到該程序,但

scanf("%s", command); 

離開換行符在由於%s(1)格式在某些非空白符後遇到第一個空白字符時停止,因此getchar()立即返回該換行符,並且不需要等待進一步輸入。

解決方法是可行的,因爲它在再次調用getchar()之前清除輸入緩衝區中的換行符。

要模仿的行爲,在打印消息前清除輸入緩衝區,

scanf("%s", command); 
int c; 
do { 
    c = getchar(); 
}while(c != '\n' && c != EOF); 
if (c == EOF) { 
    // input stream ended, do something about it, exit perhaps 
} else { 
    printf("Type Enter to continue\n"); 
    getchar(); 
} 

(1)注意,使用%sscanf是非常不安全的,你應該限制輸入到你的緩衝區可保持字段寬度,scanf("%99s", command)將讀取至多99個(sizeof(command) - 1))字符到command,爲0終止符留下空間。

+0

+1我不知道當'stdin'仍然連接到控制檯時EOF是否可以嗎?毫無疑問,如果'stdin'被重定向到一個文件就會發生 - 使我的答案不夠健壯。 – Clifford

+0

不太可能,但當然可以鍵入Ctrl-D(Windows上的Ctr-Z,iirc)來關閉流。感謝編輯,順便說一句。 –

-2

取指令後輸入flush stdin。

fflush(stdin); 

但沖洗不確定的行爲輸入流的結果(儘管微軟的C庫定義的行爲作爲一個擴展)。

+2

對於輸入流,fflush()未定義。 – Clifford

+1

-1:將'fflush()'應用於輸入流(或輸入/輸出流爲其輸入的最後一個操作)是[C標準](http:///www.open-std.org/JTC1/sc22/wg14/www/docs/n1570.pdf)。 – pmg

+0

請注意,雖然這與Microsoft的C庫一起工作,但它當然不適用於GNU C庫。避免。 – Clifford

2

空格是5y3%s格式說明符的分隔符,而換行符被視爲空白,因此它仍保持緩衝。控制檯輸入通常是面向行的,因此隨後調用getchar()將立即返回,因爲「行」保持緩衝。

scanf("%s", command); 
while(getchar() != '\n'){ /* flush to end of input line */ } 

同樣,如果你使用的getchar()或%C來到達一個字符,你通常需要衝洗管路,但在這種情況下,輸入的字符本身可能是一個換行符所以你需要一個稍微不同的解決方案:

scanf("%c", ch); 
while(ch != '\n' && getchar() != '\n'){ /* flush to end of input line */ } 

同樣的的getchar():

ch = getchar(); 
while(ch != '\n' && getchar() != '\n'){ /* flush to end of input line */ } 

的明智的做法當然是包裝這些解決方案爲獨立的專用輸入函數,您可以重複使用,也可以用作放置常用輸入驗證和錯誤檢查代碼的地方(如Daniel Fischer的答案,明智地檢查EOF - 您通常希望避免必須重複這些檢查和錯誤處處)。

2

我寧願先使用fgets,然後用sscanf來解析輸入。我一直在做這樣的事情很長一段時間,這種行爲比使用普通的scanf更容易預測。

0

那麼,我有更容易的事情:添加另一個getchar() ...問題解決!

+0

並不一定能解決這個問題,你仍然可能在緩衝區多於一個字節和'的getchar()'然後將立即返回。 – Pablo

相關問題