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不在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)。这样做而不是>>提取,但上面的其余代码应该没问题。

另一答案

std::istreamoperator >>不读全文。它会读取,直到找到无效字符或空格,如果它在无效字符之前找到了有效字符,则读取操作成功并且无效字符留在流中。

在您的示例中,第一次迭代成功读取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循环的意外行为的主要内容,如果未能解决你的问题,请参考以下文章

C语言while执行不了,代码见图?

c++中while循环的意外行为

C# - var 在 for 循环中的行为不符合预期

c_cpp 这个简单的代码片段显示了如何使用有符号整数在C中完成插值。 for()循环确定要插入的范围

下面代码的C语言中while(x--)是啥意思

C#使用while循环将项添加到List [关闭]