getline help

Just starting out and can't seem to figure this out. Basically, trying to get passenger names, if they want to sit in first class or coach and then assign them to a seat. My problem is when I ask for the user to input the passengers name, the getline (cin, name) skips/returns a blank space. The program doesn't wait for me to input the passengers name before it moves on to the next part of the code. It has worked fine in other programs but I can't figure out what is wrong with this one.

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
35
36
37
38
39
40
41
#include <iostream>
using namespace std;

int main (void)
{

    int seatNumber = 0, firstClass = 0, coachClass = 0,;
    string name, whatClass, morePassengers;
    
    cout << "Do you have a passenger that you wish to enter? Yes or No?  ";
    cin >> morePassengers;
    if (morePassengers == "No")
       cout << endl << endl << "Thank you, have a nice flight." << endl;
    else 
         {      
         cout << endl << endl << "Please enter the passengers name: ";
         getline (cin,name);
         
         cout << endl << endl << "What class would " << name << " like to sit, First or Coach?  ";
         cin >> whatClass;
         if (whatClass == "First")
         {
            firstClass += 1;
            cout << endl;
            cout << name << " is assigned to seat number " << firstClass << " in " << whatClass
            << " class.";
         }
         else if (whatClass == "Coach")
         {
              coachClass += 1;
              cout << endl;
              cout << name << "is assigned to seat number " << coachClass << " in " << whatClass
              << " class.";
         }
         else 
              cout << endl << "You didn't enter a correct class to be seated! ";
         }
    cout << endl << endl;          
    system ("pause");
    return (0);
}


Any help is appreciated, I'm getting frustrated.
No doubt you'll be surprised to find that your problem DOESN'T lie in your getline() statement -- which is working perfectly. Rather it lies in the earlier cin statement;

1
2
    cout << "Do you have a passenger that you wish to enter? Yes or No?  ";
    cin >> morePassengers;


The problem is that here you're using cin to read a string - but when reading a string cin stops reading as soon as it encounters any white space (tab, return, or space).

Keep in mind here that the user is not responding to this question merely by typing "Yes" or "No", but by typing "Yes<return>" or "No<return>" and this is what the computer is working with.

What's happening is that cin is taking "Yes" or "No" -- reading up to but not including <return> -- and then moving on leaving <return> in the input buffer.

So when your program gets to;

 
         getline (cin,name);


all the computer sees is a nice fat <return> sitting in the input buffer. And as getline() reads up to and including <return> then it responds perfectly; reading a string of zero characters, ending in a <return> character (which it discards). The computer THINKS that you actually meant to do this. So your getline() is, as I said earlier, working perfectly fine.

Just for interest sake, try responding to your original "Yes/No" question by typing "Yes thanks very much" -- you'll see that your passenger is assigned the name " thanks very much" because cin reads "Yes" -- stopping at the first space and leaving " thanks very much<return>" sitting in the input buffer. getline(cin, name) then reads everything up to and including <return>, discards <return> and assigns " thanks very much" to the string "name".

What you need to do is to flush this <return> from the input buffer -- which you could do in at least two ways;

1. Don't use cin << morePassengers. Change it to;

 
         getline (cin,morePassengers);


Or...

2. Flush the input buffer by reading a single char from the buffer after your call to cin;

1
2
3
    cin >> morePassengers;
    char a;
    cin.get(a);


Given the flexibility that C++ allows when it comes to input, there's probably another dozen ways to do this, but both the above should do the trick -- although they will give you OTHER problems you probably haven't thought about yet! You need to keep in mind that EVERYTHING you type goes into the input buffer and whatever is NOT removed by any particular function call just sits there to be taken up by the NEXT function call that looks at the input buffer. I/O function calls, in other words, read from the input buffer EXACTLY what their specifications say they do and terms like "reads a single char", "up to the first white space", "up to and including <return>", "discarding <return>" and so on, need to be kept in mind when using I/O functions.

I'd suggest you read up a bit on C++ I/O and the input buffer -- Google is your friend.

BTW: if your wondering why getline() in your previous programs seemed to work fine - I'd guess that you DIDN'T have a call to cin before calling getline() so this buffer problem probably wasn't occuring.
Last edited on
Thanks for the help, I think I understand the concept now. I could not find what you just explained all night. As a follow up question... is it always a good idea to use the getline statement when getting any string input from the user?? Or are there times where cin >> will be a better choice?
Hmmm...good question -- with no really simple answer.

I guess I'd want to say three things;

First, remember: "the computer is never wrong!" Unlike dogs, computers ALWAYS do EXACTLY what you tell them and NEVER forgive you for mistakes. So the most important thing you can learn is KNOW WHAT YOU'RE TELLING THE COMPUTER TO DO because it WILL obey. Using "cin << variable" is the best command you can ever use IF you want the computer to "cin << variable". But if you want the computer to "getline(cin, string)" then the best command you can ever use is "getline(cin, string)". If you KNOW that cin stops reading at a tab, space, or <return> then you've already answered the question as to whether cin or getline() is better for STRING input (char or integer input is a different issue) -- the fact is that "cin << string" will only return a string of contiguous characters (i.e. no spaces or tabs) which makes it a pretty poor string handling method!

Second, it's actually a very happy day in programming when you find a command which tells the computer to do EXACTLY what you want it to do. More often than not, we need to do a little bit of house cleaning. And you can only do this if (as per my first comment) you KNOW WHAT YOU'RE TELLING THE COMPUTER TO DO. Let's think about this a bit in terms of the problem you've been having (above);

Using "cin << string" to get a "yes/no" answer gets the response, but leaves behind _at least_ a <return> in the buffer, and _perhaps_ more. This leaves a bit of a mess which YOU need to clean up before the input buffer is available for next time. BUT at least using cin does the hard work of truncating the input string to a single word for you -- a task which getline() leaves you to do on your own.

Using "getline(cin, string) leaves the input buffer clean, BUT you now have much less surety about what the string contains. Remembering, first up, that "Y" is different from "y" (so "yes", ""Yes", "YES" and "yES" (as in -- "yES cAPS-lOCK iS oN") are all different) THEN you now have to work out how you're going to handle ALL the possible responses from "Y" to "Well, I dunno because I'm not sure if Bob is coming. We called his place and there was no answer, so I figure that he's coming but I can't be sure. If he turns up then yeah I guess there's gonna be another passenger." getline(cin,string) will return both of these quite faithfully -- question is, what are YOU going to do about it? The good news is that if you have a strategy for processing the result of a call to getline() then you can actually deal with rediculous responses like the "late Bob" example. You could, for instance, search the string looking for any occurence of "yes/no", "yep/nope" and "yeah/nah" and continue appropriately.

Third, I think that this really comes down to control. I think it would be fair to say that an experienced programmer would rather get the entire input string and process it in a well thought-out way. This makes for longer and more complex code, but it also makes for more control. Using getline(cin, string) gives you the problem of having to deal with longer, more complex, user input. But at least YOU (and not the computer) are deciding what does, or doesn't, get ignored. With strings this more often than not means using the features of the <string> class (for which you need to include using #include <string>). This raises the level of complexity again, and means learning new classes and methods, BUT this is exactly the same as saying that it gives you more power, and so more control.

The bottom line? Knowledge is power, and the more you know about what various commands do in particular situations, the better placed you'll be to choose the most appropriate command for your circumstances AND how to take care of any unwanted side-effects it may produce.

All this might make your head swim, and if so my advice to you would be this -- don't worry too much about all the various options available to you at this stage. Make the effort to learn one or two things really well. It will be far more helpful for you to have a REALLY good grasp of how "cin" works even if you eventually NEVER use it for the simple reason that a good grasp of "cin" will teach you ALOT about principles of C++ input/output which you can then take with you to understanding "getline()" and from there to understanding the <string> class. In any case, the programs you'll be writing at this stage will be simple enough that you don't need to add complexity by devising advanced input processing routines. Keep it simple, but KNOW WHAT YOU'RE TELLING THE COMPUTER TO DO.

And, most of all...

Have fun!
Last edited on
Topic archived. No new replies allowed.