2013-05-29 141 views
4

在C++中,爲了處理錯誤的輸入(例如當程序要求輸入一個整數但你輸入一個字符),它應該能夠做些事情,然後循環重複輸入。卡在無限循環中

我的循環迭代無限,當你輸入需要一個整數,當一個字符,反之亦然:

#include<iostream> 

int main() 
{ 
    while (cout << "Enter a number" && !(cin >> num)) 
    { 
     cin.sync(); 
     cin.clear(); 
     cout << "Invalid input; please re-enter.\n"; 
    } 
} 

我應該怎麼做,使程序的新的輸入再次提示?

+3

你真的不應該寫這樣的代碼,很難理解發生了什麼,錯誤在哪裏。 – Djon

+1

提示:http://en.cppreference.com/w/cpp/io/basic_istream/ignore – aschepler

+0

@Djon我覺得代碼很清楚,錯誤很容易被發現。究竟是什麼困擾你呢? – jrok

回答

5

如果cin >> num失敗,則需要從流中刪除無效輸入。我建議使用ignore而不是sync來完成此操作。原因是sync不是保證刪除的所有的剩餘輸入標準庫的實現。

#include <iostream> 
#include <limits> 

int main() 
{ 
    int num; 
    while (cout << "Enter a number" && !(cin >> num)) 
    { 
     cin.clear(); // clear the error 

     // Remove input up to a new line 
     cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); 
     cout << "Invalid input; please re-enter.\n"; 
    } 
} 

以上的例子使用std::numeric_limits<std::streamsize>::max()用於檢索字符的輸入緩衝器可容納的最大數量。這允許ignore()刪除儘可能多的字符到新行。這是慣用的C++,並且優於使用magic numbers,這很可能只是隱藏了你當前擁有的問題。

這很好,但不處理輸入包含數字後面多餘字符的情況。爲了處理這些情況,需要對循環進行一些修改以處理額外的驗證。一種選擇是從cin中讀取整行,將其放入std::stringstream中,從中讀取數字,然後執行其他驗證。有一種可能需要考慮的特殊情況 - 只有數字後面的字符是空格的行。幸運的是,標準庫提供了流修改器std::skipws,可以輕鬆處理這種情況。下面的例子說明如何做到這一點沒有太大的避免費勁

#include <iostream> 
#include <sstream> 

int main() 
{ 
    int num; 

    for(;;) 
    { 
     std::cout << "Enter a number: " << std::flush; 

     std::string line; 
     std::getline(std::cin, line); // Read a line from console 
     std::stringstream text(line); // store in a string stream 

     char ch = 0; 
     if(!(text >> num).fail() && (text >> std::skipws >> ch).fail()) 
     { 
      break; 
     } 

     std::cout << "Invalid input; please re-enter.\n"; 
    } 

    return 0; 
} 

表達(text >> std::skipws >> ch).fail()將跳過數之後出現,然後試圖讀取一個字符的所有空格。如果沒有字符可用,則讀取將失敗,指示用戶僅輸入了一個數字,而沒有其他字符。如果我們試圖用cin這樣做,即使輸入有效,它也會等待用戶輸入更多文本。

+0

它不起作用,如果我給'233dsjfeu4'作爲輸入,因爲它讀取爲233,然後給出錯誤,但'342365465235436436'或'ddsfdfdggv' –

+0

@AmolakChandel正常工作我已更新我的答案,包括確認只輸入一個數字。除空格之外的任何尾隨字符都表示失敗。 –

2

使用cin.ignore()代替cin.sync(),看看爲什麼from this answer

while (cout << "Enter a number" && !(cin >> num)) { 
    cin.clear();   // clear error 
    cin.ignore(100, '\n'); // ignore characters until next '\n' (or at most 100 chars) 
    cout << "Invalid input; please re-enter.\n"; 
} 

More on cin.ignore

請注意,您可以延長忽略的字符數的範圍內,達到了最大

cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); 
+1

爲什麼這個神奇的數字? – jrok

+0

@jrok我不喜歡默認(1,EOF)。例如,給一個初學者一個具體的例子(100)比'std :: numeric_limits :: max()'更明確。事實上,我應該添加一個鏈接到文檔(完成)。 –

+1

如果用戶輸入超過100個字符會發生什麼情況? –

-1

您可以將輸入讀取爲字符串,將其轉換爲整數並驗證它。

#include <iostream> 
#include <string> 
using namespace std; 
int main() 
{ 
    int number = 0; 
    string input; 
    do { 
     cout << "Enter a number: "; 
     cin >> input; 
     number = atoi(input.c_str()); // atoi returns 0 on error.. 
     if (number != 0 || input.compare("0") == 0) // but maybe the user really entered "0". 
      break; 
     cout << endl; 
     cout << "Invalid input; please re-enter.\n"; 
    } while (1); 
    cout << "You entered " << number << endl; 
    return 0; 
} 

示例程序執行:

% ./foo 
Enter a number: abc 

Invalid input; please re-enter. 
Enter a number: 2 
You entered 2 
% ./foo 
Enter a number: 0 
You entered 0 

..雖然這可能不是最完美的解決方案。