2013-06-02 160 views
3

在第5行中,我讀取整數並且isint在讀取整數時獲取1,如果不是整數則爲0。如果isint是0我有一個循環要求用戶給一個整數,我讀直到用戶給出一個整數。我嘗試給出一個字符而不是一個整數的代碼,但我有一個無限循環。該程序只是不等待給一個新的輸入。我的代碼有什麼問題?爲什麼scanf在無效輸入中陷入無限循環?

#include <stdio.h> 

int main(void) { 

    int arg1; 
    //int arg2; 
    int attacknum = 1; 
    int isint = 1; 

    //printf("Insert argument attacks and press 0 when you have done this.\n"); 
    printf("Attack %d\n", attacknum); 
    attacknum++; 
    printf("Give attacking argument:"); 
    isint = scanf("%d", &arg1); //line 5 

    while(isint == 0){ 
    printf("You did not enter a number. Please enter an argument's number\n"); 
    isint = scanf("%d", &arg1); 
    printf("is int is %d\n", isint); 
    } 
    return 0; 
} 
+0

printf(「is int is%d \ n」,isint)的輸出是什麼? – Xonar

+0

請提供您場景的控制檯輸出。 – zsawyer

回答

10

正如其他人所說,如果scanf無法解析輸入,它會使其未被掃描。

一般來說scanf是交互式輸入的一個糟糕的選擇,因爲這種行爲,並且因爲它與用戶遇到的一次一行的界面不匹配。

您最好使用fgets將一行讀入緩衝區。然後使用sscanf解析該行。如果你不喜歡這個輸入,那就把整條線扔掉,再讀一遍。

事情是這樣的:

#include <stdio.h> 

int main(void) 
{ 
    char line[256]; 

    int arg1; 
    int isint; 

    while (1) { 
    printf("Give attacking argument:"); 
    fgets(line, sizeof line, stdin); 
    isint = sscanf(line, "%d",&arg1); 
    if (isint) break; 

    printf("You did not enter a number.Please enter an argument's number\n"); 
    } 

    printf("Thanks for entering %d\n", arg1); 

    return 0; 
} 

(對於生產代碼,你要處理大排長龍,檢查返回代碼,還要檢查該號碼後尾隨垃圾等)

其實,一個更好的方法是不使用scanf如果你只是想讀一個整數,而是使用strtol。這給你一個方便的指針,指向數字後面的字符,並且你可以檢查它是否是空格或nul。

+1

這仍然會接受像'123ab'這樣的輸入作爲'123'。使用for循環在行內搜索無效字符是個不錯的主意,請參閱相同的問題:http://stackoverflow.com/questions/20829672/why-this-example-is-stuck-in-an-infinite- loop-in-c – ilgaar

+0

檢測是否存在尾隨垃圾是一個好主意。如同在這個問題中那樣,通過手動掃描字符串來做到這一點是一種非常漫長而不雅的方式。最好只使用['strtol'](http://man7.org/linux/man-pages/man3/strtol.3.html),它給你一個指向下列字符的指針。 – poolie

4

scanf面臨着一個非數字字符也不會消耗任何輸入和返回零個整數宣讀。非數字將保留在下一個呼叫scanf的輸入中,其行爲與第一次呼叫相同,等等。

回答下面的問題。您可以使用fgetc解析至少一個字符,但這會爲每個已輸入字符提供錯誤消息。通常我認爲你想跳過直到換行。爲此,您可以使用poolie建議的fgets。或者您可以在scanf之後添加以下內容。

int ch; 
if (isint == 0) 
while ((ch = fgetc(stdin)) != EOF && ch != '\n') 
{ 
    /* Skip characters */ 
} 

P.S:在你的情況下,它可能是更好的把它只是在循環中的第一printf之前。

+0

你有什麼建議來解決這個問題?我如何消費非數字? – Dchris

+0

@Dchris我加了一些建議。 –

+1

@Dchris你做了哪些研究?你是否認真對待這個問題?你爲什麼不看書? – Sebivor