2012-01-10 61 views
0

我經常看到情況下,在一系列要求輸入printf語句中,某些 聲明不接受的輸入,用戶輸入的輸入錯誤接收輸入

printf_statement1: 

printf_statement2: /*Enter input here*/ 

即前語句1語句2被印刷,其允許用戶輸入的輸入,並且然後重複相同的與聲明3 & 即statement4

什麼提示這種情況?

我encounterd這一點,但沒有任何更多,在:

printf("\n\n\t\tName: "); 
scanf("%s", name); //initially used gets 
printf("\n\n\t\tType: ");  
scanf("%c", &type); 
printf("\n\n\t\tAddress: ");  //initially used gets 
scanf("%s", address); 
printf("\n\n\t\tDate - of - Birth: "); 
scanf("%s", dob); //initially used gets 

輸出:

Name: 
Type: I enter something! 
Address: 
Date - of - Birth: I enter something! 
+0

要澄清:你說你以前執行過給定的代碼,它實際上並沒有提示你提供名稱或地址的輸入,但現在呢? – 2012-01-10 03:07:35

+0

是的。想知道原因。 – user980411 2012-01-10 03:11:08

回答

-5

有時候在這樣的情況下,它是有幫助的閱讀之前,呼籲stdinfflush()它:

char name[40+1]; 
printf("\n\tName: "); 
fflush(stdin); 
scanf("%40s", name); 

根據具體情況,輸入緩衝區中可能會有一個換行符,導致您的第一個scanf跳過(無輸入)。

另請注意,您應該在scanf中指定緩衝區的大小,以避免buffer overflows

格式說明用於scanf的看起來像這樣:

%[*][width][modifiers]type 

寬度:指定要在當前讀出操作讀取的字符的最大數目

因此, %40s指定只能讀入40個字符的字符串。請注意,該緩衝區爲41個字符,爲NULL終止符留出空間。

編輯:一些消息來源(如thisthis)說,你應該避免調用fflush(stdin),這是不正確。 然而,所述Linux man page狀態:

對於輸入流,fflush()丟棄已經從底層文件取出任何緩衝的數據,但還沒有被應用程序所消耗。

符合C89,C99,POSIX.1-2001,POSIX.1-2008。 標準沒有規定輸入流的行爲。大多數其他實現的行爲與Linux相同。

此外MSDN隻字未提調用比下列其他fflush(stdin)

如果流是開放的輸入,fflush清除緩衝區的內容。

有人會認爲,如果調用fflush(stdin)是這樣的問題,在fflush的文檔的兩個最大的來源之一就不得不提到這一點。

+0

你稱之爲「%40s」?任何資源可能都有幫助。 – user980411 2012-01-10 03:16:04

+0

查看我編輯的回覆以及到'scanf'參考的鏈接。 – 2012-01-10 03:19:38

+0

@Downvoter:關心評論? – 2012-01-10 03:20:27

3

我知道這個問題已經被標記爲回答,但作爲fflush(stdin)令我生厭,我想替代張貼到結算stdin

void clear_stdin(void) 
{ 
    int c; 
    do { 
     c = fgetc(stdin); 
    } while (c != '\n' && c != EOF); 
} 

這將清除任何char s上行,直到一個新行或直到遇到了EOF。 (您可以將do..while的機身和條件粘貼到while循環的條件中,但我更願意這樣寫)。

例如,在想要讀取後調用該函數會很有用一個單一的char,以防止如果用戶輸入超過1個字符,似乎會跳過後續提示。

還考慮使用fgets()或提供寬度說明符scanf()以防止溢出。

1

,以取代「喬納森·萊因哈特」 fflush(標準輸入)的答案,我建議這個功能,這是符合標準:

void clean_stdin(void) 
{ 
    int c; 

    do { 
     c = getchar(); 
    } while (c != '\n' && c != EOF); 
} 
+0

我的答案不符合「標準」嗎?我沒有提供足夠的文檔嗎? – 2012-01-10 03:43:01

+0

fflush(stdin)的行爲根據標準被解除。那就是我的意思。所以它必須小心使用或不要用來避免未來可能出現的錯誤,因爲您不知道未來可能會對代碼做些什麼。但是,當然,你提供了一些有價值的信息。 (我投了你的詳細答案) – 2012-01-10 03:47:16

0

問題的根源在於"%c"轉換符不跳過空白。假設你輸入「Joe」作爲名字;輸入流將包含字符'J','o','e','\ n'。第一次調用scanf查找字符串("%s"轉換說明符);它會消耗'J','o'和'e',並在輸入流中保留'\ n'。爲了響應下一個提示,您鍵入一個字符'A',所以輸入流現在包含'\ n','A','\ n'。下一個電話scanf尋找單個字符;它會消耗第一個換行符並返回,在輸入流中留下'A'和'\ n'。

而不是沖洗stdin(這是不良好定義的操作根據語言的定義),最好避免使用用於交互式輸入"%c"轉換符;坦率地說,最好避免使用scanf進行交互式輸入,並使用fgets來代替。

一個快速和骯髒的解決辦法是從一個簡單的char改變type類型的char陣列和讀它作爲一個字符串:

char type[2]; 
... 
fgets(type, sizeof type, stdin); 

這將跳過卡在輸入任何新行流而不必沖洗任何東西。那麼你只需使用type[0]作爲你的類型值。

編輯

如果你不想改變type類型,你可以做這樣的事情:

#include <ctype.h> 
... 
while ((type = fgetc(stdin)) && isspace(type)) 
    ; 

將從stdin讀取單個字符,直到它看到一個非 - 空白字符。