Input tips (>>, getline, gets) and newlines
Posted: Fri Feb 28, 2003 12:43 am
Note: I have edited this post to remove an incorrect claim about getline(istream, string).
Recently a friend ran into difficulties with a WA on a simple problem. We tried many things (understatement) before finally discovering that the difficulty lay in his input routine:
[cpp]
// one version which didn't work
for (;;) {
string s;
getline(cin, s);
if (cin.eof()) break;
...
}
// another version which didn't work
for (;;) {
string s;
cin >> s;
if (cin.eof()) break;
...
}
[/cpp]
In this particular problem, no whitespace was permitted except newlines.
It turns out that both these input methods, while legal on UNIX-style text files which always end lines with newlines (newline as a line terminator), fail on DOS-style text files which may omit the final newline at EOF (newline as a line separator).
The problem is with the use of istream::eof to detect the end of input.
If there is a newline terminating the final line, then eof() will not return true until the last getline or >> fails. Without a newline, eof() will return true immediately after extraction of the last line.
There are two ways to get around this:
* use the return code of getline() to determine success
* use !cin.good() as a safe substitute for cin.eof()
.good() refers to the success of the last I/O operation, so it's correct with or without a trailing newline when used with >>.
Lessons:
* avoid istream::eof(), use istream::good() instead
* it would be kind of this site to ensure that judging data follows the standard conventions for text files: one newline character terminating every line
Good luck to all, and may your WAs always be legitimate.
Regards,
Christopher
Recently a friend ran into difficulties with a WA on a simple problem. We tried many things (understatement) before finally discovering that the difficulty lay in his input routine:
[cpp]
// one version which didn't work
for (;;) {
string s;
getline(cin, s);
if (cin.eof()) break;
...
}
// another version which didn't work
for (;;) {
string s;
cin >> s;
if (cin.eof()) break;
...
}
[/cpp]
In this particular problem, no whitespace was permitted except newlines.
It turns out that both these input methods, while legal on UNIX-style text files which always end lines with newlines (newline as a line terminator), fail on DOS-style text files which may omit the final newline at EOF (newline as a line separator).
The problem is with the use of istream::eof to detect the end of input.
If there is a newline terminating the final line, then eof() will not return true until the last getline or >> fails. Without a newline, eof() will return true immediately after extraction of the last line.
There are two ways to get around this:
* use the return code of getline() to determine success
* use !cin.good() as a safe substitute for cin.eof()
.good() refers to the success of the last I/O operation, so it's correct with or without a trailing newline when used with >>.
Lessons:
* avoid istream::eof(), use istream::good() instead
* it would be kind of this site to ensure that judging data follows the standard conventions for text files: one newline character terminating every line
Good luck to all, and may your WAs always be legitimate.
Regards,
Christopher