虽然在cin输入错误的情况下使用try catch循环失败

时间:2010-02-18 21:09:46

标签: c++ try-catch iostream while-loop

我似乎无法弄清楚为什么在获得非int输入后它会进入循环。我已经尝试了cin.flush(),它似乎不存在,cin.clear(),它看起来应该可以工作,甚至cin.sync()在阅读其他人发布有关它工作后,但没有似乎很有意义。还尝试了cin.bad()。

非常感谢您的帮助

  

请输入第一个数字:f   对不起,我认为这不是一个数字?

     

请输入第一个号码:抱歉,   我认为这不是一个数字?

     

请输入第一个号码:抱歉,   我认为这不是一个数字?

     

请输入第一个号码:抱歉,   我认为这不是一个数字?

     

请输入第一个号码:抱歉,   我不认为这是一个数字?抱歉,   你再也没有尝试过了。按   任何继续的关键。 。

#include <iostream>
using namespace std;

int main(){
    int entry;
    int attempts = 1;
    int result;
    while(attempts <= 5) {
        try {
            cout << "\n\nPlease enter the first number: ";
            cin >> entry;
            if (cin.fail())
                throw "Sorry, I don't think that's a number?";
            if (entry < 0)
                throw "Sorry, no negative numbers. Try something else? ";
            cout << "\nNow the second number: ";
            cin >> entry;
            cin.clear();
            cin.get();
        }
        catch (char* error) {
            cout << error;
            attempts++;
        }
    }
    if (attempts > 5)
        cout << "Sorry, you don\'t get any more tries.\n";
    system("pause");
    return 0;
}

6 个答案:

答案 0 :(得分:9)

如果用户在这种情况下提供无效输入,您应该仔细考虑您想要做什么。通常在这些情况下,最好的解决方案是从输入中读取一行并将其丢弃。

尝试将cin.clear()std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');放入catch子句中。 cin.clear()清除cin中的失败状态,cin.ignore()抛弃在输入缓冲区中等待的其余行。

(是的,您可能应该重新考虑使用例外情况)。

答案 1 :(得分:3)

处理基于行的输入验证的最简单(但通常不是最简单也不是最快)的方法是始终一次读取它。这样,在任何情况下都不会在缓冲区中留下额外的空格(例如换行字符),并且丢弃错误的输入也是非常自动的。

// Infinite loop for retrying until successful
while (true) {
    // Ask the user something
    std::cout << prompt;
    // Read the answer (one full line)
    std::string line;
    if (!std::getline(std::cin, line))
      throw std::runtime_error("End of input while expecting a value");
    // Put the line read into iss for further parsing
    std::istringstream iss(line);
    int val;
    // Read val from iss and verify that reading was successful and
    // that all input was consumed
    if (iss >> val && iss.get() == EOF) return val;
    std::cout << "Invalid input, try again!\n";
}

从中创建一个BASIC样式输入函数很有趣:

template <typename Val> void input(std::string const& prompt, Val& val) {
    // (the above code goes here, slightly adjusted)
}

int main() {
    int w;
    double l;
    input("Enter weight in kg: ", w);
    input("Enter length in m: ", l);
    std::cout << "BMI: " << w / (l * l) << std::endl;
}

那些想要向我投降的迂腐者的笔记:

  • 函数输入应该专门用于std :: string
  • 输入函数抛出的异常应该在main
  • 中捕获

答案 2 :(得分:2)

我的问题是阻止char输入到cin&gt;&gt;编号

此错误导致“无限”循环显示我的提示cout&lt;&lt;提示 无法退出但杀死过程...

以下显示了对我有用的内容!

========================================

double fi_trap_d()    // function to return a valid range double catching errors  
{  
  double fi_game_sec;  
//-------------------------------------------  
   do  
   {  
    fi_game_sec = -1;  
    cout << fi_game_sec_c;  

        //------------------------------  
    cin.ignore();  // (1)
        //------------------------------  

    try  
    {  cin >> fi_game_sec;  cin.clear(); }  // (2)
        catch (...)  //out_of_range)  
      {  
        fi_game_sec = -1;  
        cout << " Dis am an error!\n";  
                     // just loop back as we asked for a number  
      }  
    } while (fi_game_sec < 1);  
//-------------------------------------------  
  return fi_game_sec;  
}  

========================================

尽管尝试了“Dis is a error!”,但从未出现过。

关键是(1)&amp; (2)!

答案 3 :(得分:0)

应该使用例外来处理异常的意外情况。来自用户的不正确输入既不是意外也不是例外 - 它或多或少是常态。就个人而言,我倾向于完全忽略大多数不良输入(当它无法阻止时)。当(并且仅当)他们反复输入不可用的东西时,甚至值得指出它们。因此,我倾向于编写类似的代码:

char ch;
int attempts = 0;

std::cout << "Please enter the first number: ";
do { 
    cin >> ch;
    attempts++;
    if (attempts > 5)
        std::cerr << "The only allowable inputs are '0' through '9'\n";            
} while (cin.good() && !isdigit(ch));
int first_number = ch - '0';

这将输入作为一个字符读取,因此它总是从输入流中删除。然后它尝试验证输入,如果失败,则尝试再次读取。当然,您可能需要/需要更详细一些,例如读取整行,尝试将其转换为数字,如果失败则读取另一行。

答案 4 :(得分:-1)

为什么你这样做有例外?你不会在输入时杀死程序,所以你不应该抛出异常。

只需打印出您的错误消息并尝试再次读入。

答案 5 :(得分:-1)

看起来你会因iostream的原生例外情况而变得更好。启用

cin.exceptions( ios::failbit );

try {
   …
} catch( ios_base::failure & ) {
  cin.clear();
  …
}

永远不要throw一个非std::exception派生的对象,尤其不是像char*这样的原生类型。