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

How while(!(cin >> x)) works to re-prompt for input

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

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

我将其用作处理输入错误的措施。

所以ar是一个空整数数组,如果我决定输入'k',那么

!(cin >> ar[i]) 

是真的。

从这里我清除输入缓冲区(我认为这是正确的,我希望有人确认或对此提出异议)。然后终端打印 "Invalid input..." 现在,如果我只是按 Enter 没有任何反应,但是 Enter 不是换行符吗?所以代码不应该是

while(cin.get() == '\n'

?

整个代码的目标是不断打印错误并请求输入,直到用户输入有效数字,然后才能继续进入程序。

包含整个代码的循环...

while(!(cin >> ar[i]))

表示如果 cin 流中的输入无效则循环。由于 ar 是整数数组,如果输入不是数字,则输入无效。

cin.clear(); // clears bad input

cin流遇到无效输入时,程序开始执行循环并继续到这行代码。由于流遇到无效输入,它有一个标志表明存在错误。正如评论所说,这要求您 "clear bad input." 基本上这样做是为了摆脱这个标志。如果不这样做,该标志将保留在流中,并且程序将在下次使用 cin 流时遇到另一个错误,无论用户输入是否有效。

 while(cin.get() != '\n')
        continue;

当程序接受用户的输入时,它接受了字符串、char 等无效输入,但在 cin 流中留下了 '\n'。为了防止下次使用 cin 流时出错,程序必须去掉那个 '\n',连同其他任何遗留的东西。 cin.get() 从 cin 输入流中只读取一个字符并 returns 它。由于此函数的 return 值未分配给任何内容,因此所做的只是丢弃读取的字符。如果流中遗留的字符不止 '\n',则此循环会在处理之前检查读取的字符的值。这样,当读取的字符不是“\n”时,循环会继续执行。或者换句话说,它循环直到读取的字符是'\n'。 continue 唯一做的就是告诉程序跳过循环的当前迭代的其余部分并开始下一次迭代。在这种情况下,这相当于给循环一个空体。您完全可以将 continue; 替换为 {},程序将执行完全相同的操作。

cout << "Invalid input, please enter valid scores";

程序已清除 cin 中的标志,并且还清除了 cin 中可能遗留的任何数据。现在已经处理了所有来自无效输入的错误,只剩下一件事要做。是时候通知用户输入无效并请求新的输入了。如果用户输入更多无效输入,则循环重复。如果用户输入有效,程序将继续执行下一行代码。

while(!(cin >> ar[i]))

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

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

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

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

  • eof(文件结尾,对于输入的 "proper" shutdown/close,由 UNIX/Linux 中的 ^D 提供,^Z在 Windows 中,当程序被调用时输入结束,如 echo input | program).

以上所有方式均在"State Functions" here.

下进行了描述

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

{
    cin.clear(); // clears bad input

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

    while(cin.get() != '\n')
        continue;

这会尝试从终端读取字符,直到遇到换行符 \n。这个想法显然是为了清除可能导致 fail 条件的其余假定无法解析的输入。可悲的是,如果问题是或变成 badeof 条件,那么此循环将挂起程序,旋转燃烧 CPU 无济于事。

    cout << "Invalid input, please enter valid scores";
}

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


Now if I just press enter nothing happens, but isnt enter the newline char?

每当外层循环执行时 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: ";
}