为什么我要输入两次?

时间:2012-11-25 23:52:14

标签: c++ iostream clear ignore

出于某些原因,当我到达某个地点时,我必须按两次 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');

有什么建议吗?

3 个答案:

答案 0 :(得分:7)

在我看来,你正在抛出太多cin.ignore()左右,不知道为什么需要它们以及何时将它们放在那里。

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

  1. 混合格式化和未格式化的输入时;
  2. 从格式化的输入错误中恢复。
  3. 在这两种情况下,您都希望从输入缓冲区中删除虚假字符;如果没有任何这样的字符(这可能是你的程序中发生的事情),cin.ignore()将暂停执行并等待用户输入 - 毕竟,你要求它忽略一些字符,并且该死的,它会服从它的命令。

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

    案例1:

    如果您在执行格式化输入操作后执行无格式输入操作(如cin.ignore()),则通常需要

    getline次调用(即使用>>运算符。

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

    因此,在这里,您通常会调用cin.ignore(...)调用,以便在连续执行的最后一次格式化输入操作之后删除换行符,从而保证输入缓冲区为空。之后,您可以毫不畏惧地直接致电getline,知道您将缓冲区留空了。

    相反,将置于任何getline之前是一个坏主意,正如您在代码中所做的那样,因为可能存在导致{{1}的代码路径输入缓冲区干净,所以getline调用将阻塞。

    案例2:

    ignore在格式化的输入操作中遇到错误时,它会在缓冲区中留下“坏”字符,因此如果您重试该操作,则会无休止地陷入困境,因为违规者仍然存在。通常istream成语来拯救,从输入缓冲区中删除整个违规行。

    同样,您不会随机地放置clear()/ignore()序列,而只是在您从格式化输入操作(设置流的failbit)获得输入错误之后。


    现在,除了这些情况之外,使用clear()/ignore()并不常见(除非你真的想跳过字符);不要随意传播“只是为了安全”,因为否则你会遇到你描述的问题。

答案 1 :(得分:0)

我认为cin.ignore(numeric_limits<streamsize>::max(), '\n');期望输入中有\n并且找不到它,因此您必须再次按 Enter 才能找到它。< / p>

答案 2 :(得分:0)

答案可以找到here

  

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

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