上一篇主題 :: 下一篇主題 |
發表人 |
內容 |
yag Site Admin
註冊時間: 2007-05-02 文章: 689
2704.11 果凍幣
|
發表於: 2007-6-3, PM 4:37 星期日 文章主題: [C++疑難雜症]cin無限迴圈錯誤 |
|
|
詳細症狀請看[7]if、goto、隨機亂數、邏輯和關係運算子、算術運算子
大致就是將非數字字元用cin讀入某數字型態變數時,cin會發生錯誤,若這錯誤是發生於迴圈中,那麼就可能造成無限迴圈。
我在網路上找到一篇相關解說及處理方式的文章,不過是英文的,有興趣的可以看看看:
http://cs.nmhu.edu/personal/curtis/cs1htmlfiles/cs1ch11sec2.htm
這個網頁中比較後半段「E. Handling Invalid Input」的段落就是在說這種形態的錯誤及解決辦法。
會產生這種錯誤,是因為cin在遇到把非數字字元丟給數字型態變數時,會將狀態設成fail,然後鎖死輸入的機制,使得輸入這行直接跳過不處理,如果這個輸入又是迴圈的結束條件,那麼自然就會產生無限迴圈,而那個變數的值就會保持在最後一個正常值的狀況下。
解決的方法很簡單,只要在迴圈中加入下面的程式碼即可: 代碼: | if( cin.fail() )
{
cin.clear();
char ch1;
cin >> ch1;
cout << "錯誤型態的輸入!" << endl;
} | 這段程式碼的意思就是,當cin發生錯誤時,將錯誤狀態清除,宣告一個字元型態變數,將出錯的那個字元讀出來(此字元沒有用處,只是為了清空cin的串流,還是得讀出來),然後輸出錯誤訊息。
如此一來,就可以解決掉無限迴圈的問題,下次再到cin的位置時,就會要求再度輸入訊息,而不會直接略過。
話說為何在[7]if、goto、隨機亂數、邏輯和關係運算子、算術運算子的範例中輸入浮點數就會造成無限迴圈,那是因為當cin後面是整數變數時,它只會將浮點數小數點前面的數字丟給整數變數,後面的,就會在下一次的cin時才丟出來。
也因此,假設我輸入2.2,那麼我就會是先出石頭,如果電腦出剪刀或布,那麼接下來的這個「.」剛好丟給yesno當成願意繼續,之後第二局又是出石頭,然後直接到達詢問是否繼續的地方,因為畫面太快,我之前試的時候還以為看起來滿正常的,後來才發現,上面輸贏記錄的地方已經更新過了,代表這是第二局了。
如果第一局就平手,那麼這個「.」就會直接丟給第二次的choice,直接就進入了無限迴圈。大致就是這樣,有興趣的可以多試試,可以對程式流程有多一點體認。
以下附上更新後的猜拳遊戲程式碼: 代碼: | #include <iostream>
#include <time.h>
using namespace std;
int main()
{
char yesno;
short choise = 0, computer = 0;
int win = 0, lose = 0, deuce = 0;
cout << "這是猜拳遊戲,請從剪刀、石頭、布中選擇其一," << endl
<< "規則是剪刀贏布,布贏石頭,石頭贏剪刀。" << endl;
system( "pause" );
system( "cls" );
srand( (unsigned)time( NULL ) );
Choose:
cout << "勝場:" << win << " 敗場:" << lose << " 平手:" << deuce << endl;
cout << "請輸入1~3:(1.剪刀 2.石頭 3.布)" << endl;
cin >> choise;
if( cin.fail() ) // 只有多加了從這裡開始
{
cin.clear();
char ch1;
cin >> ch1;
cout << "錯誤的輸入格式!" << endl;
goto Choose;
} // 到這裡結束的程式碼,其他地方都沒有異動
if( choise < 1 || choise > 3 )
goto Choose;
computer = rand() % 3 + 1;
if( choise == computer )
{
cout << "平手!" << endl;
deuce++;
goto Choose;
}
else if( (choise == 1 && computer == 3) || (choise == 2 && computer == 1) || (choise == 3 && computer == 2) )
{
cout << "你贏了!" << endl;
win++;
}
else
{
cout << "你輸了!" << endl;
lose++;
}
cout << "要繼續嗎?( y/n )" << endl;
cin >> yesno;
if( yesno != 'n' && yesno != 'N' )
{
system( "cls" );
goto Choose;
}
return 0;
} |
PS.感謝kage01的細心測試程式,找出此bug。 |
|
回頂端 |
|
|
chongren 偶而上來逛逛的過客
註冊時間: 2009-07-27 文章: 14 來自: 台北 152.02 果凍幣
|
發表於: 2009-9-16, AM 11:29 星期三 文章主題: |
|
|
請問一下程式中的cls是什麼意思啊?! _________________ 爬文?
爬文這種舉動不適合我這種腦殘 |
|
回頂端 |
|
|
yag Site Admin
註冊時間: 2007-05-02 文章: 689
2704.11 果凍幣
|
|
回頂端 |
|
|
|