2012-06-21 73 views
5

當我想檢查輸入的是數字時,遇到了這個問題。如果我成功輸入一個數字,scanf函數將返回1。所以這裏是我寫的:當你輸入12ab到scanf(「%d」,&argu)時,會發生什麼?

int argu; 
while(scanf("%d",&argu)!=1){ 
    printf("Please input a number!\n"); 
} 

但是當我輸入像abcd這樣的東西,循環會永遠不會停止提示。

我在網上查了一下,發現它與緩存有關,我需要清理它,以便scanf可以獲取新數據。所以我嘗試了fflush,但沒有奏效。

然後我看到了這一點:

int argu,j; 
while(scanf("%d",&argu)!=1){ 
    printf("Please input a number!\n"); 
    while((j=getchar())!='\n' && j != '\n'); 
} 

然後當像「ABCD」我輸入的東西它的工作好,它提示我輸入。但是當我輸入像'12ab'這樣的東西時,它不會再工作。

那麼有沒有一種方法可以檢查scanf的輸入(「%d」,& arguments)實際上是一個數字,並提示輸入另一個輸入,如果它不是?

編輯

我看到了答案,並通過使用while(*eptr != '\n')解決我的問題。

請注意,fgets函數實際上讀取數組'\ n',並且fget沒有。所以要小心。

回答

4

最好是使用fgets()來讀取整行,然後檢查它,而不是試圖從輸入流中「實時」解析。

這樣更容易忽略無效輸入。

使用fgets()然後只是strtol()轉換爲數字,它會很容易看到數字後面是否有尾隨數據。

例如:

char line[128]; 

while(fgets(line, sizeof line, stdin) != NULL) 
{ 
    char *eptr = NULL; 
    long v = strtol(line, &eptr, 10); 
    if(eptr == NULL || !isspace(*eptr)) 
    { 
    printf("Invalid input: %s", line); 
    continue; 
    } 
    /* Put desired processing code here. */ 
} 
+0

使用像fgets(s,10,stdin)的代碼? – Gnijuohz

+0

謝謝!我不知道斯托爾。學到了很多! – Gnijuohz

+0

對不起,你能解釋一下if(eptr == NULL ||!isspace(* eptr))嗎?當使用你提供的代碼時,像'12 34'這樣的輸入被接受,但它們不應該是。當我輸入'1234'eptr會指出什麼,'12ab'和'12 34'怎麼樣? – Gnijuohz

1

我會建議得到輸入作爲一個字符串,併爲您在它非數字字符。如果輸入有效,則將字符串轉換爲int sscanf(str,"%d",&i);或顯示錯誤。

1

只需在循環中調用scanf(「%* [^ \ n] \ n」),它將放棄「緩存」。

+0

我試過了。它沒有工作。 – Gnijuohz

+0

這是因爲'fflush'的行爲沒有爲輸入流定義。請參閱[C語言標準](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf),第7.19.5.2節第2段。 –

+0

您是對的。不過,希望編輯現在是正確的(基於標準)。 – Spidey

2

但是,當我輸入像abcd這樣的東西,循環會永遠不會停止提示。

這是因爲如果scanf遇到與轉換說明符不匹配的字符,它會將其保留在輸入流中。基本上,發生了什麼事是scanf從輸入流中讀取字符a,確定它不是%d轉換說明符的有效匹配項,然後將其推回到輸入流中。下一次通過循環它會做同樣的事情。然後再次。然後再次。然後再次。

fflush不是一個好的解決方案,因爲它沒有被定義爲在輸入流上工作。

對於輸入"12ab",scanf將讀取並轉換"12",在輸入流中保留"ab"

最好的解決方案是將所有輸入作爲文本讀取,然後使用strtol(對於整數值)和strtod(對於實際值)將其轉換爲數字類型。例如:

char input[SIZE]; // assume SIZE is big enough for whatever input we get 
int value; 

if (fgets(input, sizeof input, stdin) != NULL) 
{ 
    char *chk; 
    int tmp = (int) strtol(input, &chk, 10); 
    if (isspace(*chk) || *chk == 0) 
    value = tmp; 
    else 
    printf("%s is not a valid integer string\n", input); 
} 

chk指向不是十進制數字輸入流中的第一個字符。如果此字符不是空格或0終止符,則輸入字符串不是有效整數。這將檢測並拒絕輸入,如"12ab"以及"abcd"

scanf是一個很好的解決方案,如果你知道你的輸入總是會正確地形成和行爲良好。如果有機會,您的輸入不是表現良好,請使用fgets並根據需要進行轉換。

0

呼叫scanf("%*[^\n]\n")循環內。這應該足以丟棄與緩存相關的任何內容。

相關問題