以下代码应检查每个输入一次,并在输入不是数字时显示“非数字”。
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()循环执行了几次但没有要求任何新的投入。
答案 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)
但由于您的输入未在第一次处理(抛出异常而非),因此不会在第二次,第三次或任何时间处理。
要前进,通过忽略输入直到下一个空格来处理异常:
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;
}
}