循环直到整数输入在所需范围内无法处理非数字字符输入
我对应该非常简单的代码有疑问.我想接收一个 1 到 3 之间的整数并进行错误检查.它可以很好地检查过大或过小的数字,但是当输入字母/数字组合时,它会陷入无限循环.建议?
I'm having a problem with what should be incredibly simple code. I want to take in an integer between 1 and 3 with error checking. It works fine for checking for numbers that are too large or too small, but when a alpha/number combination is entered, it gets stuck in an infinite loop. Suggestions?
#include <iostream>
using namespace std;
int main(int argc, char *argv[]){
int input;
cout << "
Please enter a number from 1 to 3:" << endl;
cout << "-> ";
cin >> input;
while(input< 1 || input> 3){
cout << "
---------------------------------------" << endl;
cout << "
[!] The number you entered was invalid." << endl;
cout << "
Please re-enter a number from 1 to 3" << endl;
cout << "-> ";
cin >> input;
}
cout << "You chose " << input << endl;
}
推荐答案
问题在于:
cin >> input;
当您尝试读取非数值时会导致设置坏位.在此之后,任何使用 operator>>
的尝试都会被默默忽略.
Will cause the bad bit to be set when you try and read a non numeric value. After that happens any attempt to use the operator>>
is silently ignored.
因此,纠正此问题的方法是测试流是否处于良好状态,如果不是,则重置状态标志并再次尝试读取.但请注意,错误的输入(导致问题的原因)仍在输入中,因此您需要确保将其丢弃.
So the way to correct for this is to test if the stream is in a good state and if not then reset the state flags and try and read again. But note that the bad input (that caused the problem) is still on the input so you need to make sure you throw it away as well.
if (cin >> input)
{
// It worked (input is now in a good state)
}
else
{
// input is in a bad state.
// So first clear the state.
cin.clear();
// Now you must get rid of the bad input.
// Personally I would just ignore the rest of the line
cin.ignore(std::numeric_limits<std::streamsize>::max(), '
');
// now that you have reset the stream you can go back and try and read again.
}
为了防止它卡住(这是由设置的坏位引起的)读入一个字符串然后使用字符串流来解析用户输入.我也更喜欢这种方法(用于用户交互输入),因为它可以更轻松地组合不同的阅读风格(即组合 operator>>
和 std::getline()
因为您可以在字符串流上使用这些).
To prevent it getting stuck (which is caused by the bad bit being set) read into a string then use a string stream to parse user input. I also prefer this method (for user interactive input) as it allows for easier combination of different styles of reading (ie combining operator>>
and std::getline()
as you can use these on the stringstream).
#include <iostream>
#include <sstream>
#include <string>
// using namespace std;
// Try to stop using this.
// For anything other than a toy program it becomes a problem.
int main(int argc, char *argv[])
{
int input;
std::string line;
while(std::getline(std::cin, line)) // read a line at a time for parsing.
{
std::stringstream linestream(line);
if (!(linestream >> input))
{
// input was not a number
// Error message and try again
continue;
}
if ((input < 1) || (input > 3))
{
// Error out of range
// Message and try again
continue;
}
char errorTest;
if (linestream >> errorTest)
{
// There was extra stuff on the same line.
// ie sobody typed 2x<enter>
// Error Message;
continue;
}
// it worked perfectly.
// The value is now in input.
// So break out of the loop.
break;
}
}
相关文章