In article <news:Pi******************************@drj.pf>
Darrell Grainger <da*****@NOMORESPAMcs.utoronto.ca.com> writes:
I usually use fgets to read a line then parse it.
(I think this is usually the best approach.)
Another option is to get the result from fscanf and see how many
directives were successful ...
This has some pitfalls, including one you ran into here:
rather than having two calls, e.g.
while(fscanf(infile, "%d %d %d\n", &num[0], &num[1], &num[2]) == 3) {
printf("%d %d %d\n", nums[0], nums[1], nums[2]);
}
This will work even if the last line does not contain a newline character.
True (assuming the implementation supports such lines in the first
place), but this:
It will not print out a line that only has 1 or 2 numbers on it. Something
like:
1 0 1
1 2 1
1 3
1 2 0
will quit after the second line is read.
is not the case.
The problem lies in the scanf engine's interpretation of "white
space", which disagrees with what most programmers believe is the
"most reasonable" interpretation.
The directive sequence "%d %d %d\n" does *not* mean "three
integers separated by blanks and terminated by a newline." The
final "\n", for instance, means "as much blank space as possible,
including any arbitrary number of newlines, and including no newlines."
The blanks separating the "%d"s *also* mean "as much blank space
as possible, including any arbitrary number of newlines, and including
no newlines."
That means that the third input line -- "1 3\n" -- will be treated
as the number 1 (first "%d"), one blank (first " "), the number 3
(second "%d"), one newline (second " ")... and then the fourth input
line's "1" will be read and converted to satisfy the third "%d". The
newline in the scanf directive will then match the blank after the
1, leaving "2 0\n" in the input stream.
One might attempt to fix this by rewriting the call as:
while (fscanf(infile, "%d%d%d\n", ...) ...)
so that there is no " " directive to match the newline after the
two integers on the third input line ("1 3\n"). But this is no
help, because %d directives include an implied whitespace directive
first. "%d%d%d\n" means exactly the same thing to scanf as
"%d %d %d\n", or even " %d%d \v %d \t\f\r\n"! *All* whitespace
in format directives is equivalent, and any whitespace is equivalent
to an arbitrarily long string of whitespace. Most scanf directives
-- the exceptions are %c and %[ -- have an "implied blank" in front
of them. A final "\n" in a scanf directive means the same thing as
a trailing blank, or "\t", or "\f".
What this all boils down to is that *only* the %c and %[ directives
give you control over "lines". *All* other scanf conversions will
behave poorly in any kind of file-parsing or interactive application.
In other words, these are the only *useful* directives -- unless
you first read in a line, then use sscanf() to pick it apart. (By
using sscanf(), you avoid the problem, because you have a tightly
controlled string in memory, rather than an uncontrolled input
stream coming from a file or user-at-keyboard or whatnot.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it
http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.