2012-09-16 22 views
1

我一直在解決這個問題。問題的要求非常簡單。我想要做的只是檢查用戶輸入並允許用戶只輸入小寫字母。另一個約束是我只想使用scanf()來完成它。我知道我可以使用gets()和其他輸入函數,但仍然爲了更好地理解它,我想使用scanf()來做到這一點。在C中使用scanf進行模式匹配

我曾嘗試在GCC如下:

char str[100000]; 
return_value=scanf("%99999[a-z]",str); 
if(return_value==0 || return_value==EOF) 
{ 
    printf("illegal input"); 
} 
else 
    printf("input accepted"); 

下面的作品完全符合市場預期。所以如果用戶試圖用大寫字母輸入任何字符串,代碼只會輸出:「非法輸入」。

當我嘗試將上述代碼放在有限的while循環中時,問題就出現了。例如:

int counter=0; 
char str[100000]; 
scanf("%2d",&counter); 
while(counter>0) 
{ 
    fflush(stdin); 
    return_value=scanf("%99999[a-z]",str); //note 
    if(return_value==0 || return_value==EOF) 
    { 
    printf("illegal input"); 
    } 
    else 
    printf("input accepted"); 
    counter--; 
}//end of while 

在一旦用戶輸入變量「計數」的值,並按下回車鍵的上述情況下,控制馬上進入並輸出「非法輸入」,甚至不需要等待用戶輸入一個字符串。雖然用戶被允許進入

return_value=scanf("%99999c[a-z]",str); //note 

在兩種情況下:

要糾正這個錯誤我試圖把下面的地方行標爲注:

return_value=scanf("%99999s[a-z]",str); //note 

,甚至這在輸入'counter'變量的值之後的輸入字符串,用戶輸入消毒沒有完成,即,即使用戶輸入一個由大寫字符組成的字符串,輸出不是「非法輸入」(應該是這樣),而是「輸入接受」。

現在有人可以向我解釋這一點。我在哪裏錯了,或者我只是忽略了一些東西,做了一些愚蠢的錯誤?

回答

1

您試圖一次又一次地讀取錯誤的輸入。如果你想跳過,例如,一個字符,你必須做的,如果用戶輸入錯誤的輸入,scanf("%.*s") - >這將跳過所有內容,直到下一個\ n。

說明:如果scanf()失敗,它什麼都不讀 - 所以,當它試圖再次讀取時,它將從它以前失敗的同一個地方開始。

+0

我認爲這是正確的,但它不是很清楚。這意味着stdin *上的輸入不會消失*。所以壞字符保持不變,並在循環的下一次循環中由scanf()讀取。 – 2012-09-16 11:43:07

+0

但我確實在while循環開始時使用了fflush(stdin)。它會不會照顧清理? – qre0ct

+0

@Yossarian ... uuh ...老兄m對不起,但我真的不明白你的意思....請你詳細說明 – qre0ct

2

fflush()是一個不適當的方法來清除stdin。相反,使用scanf讀,直到EOF或只是

while((c = getchar()) != '\n' && c != EOF) { /* Discard */ } 

另外,我建議範圍界定單個語句,如其他。

+0

好吧..我部分同意......但是如果oyu能夠給出一些關於fflush被認爲不合適的解釋,我們會很高興。其次,我知道你提到的這種技術,但我仍然喜歡使用scanf並執行所需的操作。任何建議,將不勝感激。 – qre0ct

+0

@geek_ji因爲您不允許在輸入流上使用fflush。結果是未定義的行爲。 –

+0

fflush(stdin)未被ANSI C定義。這意味着使用它是不好的做法,目前還不清楚,它很有可能不工作。我相信這適用於任何輸入流或「讀取」。 getchar基本上是scanf(「%c」,&c)。 – BSull