I'm trying to get input from the user using getline().
The following code works fine. It waits for the user to type the file name and stores it in fileName.
#include <iostream>
#include <string>
using namespace std;
string inputFile();
int main()
{
string fileName;
cout << "Enter the name of the file including the path" << endl;
getline(cin, fileName);
return 0;
}
However, this code does not work fine.
#include <iostream>
#include <string>
using namespace std;
string inputFile();
int main()
{
int option;
cout << "Enter option number" << endl;
cin >> option;
switch (option)
{
case 1:
{
string fileName;
cout << "Enter the name of the file including the path" << endl;
getline(cin, fileName);
break;
}
case 2:
cout << "You chose option 2";
break;
case 3:
cout << "You chose option 3";
break;
default:
cout << "value unknown";
}
return 0;
}
After the user enters 1 and the program enters the switch...case, the user is again asked for the file name. But, this time the program does not wait for a response.
Why is getline() not working the way it would outside the switch...case structure?
Any suggestions would be greatly appreciated.
cin leaves the newline character (\n) in the stream. cin.ignore() extracts and discards characters. It can be used to flush the cin until \n is reached.
So, the solution is to add std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); , before the 2nd call to getline(cin, fileName);
Also add cin.clear() to remove the error flag on cin
Example:
case 1:
{
std::string fileName;
std::cout << "Enter the name of the file including the path" << std::endl;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
getline(std::cin, fileName);
break;
}
The problem might be, that you are reading the number of the case via >> into the integer variable. By doing that, the newline produced by the enter key is still in the buffer. Now getline tries to read from the input stream and instantly receives a newline.
And because it only reads upon the next newline, it exits.
The problem has nothing to do with the switch-statement! Instead, it has to do with mixing formatted input (using operator>>()) and unformatted input (in this case std::getline()): the formatted input stops reading as soon as a character doesn't match the format. When reading an integer, it stops as soon as a non-digit is found. That is, any newline entered after the number will be stuck in the stream and std::getline() will happily take this newline as an opportunity to stop its input.
When switching between formatted and unformatted input, you normally want to get rid of whitespaces. For example, you could use
if (std::getline(std::cin >> std::ws, fileName)) { ... }
to first skip any whitespace, then attempt to read fileName and, if this is successful, process the input (input always needs to be checked for success).
You are mixing formatted input and line input on a single stream. This is a bad idea, use either formatted input operator>> or line input std::getline() never both on the same stream.
This is basically because of the way white space is handled. In this case you are leaving a \n character on the input when you read the option.
cin >> option;
This reads the option, but leaves anything after the option (after the integer) on the input stream (including the \n character). Thus the next use of std::getline() simply reads upto the \n character (which probably gives you zero characters).
Interactive user input is line based.
Especially since the std::cin stream is buffered (and thus not flushed until you hit return).
So when I read input from an interactive user I always read a line of text at a time. Then parse this line for what I am looking for.
std::string optionLine;
std::getline(std::cin, optionLine);
int option = boost::lexical_cast<int>(optionLine);
Note: You don't need boost::lexical_cast, you can achieve the same affect with std::stringstream and another variable.
// A simple alternative to boost::lexical_cast
// Not quite as pedantic as above but you can add more tests as required.
std::stringstream optionLineStream(optionLine);
int option;
if (optionLineStream >> option)
{
// reading the option worked.
}
Reading a line at a time and then parsing the input also has the advantage that you never put the input into a bad state and need to reset it (any bad state is set on intermediate std::stringstream objects). So fixing erroneous user input is easier.
Related
#include <iostream>
#include <string>
using namespace std;
struct UserInfo{
string userPhoneNumber;
string userName ;
string userAddress ;
};
int main ()
{
cout << "How many Entries do you want to enter?";
int userAmountSelection;
cin >> userAmountSelection;
UserInfo userOne [userAmountSelection];
for (int i = 0; i < userAmountSelection; i++){
cout << "Please enter your first and last name: ";
cin.ignore(); // possible problem in code
getline (cin, userOne[i].userName, '\n');
cout << "Please Enter your address, " << userOne[i].userName << ":";
cin.ignore(); // possible problem in code
getline (cin, userOne[i].userAddress, '\n');
cout << "Please enter your phone#: ";
cin.ignore (); // possible problem in code
getline (cin, userOne[i].userPhoneNumber);
}
for (int i = 0; i < userAmountSelection; i++){
cout << userOne[i].userName << " " <<
userOne[i].userAddress << " " <<
userOne[i].userPhoneNumber << endl;
}
return 0;
}
As you can see its a simple code for learning structs and experimenting. The problem i run into appears to be from cin.ignore () code. it ignores the first characters of the input strings on output. The code does compile, however input and output are skewed.
For example when i enter a name of Terry, it will output erry.
I have tried removing the cin.ignore (), however when i do that, the output skips over the parts where the user needs to enter data and leaves areas blank.
I have scoured the forums and found suggestions such as adding an argument to the cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');. for example, however this does not solve the problem and only adds to the list of errors I'm experiencing.
The Problem
The problem is with the placement of ignores to prevent the bug outlined in Why does std::getline() skip input after a formatted extraction? The ignores have been placed before the getlines, and while this solves the getline skipping problem, it causes the problem the Asker has encountered. There isn't always something that needs to be ignored.
For example
cin >> userAmountSelection;
will leave a line ending in the stream if the user typed in the amount and then hit enter.
cout << "Please enter your first and last name: ";
cin.ignore(); // possible problem in code
getline (cin, userOne[i].userName, '\n');
inside the for loop Would trip over this line ending if not for the ignore. But getline does not leave a newline in the stream , so the second and subsequent iterations of the loop have no newline to ignore. Part of the requiured data is ignored instead.
After
cin >> userAmountSelection;
rather than before
getline (cin, userOne[i].userName, '\n');
would be a good place to place an ignore so the newline is removed from the stream only after it has been left in the stream, but...
The Solution
The best way to handle this is to always read entire lines with getline and then parse those lines (see option 2 of this answer) into the pieces you want.
std::string line;
std::getline(std::cin, line);
std::istringstream(line) >> userAmountSelection;
This always works (Note: Requires #include <sstream>) and now you only have one type of reading going on, not a game of mix-n-match where you may forget you need an ignore.
Feel free to stop reading now.
The ignore approach requires some extra smarts. It's not as simple as it looks, in addition to fallibility of the human memory. You should place ignores AFTER an operation that leaves unwanted stuff in the stream. If you ignore BEFORE an operation, you often find yourself losing data you wanted because there was nothing to ignore.
std::cin >> userAmountSelection; // read a number
std::cin.ignore(); // discard the next character
Works a lot of the time, but what if the user typed in the amount and then a space and then hit enter or typed in all of the input they needed to type because they new darn well what the next prompt was? You gotta get a bit craftier.
std::cin >> userAmountSelection;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This ignore annihilates everything until it hits the end of the line or runs out of space in the stream. (Note: Requires #include <limits>)
The problem i run into appears to be from cin.ignore () code. it ignores the first characters of the input strings on output.
Looking at the istream::ignore declaration
istream& ignore (streamsize n = 1, int delim = EOF);
It will discard the first character by default.
I have tried removing the cin.ignore (), however when i do that, the
output skips over the parts where the user needs to enter data and
leaves areas blank.
That's because of the std::cin performed which left a residual newline which was then consumed by the getline. You'll only need ignore between the std::cin and getline calls:
std::cin >> userAmountSelection;
std::cin.ignore(); //---
...
for (int i = 0; i < userAmountSelection; i++) {
...
getline (...);
...
getline (...)
}
Also, there may be instances where you don't know if an std::cin will precede the getline. In that case, you may check if the input stream contains new line before doing ignore:
...
// some I/O operations happening here
...
// ignore if there's white space
if (std::iswspace(std::cin.peek())) std::cin.ignore();
std::getline(std::cin, somestring);
I wrote a very basic program in C++ which asked the user to input a number and then a string. To my surprise, when running the program it never stopped to ask for the string. It just skipped over it. After doing some reading on StackOverflow, I found out that I needed to add a line that said:
cin.ignore(256, '\n');
before the line that gets the string input. Adding that fixed the problem and made the program work. My question is why does C++ need this cin.ignore() line and how can I predict when I will need to use cin.ignore()?
Here is the program I wrote:
#include <iostream>
#include <string>
using namespace std;
int main()
{
double num;
string mystr;
cout << "Please enter a number: " << "\n";
cin >> num;
cout << "Your number is: " << num << "\n";
cin.ignore(256, '\n'); // Why do I need this line?
cout << "Please enter your name: \n";
getline (cin, mystr);
cout << "So your name is " << mystr << "?\n";
cout << "Have a nice day. \n";
}
ignore does exactly what the name implies.
It doesn't "throw away" something you don't need. Instead, it ignores the number of characters you specify when you call it, up to the char you specify as a delimiter.
It works with both input and output buffers.
Essentially, for std::cin statements you use ignore before you do a getline call, because when a user inputs something with std::cin, they hit enter and a '\n' char gets into the cin buffer. Then if you use getline, it gets the newline char instead of the string you want. So you do a std::cin.ignore(1000,'\n') and that should clear the buffer up to the string that you want. (The 1000 is put there to skip over a specific number of chars before the specified delimiter, in this case, the '\n' newline character.)
You're thinking about this the wrong way. You're thinking in logical steps each time cin or getline is used. Ex. First ask for a number, then ask for a name. That is the wrong way to think about cin. So you run into a race condition because you assume the stream is clear each time you ask for a input.
If you write your program purely for input you'll find the problem:
int main()
{
double num;
string mystr;
cin >> num;
getline(cin, mystr);
cout << "num=" << num << ",mystr=\'" << mystr << "\'" << endl;
}
In the above, you are thinking, "first get a number." So you type in 123 press enter, and your output will be num=123,mystr=''. Why is that? It's because in the stream you have 123\n and the 123 is parsed into the num variable while \n is still in the stream. Reading the doc for getline function by default it will look in the istream until a \n is encountered. In this example, since \n is in the stream, it looks like it "skipped" it but it worked properly.
For the above to work, you'll have to enter 123Hello World which will properly output num=123,mystr='Hello World'. That, or you put a cin.ignore between the cin and getline so that it'll break into logical steps that you expect.
This is why you need the ignore command. Because you are thinking of it in logical steps rather than in a stream form so you run into a race condition.
Take another code example that is commonly found in schools:
int main()
{
int age;
string firstName;
string lastName;
cout << "First name: ";
cin >> firstName;
cout << "Last name: ";
cin >> lastName;
cout << "Age: ";
cin >> age;
cout << "Hello " << firstName << " " << lastName << "! You are " << age << " years old!" << endl;
}
The above seems to be in logical steps. First ask for first name, last name, then age. So if you did John enter, then Doe enter, then 19 enter, the application works each logic step. If you think of it in "streams" you can simply enter John Doe 19 on the "First name:" question and it would work as well and appear to skip the remaining questions. For the above to work in logical steps, you would need to ignore the remaining stream for each logical break in questions.
Just remember to think of your program input as it is reading from a "stream" and not in logical steps. Each time you call cin it is being read from a stream. This creates a rather buggy application if the user enters the wrong input. For example, if you entered a character where a cin >> double is expected, the application will produce a seemingly bizarre output.
Short answer
Why? Because there is still whitespace (carriage returns, tabs, spaces, newline) left in the input stream.
When? When you are using some function which does not on their own ignores the leading whitespaces. Cin by default ignores and removes the leading whitespace but getline does not ignore the leading whitespace on its own.
Now a detailed answer.
Everything you input in the console is read from the standard stream stdin. When you enter something, let's say 256 in your case and press enter, the contents of the stream become 256\n. Now cin picks up 256 and removes it from the stream and \n still remaining in the stream.
Now next when you enter your name, let's say Raddicus, the new contents of the stream is \nRaddicus.
Now here comes the catch.
When you try to read a line using getline, if not provided any delimiter as the third argument, getline by default reads till the newline character and removes the newline character from the stream.
So on calling new line, getline reads and discards \n from the stream and resulting in an empty string read in mystr which appears like getline is skipped (but it's not) because there was already an newline in the stream, getline will not prompt for input as it has already read what it was supposed to read.
Now, how does cin.ignore help here?
According to the ignore documentation extract from cplusplus.com-
istream& ignore (streamsize n = 1, int delim = EOF);
Extracts characters from the input sequence and discards them, until
either n characters have been extracted, or one compares equal to
delim.
The function also stops extracting characters if the end-of-file is
reached. If this is reached prematurely (before either extracting n
characters or finding delim), the function sets the eofbit flag.
So, cin.ignore(256, '\n');, ignores first 256 characters or all the character untill it encounters delimeter (here \n in your case), whichever comes first (here \n is the first character, so it ignores until \n is encountered).
Just for your reference, If you don't exactly know how many characters to skip and your sole purpose is to clear the stream to prepare for reading a string using getline or cin you should use cin.ignore(numeric_limits<streamsize>::max(),'\n').
Quick explanation: It ignores the characters equal to maximum size of stream or until a '\n' is encountered, whichever case happens first.
When you want to throw away a specific number of characters from the input stream manually.
A very common use case is using this to safely ignore newline characters since cin will sometimes leave newline characters that you will have to go over to get to the next line of input.
Long story short it gives you flexibility when handling stream input.
Ignore function is used to skip(discard/throw away) characters in the input stream. Ignore file is associated with the file istream.
Consider the function below
ex: cin.ignore(120,'/n');
the particular function skips the next 120 input character or to skip the characters until a newline character is read.
As pointed right by many other users. It's because there may be whitespace or a newline character.
Consider the following code, it removes all the duplicate characters from a given string.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin>>t;
cin.ignore(); //Notice that this cin.ignore() is really crucial for any extra whitespace or newline character
while(t--){
vector<int> v(256,0);
string s;
getline(cin,s);
string s2;
for(int i=0;i<s.size();i++){
if (v[s[i]]) continue;
else{
s2.push_back(s[i]);
v[s[i]]++;
}
}
cout<<s2<<endl;
}
return 0;
}
So, You get the point that it will ignore those unwanted inputs and will get the job done.
It is better to use scanf(" %[^\n]",str) in c++ than cin.ignore() after cin>> statement.To do that first you have to include < cstdio > header.
I wrote a very basic program in C++ which asked the user to input a number and then a string. To my surprise, when running the program it never stopped to ask for the string. It just skipped over it. After doing some reading on StackOverflow, I found out that I needed to add a line that said:
cin.ignore(256, '\n');
before the line that gets the string input. Adding that fixed the problem and made the program work. My question is why does C++ need this cin.ignore() line and how can I predict when I will need to use cin.ignore()?
Here is the program I wrote:
#include <iostream>
#include <string>
using namespace std;
int main()
{
double num;
string mystr;
cout << "Please enter a number: " << "\n";
cin >> num;
cout << "Your number is: " << num << "\n";
cin.ignore(256, '\n'); // Why do I need this line?
cout << "Please enter your name: \n";
getline (cin, mystr);
cout << "So your name is " << mystr << "?\n";
cout << "Have a nice day. \n";
}
ignore does exactly what the name implies.
It doesn't "throw away" something you don't need. Instead, it ignores the number of characters you specify when you call it, up to the char you specify as a delimiter.
It works with both input and output buffers.
Essentially, for std::cin statements you use ignore before you do a getline call, because when a user inputs something with std::cin, they hit enter and a '\n' char gets into the cin buffer. Then if you use getline, it gets the newline char instead of the string you want. So you do a std::cin.ignore(1000,'\n') and that should clear the buffer up to the string that you want. (The 1000 is put there to skip over a specific number of chars before the specified delimiter, in this case, the '\n' newline character.)
You're thinking about this the wrong way. You're thinking in logical steps each time cin or getline is used. Ex. First ask for a number, then ask for a name. That is the wrong way to think about cin. So you run into a race condition because you assume the stream is clear each time you ask for a input.
If you write your program purely for input you'll find the problem:
int main()
{
double num;
string mystr;
cin >> num;
getline(cin, mystr);
cout << "num=" << num << ",mystr=\'" << mystr << "\'" << endl;
}
In the above, you are thinking, "first get a number." So you type in 123 press enter, and your output will be num=123,mystr=''. Why is that? It's because in the stream you have 123\n and the 123 is parsed into the num variable while \n is still in the stream. Reading the doc for getline function by default it will look in the istream until a \n is encountered. In this example, since \n is in the stream, it looks like it "skipped" it but it worked properly.
For the above to work, you'll have to enter 123Hello World which will properly output num=123,mystr='Hello World'. That, or you put a cin.ignore between the cin and getline so that it'll break into logical steps that you expect.
This is why you need the ignore command. Because you are thinking of it in logical steps rather than in a stream form so you run into a race condition.
Take another code example that is commonly found in schools:
int main()
{
int age;
string firstName;
string lastName;
cout << "First name: ";
cin >> firstName;
cout << "Last name: ";
cin >> lastName;
cout << "Age: ";
cin >> age;
cout << "Hello " << firstName << " " << lastName << "! You are " << age << " years old!" << endl;
}
The above seems to be in logical steps. First ask for first name, last name, then age. So if you did John enter, then Doe enter, then 19 enter, the application works each logic step. If you think of it in "streams" you can simply enter John Doe 19 on the "First name:" question and it would work as well and appear to skip the remaining questions. For the above to work in logical steps, you would need to ignore the remaining stream for each logical break in questions.
Just remember to think of your program input as it is reading from a "stream" and not in logical steps. Each time you call cin it is being read from a stream. This creates a rather buggy application if the user enters the wrong input. For example, if you entered a character where a cin >> double is expected, the application will produce a seemingly bizarre output.
Short answer
Why? Because there is still whitespace (carriage returns, tabs, spaces, newline) left in the input stream.
When? When you are using some function which does not on their own ignores the leading whitespaces. Cin by default ignores and removes the leading whitespace but getline does not ignore the leading whitespace on its own.
Now a detailed answer.
Everything you input in the console is read from the standard stream stdin. When you enter something, let's say 256 in your case and press enter, the contents of the stream become 256\n. Now cin picks up 256 and removes it from the stream and \n still remaining in the stream.
Now next when you enter your name, let's say Raddicus, the new contents of the stream is \nRaddicus.
Now here comes the catch.
When you try to read a line using getline, if not provided any delimiter as the third argument, getline by default reads till the newline character and removes the newline character from the stream.
So on calling new line, getline reads and discards \n from the stream and resulting in an empty string read in mystr which appears like getline is skipped (but it's not) because there was already an newline in the stream, getline will not prompt for input as it has already read what it was supposed to read.
Now, how does cin.ignore help here?
According to the ignore documentation extract from cplusplus.com-
istream& ignore (streamsize n = 1, int delim = EOF);
Extracts characters from the input sequence and discards them, until
either n characters have been extracted, or one compares equal to
delim.
The function also stops extracting characters if the end-of-file is
reached. If this is reached prematurely (before either extracting n
characters or finding delim), the function sets the eofbit flag.
So, cin.ignore(256, '\n');, ignores first 256 characters or all the character untill it encounters delimeter (here \n in your case), whichever comes first (here \n is the first character, so it ignores until \n is encountered).
Just for your reference, If you don't exactly know how many characters to skip and your sole purpose is to clear the stream to prepare for reading a string using getline or cin you should use cin.ignore(numeric_limits<streamsize>::max(),'\n').
Quick explanation: It ignores the characters equal to maximum size of stream or until a '\n' is encountered, whichever case happens first.
When you want to throw away a specific number of characters from the input stream manually.
A very common use case is using this to safely ignore newline characters since cin will sometimes leave newline characters that you will have to go over to get to the next line of input.
Long story short it gives you flexibility when handling stream input.
Ignore function is used to skip(discard/throw away) characters in the input stream. Ignore file is associated with the file istream.
Consider the function below
ex: cin.ignore(120,'/n');
the particular function skips the next 120 input character or to skip the characters until a newline character is read.
As pointed right by many other users. It's because there may be whitespace or a newline character.
Consider the following code, it removes all the duplicate characters from a given string.
#include <bits/stdc++.h>
using namespace std;
int main() {
int t;
cin>>t;
cin.ignore(); //Notice that this cin.ignore() is really crucial for any extra whitespace or newline character
while(t--){
vector<int> v(256,0);
string s;
getline(cin,s);
string s2;
for(int i=0;i<s.size();i++){
if (v[s[i]]) continue;
else{
s2.push_back(s[i]);
v[s[i]]++;
}
}
cout<<s2<<endl;
}
return 0;
}
So, You get the point that it will ignore those unwanted inputs and will get the job done.
It is better to use scanf(" %[^\n]",str) in c++ than cin.ignore() after cin>> statement.To do that first you have to include < cstdio > header.
I have a problem using getline method to get a message that user types, I'm using something like:
string messageVar;
cout << "Type your message: ";
getline(cin, messageVar);
However, it's not stopping to get the output value, what's wrong with this?
If you're using getline() after cin >> something, you need to flush the newline character out of the buffer in between. You can do it by using cin.ignore().
It would be something like this:
string messageVar;
cout << "Type your message: ";
cin.ignore();
getline(cin, messageVar);
This happens because the >> operator leaves a newline \n character in the input buffer. This may become a problem when you do unformatted input, like getline(), which reads input until a newline character is found. This happening, it will stop reading immediately, because of that \n that was left hanging there in your previous operation.
If you only have a single newline in the input, just doing
std::cin.ignore();
will work fine. It reads and discards the next character from the input.
But if you have anything else still in the input, besides the newline (for example, you read one word but the user entered two words), then you have to do
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
See e.g. this reference of the ignore function.
To be even more safe, do the second alternative above in a loop until gcount returns zero.
I had similar problems. The one downside is that with cin.ignore(), you have to press enter 1 more time, which messes with the program.
int main(){
.... example with file
//input is a file
if(input.is_open()){
cin.ignore(1,'\n'); //it ignores everything after new line
cin.getline(buffer,255); // save it in buffer
input<<buffer; //save it in input(it's a file)
input.close();
}
}
I know I'm late but I hope this is useful.
Logic is for taking one line at a time if the user wants to enter many lines
int main()
{
int t; // no of lines user wants to enter
cin>>t;
string str;
cin.ignore(); // for clearing newline in cin
while(t--)
{
getline(cin,str); // accepting one line, getline is teminated when newline is found
cout<<str<<endl;
}
return 0;
}
input :
3
Government collage Berhampore
Serampore textile collage
Berhampore Serampore
output :
Government collage Berhampore
Serampore textile collage
Berhampore Serampore
i think you are not pausing the program before it ended so the output you are putting after getting the inpus is not seeing on the screen right?
do:
getchar();
before the end of the program
The code is correct. The problem must lie somewhere else. Try the minimalistic example from the std::getline documentation.
main ()
{
std::string name;
std::cout << "Please, enter your full name: ";
std::getline (std::cin,name);
std::cout << "Hello, " << name << "!\n";
return 0;
}
For some weird reason my input line cin.getline(oneLine, 80); is completely ignored when I put it in this else if block. I can't understand why because when I move it somewhere else in the program, it works.
else if (choice == "user-id")
{
cout << endl << "Enter a full name e.g. John Smith ";
char oneLine[80];
cin.getline(oneLine, 80);
cout << oneLine;
}
Here's the rest of my code. I'm new to C++ so I'm sure a lot of my conventions may be questionable at best.
int main( )
{
while (true)
{
int pause;
string choice = "proceed";
string nameGiven;
string userIdGiven;
string result;
using namespace std ;
while ((choice != "name") && (choice != "user-id"))
{
cout << "Would you like to search for a name or user-id? ";
cin >> choice;
if ((choice != "name") && (choice != "user-id"))
cout <<"Please enter a valid choice (name or user-id)" << endl;
}
if (choice == "name")
{
string dataType = "int";
while (true)
{
cout << endl << "Enter a valid user id (4 digit maximum) ";
cin >> userIdGiven;
if (valid(userIdGiven))
break;
else
cout << endl << "Not a valid number. " << endl;
continue;
}
result = findData(userIdGiven, dataType);
cout << "name: " << result;
}
else if (choice == "user-id")
{
cout << endl << "Enter a full name e.g. John Smith ";
char oneLine[80];
std::getline(oneLine, 80);
cout << oneLine;
}
string ans;
cout << endl << "Would you like to play again? (yes/no) " << endl;
cin >> ans;
if ( (ans == "yes") || (ans == "Yes") || (ans == "Y") || (ans == "y") )
continue;
else
break;
cin >> pause;
}
return 0;
}
Your std::cin object is in a bad state (std::cin.good() == false) from a previous input operation. For example, you might have tried to read a number, but there were only nun-numeric characters in the input buffer.
Always check for input success before continuing using a std::istream.
Note: Don't use the old input functions operating with char*, as they are more complicated and less safe to use than the new ones operating on std::string. In your case, use std::getline(std::istream&, std::string&, char = '\n').
twsaef's comment's substantively correct... you're streaming a string into choice, which consumes the characters up until but excluding the next whitespace character - you're probably typing a newline to terminate your input, so it's left in the buffer. Then you use getline which sees that newline and reads an empty string.
Easiest solution is to call getline() to read the initial string too, then check if choice is "name\n" or "user-id\n". Better - write a "trim" function to remove the whitespace from the line before comparison (boost string library has this already). Otherwise, you could use read and ignore characters from std::cin until you get a '\n'. Or even read a line then put in into a stringstream and read a string from there.... Lots of choices.
And, please check your stream state! Try to use:
if (std::cin >> x)
// x was parsed from stream... use it
else
// print an error so you know where things failed!
FWIW, I guessed what the problem would be (it's stupidly common) before seeing the update, and chuckled to myself at the other guesses (although they make very good points even if they missed the OP's problem).
The line of code is working correctly and as advertised. It doesn't happen to be working the way you want it to.
When you read from std::cin, that does not pause the program and wait for input. What causes the pause is the lack of sufficient input data for the read operation.
Input is fed to your program a line at a time. Remember, the console window is a program, too. It is responsible for translating the user's key-presses into text characters (bytes, really), handling things like the backspace key, and gathering it all up into lines.
So say you read an int with operator>>, and then read a line with getline. The program will not see an int until the user hits the Return key, because that triggers the console to feed a line of input to your program.
operator>> will skip leading whitespace, read the integer, and leave trailing whitespace alone. Newline characters are whitespace. There is a newline character in the input (at the end of the line, obviously).
getline() will not skip any leading whitespace, and read until the next newline. The very next character happens to be a newline, so getline() happily reads an empty line and the program proceeds with that.
So how do you fix that? Chances are, if you're reading all your input from cin, that you want the program to pause every time you come to a reading operation. The way to do that is to ensure that there is never any available data at that point, and the way to do that is to read everything that's available - i.e., the whole line - every time that you read something.
So, always read a full line from cin. As noted by wilx, please use the free function std::getline for this. Do not use the .getline member function of the stream. Use std::string to represent strings of text. That's what it's there for. It will make your life much, much easier. That also means that if you're expecting an integer and the user types "76 trombones", you get rid of the "trombones" data (and can decide whether you want to just throw it away, or yell at the user and make him re-enter a number without any funny commentary).
But then what? You just have a string, where you may have wanted an int. Fortunately, there is a simple solution for that. We can treat the string as a source of stream data, using the standard library class std::stringstream. We just construct a stringstream from the string, and then use it just like std::cin - i.e. we can read from it with operator>>, check the stream state to see if reading was successful, etc.
As noted by sbi, always check whether reading succeeded! If you try to read an int and the stream contains text like "hi mom", then (a) the int variable will not be altered (so if it was uninitialized it is still uninitialized, a very dangerous state to be in), and (b) the stream will go into a "failed" state and will not read any more until you clear it, and (c) even if you clear it, the data will still be there, which can trigger an infinite loop if you're not careful.
Fortunately, with the separate stringstream, we avoid all kinds of complications. If reading fails, then all those things happen to the stringstream object - not to std::cin. The getline operation will always succeed on std::cin unless perhaps the user explicitly indicates an end-of-file (control-D character on Linux, or control-Z on Windows). We can easily check if the stringstream is in the failed state, loop and just create another one - the old one will automatically get cleaned up.
We can even make a helper function like:
template <typename T>
// Attempt to read into to_read, and return whether successful.
bool read_primitive_from_input(std::istream& input, T& to_read) {
std::string line;
std::getline(std::cin, line);
std::istringstream iss(line);
return iss >> to_read;
}
std::stringstream is provided by the standard library header <sstream>. std::string comes from <string>, of course.