Why does cin command leaves a '\n' in the buffer? - c++

This is related to: cin and getline skipping input But they don't answer the why it happens just the how to fix it.
Why does cin leaves a '\n' in the buffer but just cin.getline takes it?
for example:
cin >> foo;
cin >> bar;//No problem
cin >> baz;//No problem.
But with cin.getline
cin >> foo;
cin.getline(bar,100);//will take the '\n'
So why it doesn't happen with cin but it does with cin.getline?

Because, when you say getline you say you want to get a line... A line is string that ends with \n, the ending is integral part of it.
When you say cin >> something, you want to get precisely something, nothing more. End-line marker is not part of it, so it's not consumed. Unless you would have a special type for line, but there is no such thing in standard library.
While without citations from standard this might be taken as opinion, but this is logic behind it. They have different semantics. There is also another difference getline works as unformatted input, and operator>> works as formatted input. I strongly suggest reading of those links to get the differences. This also says that they are semantically different.
Another answer, better or not is debatable, would be to quote standard, that I am sure says, how getline behaves, and how operator>> behaves for different types, and say, it works like this, because standard says so. This would be good, because the standard absolutely defines how things work and it can do so arbitrarily... And it rarely does explain motivation and logic behind the design.

You are not comparing cin to cin.getline, but rather cin.operator>> and cin.getline, and that is exactly what these functions are defined to do. The answer to the question "why" is "by definition". If you want rationale, I can't give it to you.
cin.getline reads and consumes until a newline \n is entered. cin.operator>> does not consume this newline. The latter performs formatted input, skipping leading whitespace, until the end of the object it was reading (in your case whatever foo is) "stops" (in case foo is an int, when the character isn't a number). A newline is what remains when the number is consumed from the input line. cin.getline reads a line, and consumes the newline by definition.
Make sure to always check for error on each stream operation:
if(cin >> foo)
or
if(std::getline(cin, some_string))
Note I used std::getline instead of the stream's member because this way there's no need for any magic numbers (the 100 in your code).

Related

Storing data line by line into arrays

I need to store data into two arrays that are stored in the order Name then Number
Ex:
Kara
000131012
Tucker
002102000
I understand how to use the single-line method:
while (infile >> a >> b)
{
// process pair (a,b)
}
But this doesn't work for the way this data is stored.
I am not sure how sensible it is to add an answer so late (and to this easy question), but I want to be clear since there were some missunderstandings in the comments.
How does >> work?
The operator>> first discards als leading space characters (spaces, tabs, newlines, maybe more, this depends on the locale). Then it will try to read as many non-whitespace characters as possible (so int i; cin >> i; with input 123123jj sets i to 123123). Then it will potentially set the failbit, eofbit, or badbit, which influence the boolean value of the stream.
What does that mean for your code?
If your names consistenly do not include a space character, your code will run perfectly completely independent of the number of words per line. If you have that guarantee of spaceless names, I would recommend this way since it is easy and you don't get a problem if your input is a bit faulty and has for example a double newline at some point.
If you have perhaps spaces in the names, your code above will fail. Then you have to use std::getline. Its usage is well documented on the linked page.

How to ignore line break after reading two ints with cin?

I am new to C++, I have practically started it today. Any way, I am facing a problem where the first line contains two integers, and the next lines contain operations to be done. It's a fairly weird problem, actually, so I won't go into the details. Well, I am having a problem with reading the first line, and then the follow up operations.
My code looks like this so far:
int m, j;
string comando;
string OPR
cin << m << l;
while (getline(cin, comando)) {
OPR = comando.substr(0, 3);
}
The problem is: Apparently, whenever I write both m and l in the same line, the \n stays in the buffer, and it get's read by the newline, causing a problem when I try to take the substring. I tried adding a char variable that would be read after m and l, which would, supposedly, get the \n. However, it is getting the first letter of the newline instead, which, then, messes up my code. I tried to see if I had any syntax errors or anything, but that isn't it. I also looked for ways to ignore the \n char, but everything I found was related to strings, or reading from files.
I know I could read the line, and then cast the two ints from string to int, but that seems like a bad way to do it (at least it would be a bad way to do it in C).
Anyways, if any one can help me, that would be awesome, thanks!
P.S.: I don't do a check before the substr operation because, by the definition of the problem, the line will have a 3-char operation, a space and then an integer.
A good place to look for tips for common problems like this is your favorite reference:
When used immediately after whitespace-delimited input, e.g. after int n; std::cin >> n;, getline consumes the endline character left on the input stream by operator>>, and returns immediately. A common solution is to ignore all leftover characters on the line of input with cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); before switching to line-oriented input.
From here.

Why would I even use istream::ignore when checking for valid input?

The C++ FAQ over at parashift uses something similar to the following:
while (cout << "Enter an integer: " && !(cin >> foo))
{
cin.clear();
//feel free to replace this with just (80, '\n') for my point
cin.ignore (numeric_limits<streamsize>::max(), '\n');
}
The cin.ignore (...), however, seems unnecessary. Why can't I just use cin.sync()? It's shorter and does not require a length. It's also more versatile as it will work the same way whether or not there are any characters in the input buffer in the first place. I've tested this once in the same loop as I used with ignore and it worked the same way. Yet it seems every example involving this type of input validation uses ignore instead of sync.
What (if any) was the reasoning behind using ignore when there's a much simpler alternative?
If it matters:
Windows
GCC
MinGW
On an ifstream, the effect of sync() is implementation defined (per C++11, §27.9.1.5/19) -- there's no guarantee that it'll do what you want (and no real guarantee of what it'll do at all). In a typical case, it will be about equivalent to the ignore if and only if the stream is line buffered -- but if the stream is unbuffered, it probably won't do anything, and if the stream is fully buffered, it'll probably do bad things.
Both do different things. sync discards characters already read ahead, no matter how many there are, or what they are. On the other hand, ignore discards characters until a certain character is encountered, no matter whether those characters have already been read, or whether there are more characters already read ahead. For example, imagine that cin has a 40 byte buffer, but your line had 80 bytes. Then most likely the first 40 bytes had been read to cin's buffer. After you've interpreted the beginning of those, by calling sync you discard the rest of those 40 characters you already have read, but not the other 40 characters in the line. On the other hand, your input might come from a pipe where no line buffering is typically done. In that case, you may discard not only the current line, but also parts of the next line which have been read ahead. OTOH with ignore you always know for sure that you'll always read up to the next \n (assuming the maximal number of characters to ignore is high enough to encounter it).

Why doesn't whitespace act as a delimiter when printing strings with ostream operator<<?

I know that when writing code like std::cin >> some_var; , where some_var is a string variable, only the first word that was inputted will be stored in some_var. But I do not understand why std::cout << "something here"; does not only output "something". Am I missing something?
When reading input using cin >> some_var, the delimiter is space by default (you can change this though), while when printing, cout prints till its find \0 which is end of the string.
If you want to read till it finds \0 in the input stream, then you've to write this:
std::getline(std::cin, some_var, '\0');
You can give any other character as delimiter as third argument of std::getline function.
Note that there is a member function with same name getline which is slightly different than the one I used above which is a free standalone function.
Compare:
std::getline - free standalone function. An overloaded function is also available.
istream::getline - member function of std::istream
I used the first one.
It was deemed useful that cin, when reading into a string terminates at whitespace. But it wasn't deemed useful that only the first word is printed when you print a string.
After all you said print "something here" to cout· In the other case, you just said read something from cin. The choice between a word, between a line and between the whole content of stdin (until an EOF is received) is arbitrary and the design happens to be to read a word. That makes it easy to quickly read a record line like "john 10 2.15" (first read into string, then into an int, and then into a float). Use std::getline to read a whole line into a string.
Because when you take input from std::cin, it needs to know when to stop taking input. If it didn't stop at the first word, when would it stop? However, when you output a variable, the answer is easy- you output that one variable.
Yes... cin stops at a space because, by default, it thinks you want a word. cout doesn't follow the same restriction, because, well, why would it? Think about it for a second — would it make any sense whatsoever if printing out "Hello, world!" actually just printed out "Hello,"? Of course it doesn't make any sense. The developer knows what they want to output (at least, we hope :D).
I think they took a convention and stick to it. In the case of <<, it is clear that you specify what to be written. In the case of a >>, they have to decide where to stop. Newline? Maybe this is the most natural alternative, but they just decided to stop reading at a space.
The delimiters are different for cin and for cout. For cin, input is split at whitespaces, for cout, at end of lines. You can change those default delimiters though.

Problem of using cin twice

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