The main problem is that getline
behaves differently in two cases:
- If at least
SIZEC
characters are read and there is no newline character among them (e.g. there should be at least SIZEC+1
bytes to store the data read), it stops reading and sets so-called failbit
status bit on the stream, which means "I have failed to read something, so input stream is probably incorrect". Quoting cplusplus.com:
The failbit flag is set if the function extracts no characters, or if
the delimiting character is not found once (n-1) characters have
already been written to s.
- If newline character is encountered,
failbit
is not set and the newline character is succesfully read and ignored by getline
.
What happens next is more interesting: extraction functions (all of them, I assume) fail immediately if the input stream is bad()
(that is, either failbit
, badbit
, or eofbit
are set on the stream). In particular, if previous extraction operation failed, all subsequent will fail as well. So, basically, if first line of the input cannot be fitted in your phrase
array, then cin
becomes "bad" and all further read operations do nothing.
You can override that behavior by manually resetting the failbit
after calling getline
like this:
cin.clear();
Following read operations will succeed until another one fails.
In your particular case, I assume that you want to read the first line regardless of the length, and then a second line. I that case, I think you
should to first check whether getline failed (by checking cin.failbit()
or cin.good()
) and then either do nothing (if it did not and there is no need in reading extra newline) or resetting the failbit
and ignoring characters till the first newline. Something like this:
#include <iostream>
#include <limits>
#include <string>
using namespace std;
int main() {
char buf[5];
cin.getline(buf, sizeof buf);
if (!cin) { // operator ! is overloaded for `istream`, it's equal to `good()`
// If stream is bad: first line of the input was truncated,
// and following newline character was not read.
// Clear failbit so subsequent read operations do something.
cin.clear();
// Read remaining of the first line.
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
// At this point, first line of the input is consumed
// regardless of its length
int x;
cin >> x;
cout << "String: |" << buf << "|\n";
cout << "x: " << x << "\n";
}
You can read more on StackOverflow here and there.
However, if there is no reason to use C-style string together with istream
s, I'd suggest you using string
and std::getline
instead (like in Shreevardhan's answer); it will produce cleaner code and there will be no extra cases.