c++ trap

I'm a newbie to c++ but I have a background in python, but with that
Said, I have run into a bit of a snag with my toying around with c++.
Before I ask my question, I will show you my code first.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>

using std::cout;
using std::cin;
using std::endl;
using std::string;

int main(){
    
    // Generic input
    int x;
    cin >> x;
    cout <<"\n";
    cout << x * 42;
    
    // getline after generic input
    string y;
    getline(cin,y);
    cout << y;
    
    return 0;
}



So when I run the code this way, it will perform the
Math operation, however, it will not continue with the
rest of the // getline after generic input code. Why is that?
Also if I wrap that code into a function and try to run it, it gives me the word
trap after the math operation, and again, why?

Thanks ahead for any explanation!!!
Last edited on
After cin >> x; put a line cin.ignore(1000,'\n');
Somebody will come along and explain at great length or just google it.
Last edited on
The problem is the use of the character '\n':

cin >> x;

leaves that character in the stream.

getline(cin,y);

will use by default '\n' to determine the end of the line. Due to the previous cin there is still a '\n' in the input stream and the getline(...) returns an empty string.

You can avoid this when writing:

cin >> x >> std::ws; // Note: std::ws removes '\n'
>> std::ws works as desired if the next input/output is via cin.

Unfortunately, it screws up the order of the input/output operations if (as here) the next input/output is via cout.

cin.ignore(1000,'\n); maintains the intended order.




Compare:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <string>

using std::cout;
using std::cin;
using std::string;
using std::ws;

int main()
{
   int x;
   cin >> x >> ws;
   cout << '\n';
   cout << x * 42;

   string y;
   getline( cin, y );
   cout << y;
}
10
Help

420Help 


and

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>

using std::cout;
using std::cin;
using std::string;

int main()
{
   int x;
   cin >> x;   cin.ignore( 1000, '\n' );
   cout << '\n';
   cout << x * 42;

   string y;
   getline( cin, y );
   cout << y;
}
10

420Help
Help 


Last edited on
>> ignores proceeding white-space, extracts as per the type of the extraction variable and (assuming valid extraction) until a white space char is found. This terminating white-space char is NOT extracted.

getline() extracts all data until the specified terminating char is found (\n if none specified). It does not ignore proceeding white space and extracts and discards the terminating char.

From this you can see that these 2 don't play nicely together. If >> is followed by a getline() then the white space char left by >> is treated as an input char by getline(). If this is the getline() terminating char (such as \n) then getline() is terminated with no input obtained.

Note that >> followed by >> is OK and getline() followed by >> is OK. The issue is just when >> is followed by getline(). In this case the >> terminating char (usually \n) needs to be extracted from the stream before getline(). This is the purpose of using .ignore() in this context.

Also note that if there are no chars to ignore, then .ignore() will wait until there are. So only use before .getline() in this context when getline() is preceded by >>. Don't use between consecutive uses of getline() othereise you'll loose the first char from the second getline().
Hey everyone! Thanks a million for your replies. While I have not searched anything yet, you all have given me
Some food for thought. I think I kind of understand what is being said but I'll need to do some digging. Thx again!
DevTurtle


DevTurtle wrote:
Apologies if this doesn't format right

There are some resources/links you should read that can help:
PLEASE learn to use code tags, they make reading and commenting on source code MUCH easier.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

HINT: you can edit your post and add code tags.

Some formatting & indentation would not hurt either
@lastchance, You could put the ws in the getline instead:
 
getline( cin >> ws, y );

@OP std::ws is a red herring. On face value it 'works', maybe, but doesn't address your issue beyond being a hack.

The following, Error Case 2 in particular, gives a fairly definitive going over of the problem including how C++streams are designed to work. [Notably clear() and numeric limits haven't been mentioned here until now ;) ]

https://www.learncpp.com/cpp-tutorial/stdcin-and-handling-invalid-input/

Most ppl here will agree that learncpp isn't a bad reference along with stackoverflow and cplusplus tutorials and reference sections.

(PS: Despite the late edit, I missed the second "'" so it is '\n' not '\n in my above.)
DizzyDon wrote:
@lastchance, You could put the ws in the getline instead:


I did try that @DizzyDon. But it actually does exactly the same as putting it in the cin>> statement.

In this instance, mixing cin and cout statements, buffering seems to mean that only cin.ignore() gives the order of input/output operations as coded.
Topic archived. No new replies allowed.