Input tips (>>, getline, gets) and newlines

Write here if you have problems with your C++ source code

Moderator: Board moderators

Post Reply
ChristopherH
New poster
Posts: 31
Joined: Sun Feb 23, 2003 9:18 pm
Location: Waterloo, Ontario, Canada

Input tips (>>, getline, gets) and newlines

Post by ChristopherH »

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
Juergen Werner
New poster
Posts: 27
Joined: Wed Apr 17, 2002 7:54 pm

Post by Juergen Werner »

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)
{
...
}

ChristopherH
New poster
Posts: 31
Joined: Sun Feb 23, 2003 9:18 pm
Location: Waterloo, Ontario, Canada

Post by ChristopherH »

Yes, that's a great technique too.

I'd forgotten about that: istream has a truth-conversion operator (not sure if it converts to bool or to void *) which returns the same result as good().

Quite useful.
Post Reply

Return to “C++”