2

出于某种原因,当我到达某个位置时,我必须按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');

有什么建议么?

4

3 回答 3

8

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

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

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

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

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

情况1:

cin.ignore()如果您在执行格式化的输入操作(即使用运算符)之后执行未格式化的输入操作(如),则通常需要调用。getline>>

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

因此,在这里您通常会在您cin.ignore(...)连续执行的最后一个格式化输入操作之后调用 call 以摆脱换行符,从而保证输入缓冲区为空。之后,您可以放心getline地直接调用,因为您知道缓冲区是空的。

相反,将它放在any之前getline是一个坏主意,就像您在代码中所做的那样,因为可能存在导致getline输入缓冲区干净的代码路径,因此ignore调用将阻塞。

案例二:

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

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


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

于 2012-11-26T00:04:27.367 回答
0

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

于 2012-11-25T23:58:49.807 回答
0

答案可以在这里找到。

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

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

于 2012-11-26T00:01:06.457 回答