Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/google-app-engine/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++中while循环的意外行为_C++_Arrays_Loops_While Loop - Fatal编程技术网

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也是。