while(!(cin >> x)) 如何重新提示输入

3 c++ iostream

while(!(cin >> ar[i]))
    {
        cin.clear(); // clears bad input
        while(cin.get() != '\n')
            continue;
        cout << "Invalid input, please enter valid scores";
    }
Run Code Online (Sandbox Code Playgroud)

上面的代码来自一个更大的文件。我从一本教科书中复制了这段代码,但我不太习惯使用它,因为我不明白它是如何工作的。

我用它作为处理输入错误的措施。

ar空整数数组也是如此,如果我决定输入“k”,那么

!(cin >> ar[i]) 
Run Code Online (Sandbox Code Playgroud)

是真的。

从这里我清除输入缓冲区(我认为这是正确的,我希望有人确认或对此提出异议)。然后终端打印“无效输入...”现在,如果我按什么都不会发生,但换行符Enter不是吗?Enter所以代码不应该读

while(cin.get() == '\n'
Run Code Online (Sandbox Code Playgroud)

Ton*_*roy 5

while(!(cin >> ar[i]))
Run Code Online (Sandbox Code Playgroud)

这尝试从 中解析一个值cin并将其存储在 中ar[i]。默认情况下,>>首先跳过空格,然后查看 中的字符是否cin描述了无论类型ar[i]是什么的合法值。如果找到合法值,则cin流状态保持不变good,并且它将在给定的布尔/操作operator bool() const中启动,从而导致循环中断。not!while

如果解析失败,流状态将设置为以下一项或多项:

  • bad(如果存在一些不可恢复的流错误,例如通过断开连接的网络连接提供的标准输入),

  • fail(如果字符没有形成该类型的合法值),或者

  • eof(文件结束,用于输入的“正确”关闭/关闭,如 UNIX/Linux 中的 ^D、Windows 中的 ^Z 以及调用程序时的输入结束,如 中所示echo input | program)。

所有上述模式均在此处的“状态功能”下描述。

如果由于上述任何错误情况而进入循环......

{
    cin.clear(); // clears bad input
Run Code Online (Sandbox Code Playgroud)

...这不会清除流中的任何输入数据,但会清除badeoffail状态标志,之后可以进行进一步的输入尝试,尽管处于badeof状态的流在进一步输入时可能会立即重新进入该状态尝试(但并非总是如此 -如果用户键入/生成 EOF 代码,然后再次键入实际文本,某些操作系统可能会在eof满足条件后允许成功输入...std::cin

    while(cin.get() != '\n')
        continue;
Run Code Online (Sandbox Code Playgroud)

这会尝试从终端读取字符,直到\n遇到换行符。这个想法显然是为了清除其余的假定的不可解析的输入,这些输入可能会导致fail更早的情况。遗憾的是,如果问题曾经是或变成了badoreof条件,则该循环将挂起程序,使燃烧的 CPU 旋转而无济于事。

    cout << "Invalid input, please enter valid scores";
}
Run Code Online (Sandbox Code Playgroud)

如果问题只是输入错误的值并且没有badeof条件,则将cout提示您进一步输入。


现在,如果我只按 Enter 键,什么也不会发生,但不是输入换行符吗?

每当外部循环执行时cin >> ar[i],它都会跳过空格,包括您键入的任何额外换行符,直到它看到一些输入(可能需要是一个完整的换行符终止行才能被终端或将其提供给程序的程序刷新),或一个badeof条件。内部 while 循环并不是为了消除空行 - 它试图丢弃其中包含假定的非数字文本的行。


更正的代码:

while (!(std::cin >> ar[i]))
{
    if (std::cin.bad() || std::cin.eof())
    {
        std::cerr << "Fatal error on cin while reading numbers\n";
        exit(EXIT_FAILURE);
    }
    std::cin.clear();
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    std::cout << "Invalid input, please enter valid scores\n: ";
}
Run Code Online (Sandbox Code Playgroud)