2012-01-25 39 views
1

以下是簡單菜單的代碼。如果用戶輸入無效選項(4或'o'),應重新打印菜單,顯示錯誤消息。該代碼在用戶輸入數字時起作用,但當用戶向選項中輸入字母或字符串時,該代碼失敗(循環無限期)。我的猜測是在產生奇怪行爲的循環情況下內存被覆蓋。有人可以幫我解決它嗎? 謝謝菜單循環中scanf的奇怪行爲

int inmenu = 1; 
while (inmenu){ 
    //Menu 
    printf("User: %s %s\n", user.firstname, user.lastname); 
    printf("0) Exit\n1) List Friends\n2) Add Friend\n3) Delete Friend\nWhat would you like to do? "); 
    int option; 
    scanf("%i", &option); 
    if(option == 0) 
     inmenu = 0; 
    else if (option == 1) 
     defaultPrint(friends, numfriends, NULL); 
    else if (option == 2){ 
     //addfriend 
     char *name = (char *) malloc(sizeof(char) * 256); 
     int birthdate; 
     printf("Enter first name: "); 
     scanf("%s", name); 
     printf("Enter last name: "); 
     scanf("%s", name); 
     printf("Enter birthdate: "); 
     scanf("%i", &birthdate); 

    } 
    else if (option == 3){ 
     //deletefriend 
     defaultPrint(friends, numfriends, NULL); 
     int n; 
     printf("What friend would you like to delete? "); 
     scanf("%i", &n); 
    } 
    else 
     printf("ERROR: Invalid option %i\n", option); 
} 

測試輸入:

0) Exit 
1) List Friends 
2) Add Friend 
3) Delete Friend 
What would you like to do? 4 
ERROR: Invalid option 4 
0) Exit 
1) List Friends 
2) Add Friend 
3) Delete Friend 
What would you like to do? 

(正確的行爲)

0) Exit 
1) List Friends 
2) Add Friend 
3) Delete Friend 
What would you like to do? o 
What would you like to do? ERROR: Invalid option 4 
0) Exit 
1) List Friends 
2) Add Friend 
3) Delete Friend 
... 

(不正確的行爲保持打印在一個無限循環相同的最後5行)

+0

檢查此問題。 http://stackoverflow.com/questions/1716013/why-is-scanf-causing-infinite-loop-in-this-code –

+0

你可能想看看答案並接受答案。像我一樣,例如。 – tekknolagi

回答

1

問題的原因在於scanf()不符合請求的格式時不會消耗輸入流。

這意味着,當你撥打:

scanf("%i", &option); 

如果用戶輸入以外的東西多了一些(像"o")則該用戶輸入保持輸入流中 - 所以,當你周圍循環,再次呼叫scanf()"o"仍然存在,但仍不符合請求的格式。

這就是爲什麼scanf()不是特別適合用戶輸入 - 它是爲消費格式良好的數據文件而設計的。相反,由於您有面向行的用戶界面,因此您應該從fgets()開始閱讀用戶的整行內容,然後嘗試使用sscanf()對其進行解析。如果分析不正確,則可以報告錯誤,然後從用戶那裏讀取新行。

+0

謝謝你的解決方案解決了我的問題! – pretobomba

+0

@pretobomba提供更持久的解決方案(如果您想添加更多選項等),請查看我的答案。另外,如果它解決了您的問題,您可能想要接受他的答案。 – tekknolagi

2

爲什麼使用scanf?如何使用getchar,檢查範圍,看看它是否0 - 4,如果沒有,則顯示錯誤消息。

1

當你輸入一個數字並按下回車鍵時,scanf會讀取該數字,但會將新行保留在緩衝區中,循環循環時,scanf將從緩衝區讀取換行符,查看它與格式不匹配,把它留在那裏。這將永遠重複。

速戰速決可能是新行添加到格式:

scanf("%i\n", &number); 

但如果用戶沒有輸入正是你所期望的數據,這將失敗,換行符是不是唯一的東西會導致行爲,任何與格式不匹配的東西都會留在緩衝區中。

+1

帶'%i'格式的'scanf()'將跳過包括換行符在內的空白字符,直到找到一個數字(或絕對不是數字的東西)。換行符不是問題。 – caf