当我使用getline时,为什么cout会打印两次?

7

我正在尝试使用getline读取一串文本。但是,它会打印两次“请输入您的选择”的提示信息:

Please enter your selection
Please enter your selection

如果我输入了无效的文本,它会重新循环,并且每次循环后只打印一次。
while (valid == false) {    
    cout << "Please enter your selection" << endl;
    getline (cin,selection);

    // I have a function here which checks if the string is valid and sets it to true 
    // if it is valid.  This function works fine, so I have not included it here.  The while
    // look breaks correctly if the user enters valid input.
}

有人知道为什么会发生这种情况吗?谢谢。

尝试在第一次打印后刷新std::cout:flush(cout); - Fantastic Mr Fox
2
@Ben,对于交互设备,endl应该会自动完成这个操作。 - paxdiablo
1
你能提供一些(简短的)可编译代码来重现这个问题吗? - mfontanini
2
你可以在循环之前尝试使用 cin.ignore(INT_MAX); cin.clear(); 吗? - scientiaesthete
可能是为什么std :: getline不会阻塞?的重复问题。 - Martin York
显示剩余2条评论
2个回答

10

可能是由于在进入循环之前存在来自先前操作的输入缓冲区中的内容。

getline 读取到这些内容,发现其无效,然后循环再次运行。


举个例子,在进入循环之前,假设你读取了一个单独的字符。但是,在Cooked模式下,您需要输入该字符和换行符才能执行操作。

因此,您读取字符并将换行符留在输入缓冲区中。

然后您的循环开始,读取换行符,认为它无效,因此循环返回以获取您的实际输入行。

当然,这只是一种可能性,还有其他可能性-这非常取决于循环之前的代码及其对cin的处理方式。

如果 确实 是这种情况,则可以考虑类似以下的解决方法:

cin.ignore(INT_MAX, '\n');

在循环之前可能需要修复它。

或者,您可能希望确保在所有地方都使用基于行的输入。


以下是一些代码,以查看该场景的操作:

#include <iostream>
#include <climits>

int main(void) {
    char c;
    std::string s;

    std::cout << "Prompt 1: ";
    std::cin.get (c);
    std::cout << "char [" << c << "]\n";
    // std::cin.ignore (INT_MAX, '\n')

    std::cout << "Prompt 2: ";
    getline (std::cin, s);
    std::cout << "str1 [" << s << "]\n";

    std::cout << "Prompt 3: ";
    getline (std::cin, s);
    std::cout << "str2 [" << s << "]\n";

    return 0;
}

连同一份文字记录:

Prompt 1: Hello
char [H]
Prompt 2: str1 [ello]
Prompt 3: from Pax
str2 [from Pax]

你可以看到,它并没有真正等待第二个提示符的新输入,而是获取了你在第一个提示符处输入的整行剩余部分,因为字符e, l, l, o\n仍然在输入缓冲区中。

当你取消注释ignore这一行时,它会按照你预期的方式运行:

Prompt 1: Hello
char [H]
Prompt 2: from Pax
str1 [from Pax]
Prompt 3: Goodbye
str2 [Goodbye]

cin.ignore(INT_MAX, '\n'); 已经解决了这个问题。非常感谢您,也感谢您详细的回复。 - CocaCola

1
我会使用调试器(例如Linux中的gdb)来检查原因。为什么要做理论呢?当你可以找到真正的答案时。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接