Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is cout printing twice when I use getline?

Tags:

c++

I'm trying to read in a string of text using getline. For some reason, it prints 'Please enter your selection' twice:

Please enter your selection
Please enter your selection

If I key invalid text, it loops again, and only prints the one time each loop thereafter.

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

Does anybody have any idea why this may be occurring?

Thank you

like image 915
CocaCola Avatar asked Aug 10 '12 01:08

CocaCola


2 Answers

Probably there's something still in the input buffer from a previous operation when you enter the loop.

It's picked up by the getline, found to be invalid, then the loop runs again.


By way of example, let's say that, before you enter the loop, you read a single character. But, in cooked mode, you'll need to enter the character and a newline before it's actioned.

So, you read the character and the newline is left in the input buffer.

Then your loop starts, reads the newline, and deems it invalid so it then loops back to get your actual input line.

That's one possibility though, of course, there may be others - it depends very much on the code before that loop and what it does with cin.

If that is the case, something like:

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

before the loop may fix it.

Alternatively, you may want to ensure that you're using line-based input everywhere.


Here's some code to see that scenario in action:

#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;
}

Along with a transcript:

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

in which you can see that it doesn't actually wait around for new input for prompt 2, it just gets the rest of the line you entered at prompt 1, because the characters e, l, l, o and \n are still in the input buffer.

When you uncomment the ignore line, it acts in the manner you'd expect:

Prompt 1: Hello
char [H]
Prompt 2: from Pax
str1 [from Pax]
Prompt 3: Goodbye
str2 [Goodbye]
like image 161
paxdiablo Avatar answered Oct 14 '22 10:10

paxdiablo


I would use debugger (for example gdb in linux) to check why. Why make a theories when you can find out the real answer?

like image 39
klm123 Avatar answered Oct 14 '22 11:10

klm123