C++中while循环的意外行为
做了这样的事情:C++中while循环的意外行为,c++,arrays,loops,while-loop,C++,Arrays,Loops,While Loop,做了这样的事情: int main() { while (true) { std::cout << "Enter a number between one and nine. \n"; int oneandnine; std::cin >> oneandnine; if (std::cin.fail()) { std::cin.clear();
int main()
{
while (true)
{
std::cout << "Enter a number between one and nine. \n";
int oneandnine;
std::cin >> oneandnine;
if (std::cin.fail())
{
std::cin.clear();
std::cin.ignore(100, '\n');
std::cout << "INVALID UNPUT!\n";
}else if (oneandnine <= 9 && oneandnine >= 1)
{
break;
}else
{
std::cout << "INVALID UNPUT!\n";
}
}
return 0;
}
INVALID UNPUT!
Enter a number between one and nine.
INVALID UNPUT!
Enter a number between one and nine.
为什么它会像这样循环两次?是因为当456被丢弃而其余的aihdb没有被丢弃时,导致它再次循环并跳过cin输入?std::istream的运算符>>没有读取整行内容。它一直读取,直到找到无效字符或空白,如果在无效字符之前找到了有效字符,则读取操作将成功,并且无效字符将保留在流中
在您的示例中,第一次迭代成功读取456并将aihdb保留在流中。这会使范围检查失败,然后第二次迭代尝试读取其余字符,但由于第一个字符不是数字而失败
如果要读取整行,请使用std::getline,然后将整行解析为一个数字。例如:
#include <iostream>
#include <string>
using std::cout;
int main()
{
while (true)
{
std::cout << "Enter a number between one and nine. \n";
std::string line;
std::getline(std::cin, line);
int oneandnine;
size_t pos;
try
{
oneandnine = std::stoi(line, &pos);
}
catch ( std::exception& )
{
oneandnine = -1;
}
if (pos != line.size() || oneandnine > 9 || oneandnine < 1)
{
std::cout << "INVALID INPUT!\n";
}
else
{
break;
}
}
return 0;
}
这正是你所想的 不会立即设置失败标志,相反,格式化输入运算符会将整数456读入1和9,但不会设置失败标志,因为它是有效的整数值。这将导致执行else情况,因为std::cin.fail为false,而oneandnine不在1和9之间 在下一次迭代中,您将读取无效输入,并设置失败标志,从而导致第二次错误输出 处理验证的一种常见方法是将整行读入字符串,将该字符串放入并使用该字符串尝试解析输入:
if (!std::getline(std::cin, line))
{
// Failure of some kind, could be EOF or something else
// Probably best not to continue in this case
}
std::istringstream iss(line);
if (!(iss >> oneandnine))
{
// Invalid input, report it as such
}
if (oneandnine < 1 || oneandnine > 9)
{
// Invalid number, report it as such
}
// Correct input, continue with program
请注意,上述代码将认为6abc等输入有效。6将被提取为1和9,abc部分将被无声地丢弃。如果不需要,还有其他解析方法,例如,或者如果不需要异常。这样做而不是>>提取,但是上面的其余代码应该可以。如果您也在寻找修复类似问题的方法,请将数据读入字符串,然后自己将字符串转换为整数。这样,您就可以完全控制输入的有效性测试,而不是让系统来执行这些检查。从std::istringstream读取也有完全相同的问题,除非您检查读取操作是否消耗了整个输入stream@AlanBirtles不,不是真的。因为用户输入已经被getline调用使用了,这意味着这样的输入会被默默地忽略。我想OP希望整个输入都是有效的,而不是默默地忽略无效的输入Std::istream不在整行中读取没有多大意义。给定上下文,您的意思是流操作符>>不读取整行吗?@user4581301 operator>>是std::istream:的一部分,但std::istream::getline也是。