c++ - 为什么我必须按 Enter 两次?

标签 c++ iostream

由于我的程序中的某些原因,当我到达某个位置时,我必须按 Enter 两次才能提交。我添加了clear以防止它跳过输入,并添加了ignore()以防止它在缓冲区中保留任何额外的字符。我输入我的输入,然后它下降到一个新行,我再次点击 Enter ,它输入输入并继续程序,没有问题,但我想知道为什么。这是一个代码片段:

    cin.ignore();
    cout << "Enter Student Major (ex. COSC): ";
    cin.getline(student.major, 6);

    for(int i = 0; i < sizeof(student.major); i++)
        student.major[i] = toupper(student.major[i]);

    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

有什么建议吗?

最佳答案

我觉得你折腾太多了cin.ignore()周围,​​不知道为什么需要它们以及何时将它们放在那里。

有两种常见情况需要 cin.ignore() 来“使输入正常工作”:

  1. 混合格式化和未格式化的输入时;
  2. 从格式化输入错误中恢复。

在这两种情况下,您都希望从输入缓冲区中删除虚假字符;如果没有任何这样的字符(这可能是您的程序中发生的情况),cin.ignore() 将暂停执行并等待用户输入 - 毕竟,您要求它忽略某些字符角色,该死的,它会服从它的命令。

(尽管 ignore() 默认情况下只会“吃掉”一个字符,无论它是什么,执行都会暂停,直到找到换行符,因为默认情况下 cin是行缓冲的 - 在收到换行符之前不会检查新输入)

情况1:

如果您在执行后执行未格式化的输入操作(如getline),则通常需要

cin.ignore()调用>格式化输入操作(即使用>>运算符)。

发生这种情况是因为 >> 运算符将换行符留在输入缓冲区中;如果您仅执行格式化输入操作(默认情况下,它们在尝试解释输入之前会跳过所有空格),那么这不是问题,但如果之后执行未格式化输入,则这是一个问题:默认情况下读取 getline直到它找到换行符,因此留下的“虚假换行符”将使其立即停止读取。

因此,这里您通常会在连续执行最后一次格式化输入操作之后调用 cin.ignore(...) 来消除换行符,从而保证输入缓冲区是空的。之后,您可以直接调用 getline 而无需担心,因为您知道缓冲区已空。

相反,将其放在任何 getline 之前是一个坏主意,就像您在代码中所做的那样,因为可能存在导致该结果的代码路径getline 具有干净的输入缓冲区,因此 ignore 调用将被阻止。

情况2:

istream在格式化输入操作中遇到错误时,它会将“坏”字符留在缓冲区中,因此如果您重试该操作,您会陷入无休止的困境,因为违规者仍然存在。通常的 clear()/ignore() 习惯用法可以解决这个问题,从输入缓冲区中删除整个有问题的行。

同样,您不能随机放置 clear()/ignore() 序列,而是仅在从格式化输入操作(设置流的失败位)收到输入错误之后)。

<小时/>

现在,除了这些情况之外,使用 cin.ignore() 并不常见(除非您确实想跳过字符);不要“为了安全起见”随意传播它,否则你会遇到你所描述的问题。

关于c++ - 为什么我必须按 Enter 两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13556890/

相关文章:

c++ - OSX 上 32 和 64 位程序之间共享内存中的 boost::进程间同步机制(互斥体、条件)

c++ io streams sync_with_stdio 没有区别

c++ - 如何在 openscenegraph 中旋转相机(在模型中穿行)?

c++ - 使用 open() 在文件的特定位置写入

c++ - Vivado_hls 2014.4 Ubuntu 14.04 x64 vivado 包含错误

c++ - 我可以使用 CreateFile,但将句柄强制为 std::ofstream 吗?

c++ - 有没有办法使用特征使 pos_type 和 off_type 成为 int64_t?

c++ - Arduino 打印在大量打印时失败

c++ - C++ iomanip 库的有效使用

c++ - 如果在多个共享库中调用并且启用了libstdc++静态链接,则C++流变得很糟糕