c ++中while循环的意外行为
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c ++中while循环的意外行为相关的知识,希望对你有一定的参考价值。
做了这样的事情:
int main()
{
while (true)
{
std::cout << "Enter a number between one and nine.
";
int oneandnine;
std::cin >> oneandnine;
if (std::cin.fail())
{
std::cin.clear();
std::cin.ignore(100, '
');
std::cout << "INVALID UNPUT!
";
}else if (oneandnine <= 9 && oneandnine >= 1)
{
break;
}else
{
std::cout << "INVALID UNPUT!
";
}
}
return 0;
}
当输入提供像这样的456aihdb
,得到这样的东西:
INVALID UNPUT!
Enter a number between one and nine.
INVALID UNPUT!
Enter a number between one and nine.
为什么这样循环两次?是因为当456
被丢弃而其余的aihdb
不会导致它再次循环并跳过cin
输入?
它完全按照你的想法。
fail
标志不是立即设置的,而是格式化的输入运算符将整数456
读入oneandnine
,但不设置fail
标志,因为它是一个有效的整数值。这导致else
案件执行,因为std::cin.fail()
是假的,oneandnine
不在1
和9
之间。
您读取无效输入的下一次迭代和fail
标志将被设置为导致第二个错误输出。
处理验证的一种常用方法是将整行读入字符串,将该字符串放入std::istringstream
并使用它来尝试解析输入:
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
将被提取到oneandnine
,而abc
部分将被无声地丢弃。如果不需要,还有其他解析方法(例如,如果不需要例外,则为std::stoi
或std::strtol
)。这样做而不是>>
提取,但上面的其余代码应该没问题。
std::istream
的operator >>
不读全文。它会读取,直到找到无效字符或空格,如果它在无效字符之前找到了有效字符,则读取操作成功并且无效字符留在流中。
在您的示例中,第一次迭代成功读取456
并在流中留下aihdb
。这会使您的范围检查失败,然后第二次迭代会尝试读取由于第一个字符不是数字而失败的剩余字符。
如果你想读整行,请使用std::getline
然后将整行解析为数字。例如:
#include <iostream>
#include <string>
using std::cout;
int main()
{
while (true)
{
std::cout << "Enter a number between one and nine.
";
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!
";
}
else
{
break;
}
}
return 0;
}
以上是关于c ++中while循环的意外行为的主要内容,如果未能解决你的问题,请参考以下文章