为什么我必须按enter两次

Why do I have to press enter Twice?

本文关键字:enter 两次 为什么      更新时间:2023-10-16

由于程序中的某些原因,当我到达某个位置时,我必须按两次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()是不常见的(除非你真的想跳过字符);为了安全起见,不要随意传播,否则你会遇到你描述的问题。

答案可以在这里找到。

当n个字符被提取并丢弃时,或者当找到字符delim时,提取结束,以先到者为准。在后一种情况下,熟食字符本身也会被提取出来。

因此,在您的情况下,程序将不会继续,直到收到'n'字符。

我认为cin.ignore(numeric_limits<streamsize>::max(), 'n');在输入中期望n,但它找不到它,所以你必须再次按Enter才能找到它。