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.
}

有谁知道为什么会发生这种情况?

谢谢

4

2 回答 2

10

当您进入循环时,可能还有来自先前操作的输入缓冲区中的内容。

被 捡到getline,发现无效,然后循环再次运行。


例如,假设在您进入循环之前,您读取了一个字符。但是,在熟化模式下,您需要在操作之前输入字符换行符。

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

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

这是一种可能性,当然,可能还有其他可能性——它在很大程度上取决于该循环之前的代码以及它对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]

您可以在其中看到它实际上并没有等待提示 2 的新输入,它只是获取您在提示 1 输入的行的其余部分,因为字符、 、 和e仍在l输入l缓冲区中。o\n

当您取消注释该ignore行时,它会以您期望的方式运行:

Prompt 1: Hello
char [H]
Prompt 2: from Pax
str1 [from Pax]
Prompt 3: Goodbye
str2 [Goodbye]
于 2012-08-10T01:30:55.790 回答
1

我会使用调试器(例如 linux 中的 gdb)来检查原因。当你能找到真正的答案时,为什么还要提出理论?

于 2012-08-10T02:02:05.760 回答