由于我的程序中的某些原因,当我到达某个位置时,我必须按 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()
来“使输入正常工作”:
- 混合格式化和未格式化的输入时;
- 从格式化输入错误中恢复。
在这两种情况下,您都希望从输入缓冲区中删除虚假字符;如果没有任何这样的字符(这可能是您的程序中发生的情况),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/