2013-04-05 59 views
1

我發現這個代碼片段在一本書:利空數據,再試一次

int ival; 
// read cin and test only for EOF; loop is executed even if there are other IO failures 
while (cin >> ival, !cin.eof()) { 
    if (cin.bad())   // input stream is corrupted; bail out 
     throw runtime_error("IO stream corrupted"); 
    if (cin.fail()) {      // bad input 
     cerr<< "bad data, try again";  // warn the user 
     cin.clear(istream::failbit);   // reset the stream 
     istream::iostate cin_state = cin.rdstate(); 
     continue;       // get next input 
    } 
    // ok to process ival 
} 

如果我在命令窗口中單擊「F」,然後無數的「壞數據,再試一次」,並cin_state爲0x02,這等於壞道。 Failbit尚未清楚,爲什麼?

+0

可能的重複[爲什麼下面的c + +代碼保持輸出「壞數據,再試一次」?](http://stackoverflow.com/questions/4297469/why-the-following-c-code-keeps-output- bad-data-try-again) – jerry 2015-02-16 12:46:29

回答

6

問題是f從不會從輸入流中刪除,所以cin >> ival一直試圖一遍又一遍地讀取它。

您需要跳過它。例如,請參閱How does istream::ignore() work?

+0

我得到了你的答案,但是當我用'cin.ignore(1000,'\ n');',問題再次出現。當我使用'cin.clear();'而不是'cin.clear(istream :: failbit);',「壞數據,再試一次」只出現一次。我認爲'cin.clear();'清除失敗狀態,但'cin.clear(istream :: failbit);'沒有,我無法解釋爲什麼。 – Robert 2013-04-05 15:35:26

+0

@Robert'cin.clear()'是正確的,請參閱我的回答以獲得解釋。 – jerry 2013-04-23 21:00:41

1

雖然NPE關於不從流中刪除違規數據的觀點是正確的,但它不是唯一的(或最令人震驚的)問題。

由於默認參數,您應該使用cin.clear(),與cin.clear(ios_base::goodbit)相同。正如你在你的評論中推測的那樣,cin.clear(istream::failbit)不會將cin重置爲良好狀態。實際上,它將流設置爲失敗狀態。這似乎違反直覺,但clear將流的狀態設置爲(或「清除它」)傳遞的參數。關於它的運作還有一些其他細節,但它們與這個討論沒有密切關係。

確保您在ignore之前致電clear,否則後者將不起作用。最後,爲防止任意長的無效條目,請將std::numeric_limits<int>::max()作爲第一個參數傳遞給ignore

修改後的代碼片段應該是:

int ival; 
// read cin and test only for EOF; loop is executed even if there are other IO failures 
while (cin >> ival, !cin.eof()) { 
    if (cin.bad())   // input stream is corrupted; bail out 
     throw runtime_error("IO stream corrupted"); 
    if (cin.fail()) {      // bad input 
     cerr<< "bad data, try again";  // warn the user 
     cin.clear();   // or cin.clear(istream::goodbit); 
     istream::iostate cin_state = cin.rdstate(); 
     cin.ignore(std::numeric_limits<int>::max(), '\n'); 
     continue;       // get next input 
    } 
    // ok to process ival 
} 

至於爲什麼你看到這個C++入門,我不能說。我沒有看過這本書,但我知道這是相當好的想法。我建議檢查你的版本有多舊,並尋找勘誤表。