How to promt the user correctly? [duplicate] - c++

Here is the code:
string str;
cin>>str;
cout<<"first input:"<<str<<endl;
getline(cin, str);
cout<<"line input:"<<str<<endl;
The result is that getline never pauses for user input, therefore the second output is always empty.
After spending some time on it, I realized after the first call "cin>>str", it seems '\n' is still stored in cin (using cin.peek() to check), which ends getline immediately. The solution will be adding one more line between the first usage and the second one:
cin.ignore(numeric_limits::max(), '\n');
However, I still don't understand, why is '\n' left there after the first call? What does istream& operator>> really do?

The \n is left in the input stream as per the way operator>> is defined for std::string. The std::string is filled with characters from the input stream until a whitespace character is found (in this case \n), at which point the filling stops and the whitespace is now the next character in the input stream.
You can also remove the \n by calling cin.get() immediately after cin>>str. There are many, many different ways of skinning this particular I/O cat, however. (Perhaps a good question in and of itself?)

By default, the stream insertion operator reads until it sees whitespace. Your first call isn't returning until it sees a space, tab, newline, etc. Then the next character needs to be consumed so that you can get to the next one.

I generally recommend only doing line-oriented input from std::cin. So, your code could look something like this:
string str;
int val;
// Read an entire line and parse an integer from it
{
string line;
getline(cin, line);
istringstream iss(line);
iss >> val;
}
cout<<"first input:"<<val<<endl;
getline(cin, str);
cout<<"line input:"<<str<<endl;
Be sure to add error checking too.
The getline-only approach avoids having to think about line buffering of the input, of clearing the input, etc. If you directly read something with >>, the input does not terminate if the user hits enter instead of inputting what is required, but instead continues until a token is input (this behavior is usually not wanted).

As others have said, th problem is that the newline is left from the first extraction. One solution I do is to discard all the left characters in the stream:
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );

Good writeup that explains some of the reasons why you are running into this issue, primarily due to the behavior of the input types and that you are mixing them

Also was searching for most suitable solution. Implementation of this operator could produce problems. And not always is acceptable to read entire line, or not mix different types in one input line.
To solve problem, when you want to read some data from cin, and don't know if whitespaces was correctly extracted after last input operation, you can do like this:
std::string str;
std::cin >> std::ws >> str;
But you can't use this to clear trailing newline symbol after last input operation from cin to do not affect new input, because std::ws will consume all whitespaces and will not return control until first non-ws character or EOF will be found, so pressing enter will not finish input process.
In this case should be used
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
which is more flexible.
P.S. If got errors with max() function such as "identifier expected", it could be caused by max macros defined in some header (for example, by Microsoft); this could be fixed by using
#undef max

Related

Empty input variable that failed C++

I've found many posts saying I should be using the following code to empty the input variable in order to reset it:
cin.ignore(numeric_limits<streamsize>::max(), '\n');
But what am I missing here since it's not compiling, it says expected an identifier when mouse hover over max();
code:
int Menu::getInput()
{
int choice;
cin >> choice;
if (cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
return choice = 3;
}
return choice;
}
The suggestions that you've read to use ignore() are just band-aids designed to workaround broken logic that attempts to read newline delimited text using operator>>.
The general situation goes something like this: "well, I should be reading lines of text that contain two integers, followed by a text string, ok, so I'll use operator>> to read two integers, then a std::string, from std::cin". And that's fine, as long as we all live in a perfect world. Unfortunately, we don't live in a perfect world, and when bad input is encountered, in the middle of this odyssey, we end up with:
A std::istream in an error/fail state.
An undeterminate amount of consumed input, with a partially read line.
Recovering from this mess is what the using ignore() is supposed to achieve, by reading and discarding the remainder of the partially-consumed line, until the next newline characters.
But wouldn't you agree that it's much better not end up in this ugly mess to start with, in the first place?
And that's why if you need to read something that's formatted as lines of text, you should simply use std::getline(), to read one line of text at time. What a novel idea!
And then, once you've read the next line of text into a simple, std::string buffer, if you feel like it you can go ahead and construct a std::istringstream object from it, and use operator>> to your heart's content.
And if parsing the line of text, using std::istringstream, fails for some reason, you only need to issue an appropriate complaint to the user, then simply loop back, and use std::getline() to read the next line of text from your input time, without having to screw around with resetting the stream's status, or discarding partially-processed line. That seems to me like a much simpler, easier approach, doesn't it?
It appears to me that most C++ courses, instructors, and textbooks, are doing a disservice to their students by unceremoniously sprinkling liberal usage of operator>>, without properly explaining that this is a completely wrong approach to reading input that's formatted as newline-delimited lines of text. This just leads to nothing but utter confusion, and buggy code.
Take this as an answer to your question: scrap completely what you're doing, and simply rewrite it, simply as:
int Menu::getInput()
{
int choice;
std::string buffer;
if (!std::getline(std::cin, buffer).eof())
{
std::istringstream i(buffer);
i >> choice;
if (!i.fail())
return choice;
}
return 3;
}
Money back guarantee: this approach guarantees to never mess up your std::cin's state, or leave it with partially-consumed input.

why does cin works wheras cin.getline doesn't?

My code is
char buffer[10]={0};
cin>>buffer; //here i enter the contents as "12345678912345"
//Now i tried to enter 14 characters into a buffer of 10
cin>>buffer; //This works as it waits for input on the console
cout<<buffer;
wheras
char buffer[10]={0};
cin>>buffer;//same input as above "12345678912345"
cin.getline(buffer,10);//This doesn't wait for input on console and returns
cout<<buffer;
why does this happen?
THANKS:
thanks everyone for your answers they were helpful
Neither of your code-snippets "work" in the sense that both overflow the buffer in the first input line. This is not a good thing at all.
The second case doesn't wait for input because of technical differences between operator>> and getline - they react differently to the newline character that you have entered. When reading the first cin >> buffer, the newline at the end of the input is left in the input stream (cin). In your first case, the second cin >> buffer will skip over the newline that is in the input buffer, and then wait for more input.
In the second case, because of the workings of getline, it accepts the remaining newline as input, and buffer is not filled in with anything.
This is a common problem when mixing getline and operator>> for input. The best solution to solve that particular problem is to either use only operator >> or only getline - there are various other solutions, but they are generally quite tricky to get just right.
First off you have a buffer overrun: Reading to a char* stops when the stream goes bad, a space is found, or the width() is exhausted if it were bigger than 0. You want to use
std::cin >> std::setw(10) >> buffer;
Assuming this undefined behavior is abouded, the difference between using formatted and unformatted input for the second read is that formatted input starts with skipping leading whitespace whike unformatted input does not. Your first input stopped right before the newline character resulting from the enter key. That newline is good enough for getline() but it is skipped when using >>.
When switching between formatted and unformatted I/O you normally want to skip leading whitespace using, e.g., the std::ws manipulator:
(std::cin >> std::ws). getline(buffer, 10);
You should also consider using std::string together with std::getline().
When you input the value for buffer in console, the return is still stored in the input stream.
Hence the termination character '\n' is already read by getline() from the previous read operation. This is why this function does not wait further for user input.
Try reading the getline() before the cin >> operation.
Also, as noted by Mike, you should be careful not to cause buffer overflow.
The >> operator does not consume any whitespace including the newline. The getline function returns when it sees a newline. Your problem is the newline that >> statement leaves at the buffer. You can solve this by consuming all characters, including the newline until you see a newline in the buffer. See the ignore function:
char buffer[10]={0};
cin>>buffer;
cin.ignore('\n', 256);
cin.getline(buffer,9);
cout<<buffer;
return 0;

Possible to discard return character when using std::cin >>?

When using the >> operator in c++ to capture user input, is it possible to prevent the console from printing the newline that is generated when the user presses the return key?
You cannot prevent newline character, because when you use cin, you are communicating with system core, which is not under control by users. console will return, when you enter \n or EOF or other exception situation.
So the better way is to use getchar() to capture the '\n', and do not leave it in buffer.
It is possible to prevent this newline behavior by inputting two EOFs instead of Carriage Return from the keyboard. After entering your string at the console prompt, hit
CTRL-D, CTRL-D
Note, this is a platform specific answer. This works on my Mac, but on Windows OS the EOF sequence may be CTRL-Z, RETURN. I would appreciate an answer edit <-- HERE.
Alternately, you can ditch the >> operator and use something like std::getline and specify an exact string termination delimiter. For example:
std::string myString;
std::getline(std::cin, myString, ';');
std::cout << myString;
This will read from standard input to myString, and put the string terminating NULL character where it finds the first semicolon ';'. Then you'll only have to hit CTRL-D (input EOF) once.
You can enter the values or input by pressing space every time. But at the end you must press enter key.
Let's say: you want to enter "5,4,3,2,1"
You can do: 5 [enter] 4 [enter] 3[enter] 2[enter] 1[enter]
Also: 5[space]4[space]3[space]2[space]1[enter]
But if you want to print the output near input, you can simply print the input first and than you can print the what you want.
Example:
Input: 3 Output: input+1
So you will do:
cout<<input;
cout<<" "<<input+1<<endl;
Good luck :)

Why doesn't std::getline block?

I have this code in an Objective-C class (in an Objective-C++ file):
+(NSString *)readString
{
string res;
std::getline(cin, res);
return [NSString stringWithCString:res.c_str() encoding:NSASCIIStringEncoding];
}
When I run it, I get a zero-length string, Every time. Never given the chance to type at the command line. Nothing. When I copy this code verbatim into main(), it works. I have ARC on under Build Settings. I have no clue what it going on. OSX 10.7.4, Xcode 4.3.2.
It is a console application.
It means there is input waiting to be read on the input. You can empty the input:
cin.ignore(std::numeric_limits<std::streamsize>::max();
std::getline(cin, res);
If this is happening it means you did not read all the data off the input stream in a previous read. The above code will trash any user input before trying to read more.
This probably means that you are mixing operator>> with std::getline() for reading user input. You should probably pick one technique and use that (std::getline()) throughout your application ( you can mix them you just have to be more careful and remove the '\n' after using operator>> to make sure any subsequent std::getline() is not confused..
If you want to read a number read the line then parse the number out of the line:
std::getline(cin, line);
std::stringstream linestream(line);
linestream >> value;
You can simply do:
cin.ignore();
or use
cin.clear();
cin.sync();
before using getline()

How do you get input until a newline in C++?

I'm reading input using cin. If I leave the input blank (and just hit enter), the cursor moves to a new line and asks for input again. Is there any way to make cin or scanf just return an empty string in this case?
Instead of operator>>, use getline.
std::string data;
std::getline(std::cin, data);
Side note: There's no recursion involved here. Recursion is when a function calls itself, that's not happening here.