[英]Ignoring scanf value in while loop
我正在學習 C 並且在運行此循環時遇到問題。 我寫了一個while
循環來提示用戶輸入 package 及其數量。 我嘗試驗證輸入的數量以檢查是否為 integer(當用戶鍵入一個字符時,它會提示用戶再次鍵入)
對於第一次運行,一切都很好。
但是當循環運行第二次等等時,我嘗試輸入一個字符來表示 package 的數量,不會彈出消息告訴用戶再次輸入。
scanf
的值被忽略, tempQtty
的值等於用戶鍵入的先前數量。
有什么辦法可以解決這個問題,還是有另一種方法來驗證用戶輸入是 integer?
抱歉我的英文不好:")[輸入,預期輸入和實際輸入][1]
while(skip != 'x')
{
printf("\n\n%27sPACKAGE A/B/C/D ( x = skip ) : ", "");
rewind(stdin);
package = getchar();
switch (package)
{
case'x':case'X': skip = tolower(package); break;
case'A':case'a':case'B':case'b': case'C':case'c':case'D':case'd':
printf("%27sQUANTITY%21s: ", "", "");
rewind(stdin);
scanf("%d", &tempQtty); //here's the problem
while (tempQtty < 0)
{
printf("%27s(PLEASE KEY IN A CORRECT VALUE!)\n", "");
printf("%27sQUANTITY%21s: ", "", "");
rewind(stdin);
scanf("%d", &tempQtty);
}
switch (package)
{
case 'A':case 'a': qttyA = tempQtty; totalQttyA += tempQtty; break;
case 'B':case 'b': qttyB = tempQtty; totalQttyB += tempQtty; break;
case 'C':case 'c': qttyC = tempQtty; totalQttyC += tempQtty; break;
case 'D':case 'd': qttyD = tempQtty; totalQttyD += tempQtty; break;
}
break;
default:
printf("%27s(NO SUCH PACKAGE! PLEASE KEY IN AGAIN!)\n", "");
}
}
printf("\nA = %d", qttyA);
printf("\nB = %d", qttyB);
[1]: https://i.stack.imgur.com/hBD82.png
我試着輸入package這個號碼的字符,不會彈出提示讓用戶再次輸入。
scanf
的值被忽略,tempQtty
的值等於用戶鍵入的先前數量。有什么辦法可以解決這個問題,還是有另一種方法來驗證用戶輸入是 integer?
如果您輸入z
,您認為tempQtty
將收到負值的假設是沒有根據的。 事實上,C 標准要求如果轉換失敗, tempQtty
不受影響。 解決這個問題的方法是不要忽略scanf
返回值,它告訴輸入是否有效。
首先,正如我在評論中提到的,這是一個異常復雜的問題,面對它的並不只有你一個人。 不是你的問題,也不是C語言的問題; 這基本上只是scanf
function 本身的問題。
部分答案:
(1) 到處都有類似的東西
scanf("%d", &tempQtty);
while (tempQtty < 0)
...
那是錯誤的。 如果您使用%d
請求 integer 輸入,並且如果用戶鍵入非數字內容,則scanf
不會將tempQtty
填寫為 -1。 它所做的是返回一個值,表示它無法轉換您(程序員)所要求的內容。 所以你想把它改成更像
while (scanf("%d", &tempQtty) != 1)
...
(2) 如果用戶沒有鍵入您請求的 integer,並且如果scanf
返回 0 告訴您,則存在問題:用戶鍵入的非數字輸入可能仍然位於輸入 stream 上。看起來您可能已經意識到這一點,並且您正試圖通過調用rewind(stdin)
來擺脫未讀的輸入。 但那是行不通的; 那不是這樣做的方法。
你想要做的是像這樣寫一個小“幫手”function:
void flush_unread_input()
{
int c;
do {
c = getchar();
} while(c != EOF && c != '\n');
}
然后,只要檢測到錯誤(即scanf
返回 1 以外的值),而不是調用rewind(stdin)
,只需調用flush_unread_input()
。
還有幾點:
flush_unread_input
以及在哪里不調用。 你不能盲目地將它灑在任何地方,因為它基本上讀取並丟棄該行的 rest,但這意味着它也可以讀取並丟棄整行,有時這可能是你真正想要的一行。flush_unread_input
function 的方法。我已經展示了一種應該很容易理解的方法,但是你會經常看到更緊湊的東西,比如while((c = getchar());= EOF && c != '\n');
. (我還沒有測試我在這里展示的版本。)scanf
如果成功則返回 1,如果失敗則返回 0,但它比這更復雜。 scanf
實際上返回成功轉換和存儲的項目數,如果您的格式說明符中包含多個%
符號,則該數可能大於 1。關於這個話題還有很多話要說,但今天早上我沒有時間寫更長的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.