Catch ios :: failure保持循环

时间:2013-08-02 23:06:37

标签: c++

以下代码应检查每个输入一次,并在输入不是数字时显示“非数字”。

int input;
while (1 == 1){
    cout << "Enter a number: ";
    try{
        cin.exceptions(istream::failbit);
        cin >> input;
    }catch(ios::failure){
        cout << "Not a number\n";
        input = 0;
    }
}

问题是当调用catch时(当它不是数字时)它会无休止地显示“无效数字”,就好像while()循环执行了几次但没有要求任何新的投入。

3 个答案:

答案 0 :(得分:3)

while(true)while(1) [或for(;;)]是制作“永久循环”的惯用方法。

您需要“清理”cin流中不可接受的输入。 典型的方法是调用cin.ignore(1000, '\n');,它会忽略所有输入,直到下一个换行符[最多1000个字符 - 你可以选择一个更大的数字,但通常1000就足以“到达换行符”。

您几乎肯定也(感谢Potatoswatter)需要在输入上调用cin.clear();,以删除failed状态,以便下一个输入成功。 [而且cin.ignore()是进一步的输入,所以它需要在此之前 - 只是为了清楚]。

答案 1 :(得分:1)

虽然您无法将流中的字符提取到int,但这些字符仍保留在流中,以便您可以尝试将其作为其他内容提取。

要完全跳过它们,请在std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');区块内运行catch

然后,无论用户输入 next ,都将是流中的第一件事。也许这将是一个数字,所以你下一次尝试提取成int成功。

答案 2 :(得分:0)

好的,是的。你的try-catch语句在循环中。所以你尝试了一些东西,它失败并抛出一个异常,然后你捕获异常,你永远不会退出或从循环返回,所以你再次做同样的事情。

但由于您的输入未在第一次处理(抛出异常而非),因此不会在第二次,第三次或任何时间处理。

要前进,通过忽略输入直到下一个空格来处理异常:

int input;
while (1 == 1){
    cout << "Enter a number: ";
    try{
        cin.exceptions(istream::failbit);
        cin >> input;
    }catch(ios::failure){
        cout << "Not a number\n";
        input = 0;
        //the line below ignores all characters in cin until the space (' ')
        //(up to 256 characters are ignored, make this number as large as necessary
        cin.ignore(256, ' ');  
    }
}

顺便说一句,作为一般规则:异常应该是真正例外的事情,特别是因为处理异常有开销。关于whether invalid user input is exceptional存在争议。

作为替代方案,您可以制作更紧凑,同样正确的循环,而不会出现以下情况:

int input;
while (true){  //outer while loop that repeats forever. Same as "while(1 == 1)"
    cout << "Enter a number: ";
    //The following loop just keeps repeating until a valid value is entered.
    //The condition (cin >> input) is false if e.g. the value is a character,
    //or it is too long to fit inside an int.
    while(!(cin >> input)) { 
      cout << "Not a number" << endl;
      input = 0;
    }
}