C ++中while循环的异常行为

时间:2018-09-23 17:06:35

标签: 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();
            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;
}

,当提供了类似456aihdb的输入时,得到了类似的东西:

  INVALID UNPUT!
  Enter a number between one and nine.
  INVALID UNPUT!
  Enter a number between one and nine.

为什么这样循环两次?是因为当456被丢弃而其余aihdb不在时导致它再次循环并跳过cin输入吗?

2 个答案:

答案 0 :(得分:1)

完全按照您的想法。

不会立即设置fail标志,而是格式化的输入运算符将整数456读入oneandnine,但不设置fail标志,因为它是有效的整数值。这导致执行else情况,因为std::cin.fail()为假,并且oneandnine不在19之间。

您读取无效输入的下一次迭代和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::stoistd::strtol(如果不需要例外)。这样做而不是>>提取,但是上面的其余代码应该没问题。

答案 1 :(得分:-1)

std::istream的{​​{1}}不能整行阅读。它会读取直到找到一个无效字符或空白为止,如果它在该无效字符之前找到了一个有效字符,则读取操作将成功并将无效字符保留在流中。

在您的示例中,第一次迭代成功读取operator >>并将456留在流中。这将使您的范围检查失败,然后第二次迭代尝试读取其余字符,因为第一个字符不是数字,因此失败。

如果要阅读整行,请使用aihdb,然后将整行解析为一个数字。例如:

std::getline