char c; while((c = getchar()) != EOF)...
For one thing, the variable to hold getchar's return value must
be an int. getchar
can return all possible character values, as
well as EOF
. By passing getchar
's return value through a char
,
either a normal character might be misinterpreted as EOF
, or the
EOF
might be altered (particularly if type char
is unsigned) and
so never seen.
References: CT&P Sec. 5.1 p. 70.
'%'
character in a printf
format string? I tried \%
, but it didn't work.
Simply double the percent sign: %%
.
References: K&R I Sec. 7.3 p. 147; K&R II Sec. 7.2 p. 154; ANSI Sec. 4.9.6.1 .
11.3: Why doesn't the code scanf("%d", i);
work?
scanf
needs pointers to the variables it is to fill in; you must
call scanf("%d", &i);
double d; scanf("%f", &d);
scanf
uses %lf
for values of type double
, and %f
for float
.
(Note the discrepancy with printf
, which uses %f
for both double
and float
, due to C's default argument promotion rules.)
while(!feof(infp)) { fgets(buf, MAXLINE, infp); fputs(buf, outfp); }
C's I/O is not like Pascal's. EOF
is only indicated after an
input routine has tried to read, and has reached end-of-file.
Usually, you should just check the return value of the input
routine (fgets
in this case); often, you don't need to use
feof()
at all.
gets()
?
It cannot be told the size of the buffer it's to read into, so
it cannot be prevented from overflowing that buffer. See
question 3.1 for a code fragment illustrating the replacement of
gets()
with fgets()
.
ENOTTY
after a call to printf
?
Many implementations of the stdio
package adjust their behavior
slightly if stdout
is a terminal. To make the determination,
these implementations perform an operation which fails (with
ENOTTY
) if stdout
is not a terminal. Although the output
operation goes on to complete successfully, errno
still contains
ENOTTY
.
References: CT&P Sec. 5.4 p. 73.
It is best to use an explicit fflush(stdout)
whenever output
should definitely be visible. Several mechanisms attempt to
perform the fflush
for you, at the "right time," but they tend
to apply only when stdout
is a terminal. (See question 11.7.)
scanf
, it seems to hang until
I type one extra line of input.
scanf
was designed for free-format input, which is seldom what
you want when reading from the keyboard. In particular, "\n"
in
a format string does not mean to expect a newline, but rather
to read and discard characters as long as each is a whitespace
character.
A related problem is that unexpected non-numeric input can cause
scanf
to "jam." Because of these problems, it is usually better
to use fgets
to read a whole line, and then use sscanf
or other
string functions to pick apart the line buffer. If you do use
sscanf
, don't forget to check the return value to make sure that
the expected number of items were found.
fopen
mode "r+"
,
then reading a certain string, and finally writing back a
modified string, but it's not working.
Be sure to call fseek
before you write, both to seek back to the
beginning of the string you're trying to overwrite, and because
an fseek
or fflush
is always required between reading and
writing in the read/write "+"
modes. Also, remember that you
can only overwrite characters with the same number of
replacement characters; see also question 17.4.
References: ANSI Sec. 4.9.5.3 p. 131.
See question 16.1.
fflush(stdin)
work?
fflush
is defined only for output streams. Since its definition
of "flush" is to complete the writing of buffered characters
(not to discard them), discarding unread input would not be an
analogous meaning for fflush
on input streams. There is no
standard way to discard unread characters from a stdio
input
buffer, nor would such a way be sufficient; unread characters
can also accumulate in other, OS-level input buffers.
stdin
or stdout
to a file from within a
program?
Use freopen
.
freopen
, how can I get the original stdout
(or
stdin
) back?
If you need to switch back and forth, the best all-around
solution is not to use freopen
in the first place. Try using
your own explicit output (or input) stream variable, which you
can reassign at will, while leaving the original stdout
(or
stdin
) undisturbed.
This problem is, in general, insoluble. Under Unix, for
instance, a scan of the entire disk, (perhaps requiring special
permissions) would theoretically be required, and would fail if
the file descriptor was a pipe or referred to a deleted file
(and could give a misleading answer for a file with multiple
links). It is best to remember the names of files yourself when
you open them (perhaps with a wrapper function around fopen
).