2010-01-09 91 views
3

當運行下面的代碼並輸入一個數字時,它工作正常。 但輸入字母時,程序進入無限循環,顯示「輸入數字(0退出):cin失敗。」C++ cin.fail()問題

我的意圖是處理cin失敗案件並再次提示用戶。

int number; 
do{ 
    cout << "Enter a number (0 to exit): "; 
    cin >> number; 
    if(cin.fail()){ 
     cout << "cin failed." << endl; 
     cin.clear(); 
    }else{ 
     cout << "cin succeeded, " << number << " entered." << endl; 
    } 
}while(number != 0); 

回答

5

您需要從清除線CIN,使用cin.ignore,除了清除流狀態(這是什麼cin.clear一樣)。

我有several utility functions,使這個容易(你會感興趣clearline特別,它清除了流狀態和當前行)和what you want幾乎一個確切的例子。

您的代碼,或多或少的,用我的clearline

#include "clinput.hpp" // move my file to a location it can be used from 

int main() { 
    using namespace std; 
    while (true) { 
    cout << "Enter a number (0 to exit): "; 
    int number; 
    if (cin >> number) { 
     cout << "Read " << number << '\n'; 
     if (number == 0) { 
     break; 
     } 
    } 
    else { 
     if (cin.eof()) { // tested only *after* failed state 
     cerr << "Input failed due to EOF, exiting.\n"; 
     return 1; 
     } 
     cerr << "Input failed, try again.\n"; 
     clearline(cin); // "cin >> clearline" is identical 
    } 
    } 
    return 0; 
} 

目前仍然是一個潛在的問題在這裏(定格在我clinput_loop.cppblankline),與在緩衝區將離開輸入擰緊後面的IO(參見示例會話中的「42 abc」)。提取上述代碼放到一個獨立的和自足的功能留給作爲練習讀者,但這裏有一個骨架:

template<class Type, class Ch, class ChTr> 
Type read(std::basic_istream<Ch,ChTr>& stream, Ch const* prompt) { 
    Type value; 
    // *try input here* 
    if (could_not_get_input or more_of_line_left) { 
    throw std::runtime_error("..."); 
    } 
    return value; 
} 
template<class Type, class Ch, class ChTr> 
void read_into(
    Type& value, 
    std::basic_istream<Ch,ChTr>& stream, 
    Ch const* prompt 
) { 
    value = read<Type>(stream, prompt); 
} 

使用例:

int n; 
try { 
    read_into(n, std::cin, "Enter a number: "); 
} 
catch (std::runtime_error& e) { 
    //... 
    raise; 
} 
cout << "Read " << n << '\n'; 

clearline功能提取爲後代,萬一上面的鏈接斷裂(並稍作改變,使自成體系):

#include <istream> 
#include <limits> 

template<class C, class T> 
std::basic_istream<C,T>& clearline(std::basic_istream<C,T>& s) { 
    s.clear(); 
    s.ignore(std::numeric_limits<std::streamsize>::max(), s.widen('\n')) 
    return s; 
} 

模板的東西是有點混亂,如果你不使用它,但它並不難:

  • 的std :: istream的std::basic_istream<char, std::char_traits<char> >
  • 性病的一個typedef :: wistream是的std::basic_istream<wchar_t, std::char_traits<wchar_t> >
  • 一個typedef擴大允許'\n'成爲L'\n'適當
  • 該代碼同時適用於的常見焦炭wchar_t的箱子,也
  • 它寫入到被稱爲clearline(stream)stream >> clearlinebasic_istream的任何兼容的實例,比較其它操縱像的std :: ENDL的std :: WS,或的std :: boolalpha
+0

謝謝!這解決了它。還有一點是我必須同時使用cin.clear()和cin.ignore()。 – 2010-01-09 07:45:04

+0

是的,如果你看看我的clearline函數(在clinput.hpp中,並按照代碼路徑),它會調用clear和ignore。 – 2010-01-09 07:45:46

+0

+1由於明顯的原因 – 2010-01-09 08:02:39

1

這可能是你究竟想要做的事:

#include <iostream> 
using namespace std; 

int main() 
{ 
    int i; 
    do { 
    if (cin.fail()) 
    { 
     cin.ignore(255); 
     cin.clear(); 
    }   
    cout << "Please enter an integer value: "; 
    cin >> i; 
    } while (cin.fail()); 
    cout << "The value you entered is " << i; 
    return 0; 
} 
+1

這將始終導致無限循環,因爲一旦進入失敗狀態,您既不修改流狀態,也不修改流緩衝區。 – 2010-01-09 07:48:18

+0

「總是結果..」如果第一次輸入錯誤的輸入,也就是說。 – 2010-01-09 07:56:04

+0

嘿,好像每天都在學習新的東西......現在它是正確的? (沒有編譯器在手測試...) – 2010-01-09 08:01:55

0

這是cin.fail() 的簡單的例子,直到提供了一種有效的整數值將處理輸入

#include <iostream> 
using namespace std; 

int main() 
{ 
int j; 
int i; 

i = 0; 
while (1) { 
    i++; 
    cin >> j; 
    if (cin.fail()) return 0; 
    cout << "Integer " << i << ": " << j << endl; 
} 
} 

輸入:

42 51 85 85你好

輸出:

整數1:42

整數2:51

整數3:85

+0

請編輯[編輯]解釋你的代碼在做什麼。 – 2015-10-07 16:23:49