std::getline doesn't wait for input

the getline
std::getline(std::cin, input);
in test 2 doesn't wait for user input

I'm sorry for the length of code
but I can't reproduce problem in any other way.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int main() {
    //test one
    std::string text{};
    std::cout << "Enter a line of text for test one:\n";
    std::getline(std::cin, text);
    std::cout<<"line entered for test one=["<<text<<"]"<<std::endl;
    std::string sep(25,'-');
    std::cout<<sep<<std::endl;
    int choice{};
    std::cout<<"enter choice 0-exit 2-test 2:>";
    std::cin>>choice;
    if (choice==0)
        return 0;
    {
        while(true) {
            switch (choice) {
                case 2://test two
                {
                    std::string input{};
                    std::cout << "Enter a line of text for test 2:\n";
                    std::getline(std::cin, input);
                    std::cout << "line entered=[" << input << "]" << std::endl;
                    break;
                }
                default:
                    std::cout<<"wrong choice"<<std::endl;
            }
            std::cout<<"enter choice 0-exit 1-test:>";
            std::cin>>choice;
            if (choice==0)
                return 0;
        }
    }
}


cin is the culprit. Even I never know about this like forever man, but it turns out that cin, apart from not being able to read whitespaces, also leaves those trailing whitespaces in the buffer itself (note that leading whitespaces are ignored and completely omitted).

So if you typed
hello (tabspace) (linefeed i.e '\n')
and wanted cin to put that into a string variable,

it would put "hello" into the variable and leave (tabspace) (linefeed) in the buffer.

But wait! linefeed is what getline() uses to mark end of input! So what is happening is that the getline is reading the linefeed ('\n') from the buffer.

Try this:
1
2
3
4
5
string foo;
cin >> foo;
getline(cin, foo)
for(auto i: foo)
  cout << (int)i;


Run that snippet and type in say "Hello (tabspace)(linefeed)" or "Hello(linefeed)"
You will note that getline is reading whitespaces and tabspaces even though it never begun input.

How to solve this? Simply clear the buffer before allowing getline() to take input.

i.e,
put "cin.ignore(INT_MAX, '\n');"
before your getline statements when you are using cin.

That statement reads and discards characters from the buffer until it reaches '\n'.
thanks for the explanation and the hint I'm one step over;

snippet is now:
1
2
3
4
5
std::cout<<std::endl<< "Enter another line of text:\n";
            std::string input{};
            std::cin.ignore(INT_MAX, '\n');
            std::getline(std::cin, input);
            std::cout<<"other line entered="<<input;

but I need 2 return to close the input line and input var still remains empty


cin is the culprit. Even I never know about this like forever man


this is because you have learnt c++ a while ago

I'm php developer starting now the c++ adventure something like lesson one.



this is because you have learnt c++ a while ago

I think you misread my comment. I said "Even I never knew about this like forever man" meaning it's something not a lot of people know about. I just wanted to make sure you didn't think I meant "Even I knew about this like forever man". :P!

std::string input{};
Is wrong syntax.

it should be
std::string input;

Don't worry though it's a naive mistake. You'll get used to it.
Just know that the general rule for declaring variables is:
DATATYPE VAR_NAME;
here datatype is string and var_name is input.

Which compiler are you using?

Only reason I can think of is that you haven't written #include<string> if even fixing the above doesn't work.

I'm a newbie too. And C++ is my first language so it's all fine ;)
thanks to your hint I solved googling

just added
 
std::cin.clear();
Did that help? What is your full code snippet now if you don't mind?
If I'm not right cin.clear() is used to clear error flag of cin.

Can error flag of cin affect getline()??
Only place where you can get an error flag is in the line cin>>choice if you try to type a non-digit..

Which compiler are you using? Because the first code snippet in original post is faulty right?
Last edited on
closed account (1vf9z8AR)
1
2
3
4
5
int temp;
cin>>temp;
cin.ignore();
string str;
getline(cin,str);
t he full code now is :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <climits>

int main() {
    std::cout << "Hello, World!" << std::endl;
    std::string text; // Stores the input
    std::cout << "Enter a line of text:\n";
    std::getline(std::cin, text);
    std::cout<<"line entered="<<text;
    switch (1){
        case 1:
            std::cout<<std::endl<< "Enter another line of text:\n";
            std::string input{};
//            std::cin.ignore(INT_MAX, '\n');
            std::cin.clear();
            std::getline(std::cin, input);
            std::cout<<"other line entered="<<input;
    }
    return 0;
}


I suppose that
std::string input{};
is correct

std::string is type
input varname
{} empty initializer

as I know you can initializes a var in these way

1
2
3
int apple_count {5};
int apple_count(5);
int apple_count=5;

the book I'm reading states

these possibilities are equally valid as the braced initializer form and mostly completely
equivalent. Both are therefore used extensively in existing code as well. In this book, however, we’ll adopt
the braced initializer syntax. This is the most recent syntax that was introduced in C++11 specifically to
standardize initialization. Its main advantage is that it enables you to initialize just about everything in the
same way—which is why it is also commonly referred to as uniform initialization. Another advantage is that
the braced initializer form is slightly safer when it comes to narrowing conversions:















std::string input{}; is equivalent to std::string input;
{} is used for initializing, like you said. But when there is no initializing that is being done, what's the point of using {}?

In your code cin.clear(); is obsolete. It serves no purpose. Try running without cin.clear(); and you will notice that you get the same result.

cin.clear(); is used only when cin enters error state. cin might enter error state when you try to input non-digits to an integer variable.

I know that you might know this but you can omit the switch statement in your example.

And lastly in this case emptying the input buffer with cin.ignore(INT_MAX, '\n'); is not required because there is no cin statement. But if you were to have cin statement(s) and have a getline follow it then you will have to clear the buffer or the getline won't wait for input.
Topic archived. No new replies allowed.