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
Input tips (>>, getline, gets) and newlines
Moderator: Board moderators
-
- New poster
- Posts: 31
- Joined: Sun Feb 23, 2003 9:18 pm
- Location: Waterloo, Ontario, Canada
-
- New poster
- Posts: 27
- Joined: Wed Apr 17, 2002 7:54 pm
I"m also no friend of testing for EOF or whatsoever manually (actually never did it - and never needed to). Not only the return value of getline can be used, but e.g. reading int until EOF can be done the following way:
Code: Select all
// reading line-wise
string line;
while (getline(cin, line))
{
...
}
//reading int-wise
int n;
while (cin >> n)
{
...
}
-
- New poster
- Posts: 31
- Joined: Sun Feb 23, 2003 9:18 pm
- Location: Waterloo, Ontario, Canada