In article <27d81185-ca59-482e-898a->
<> wrote:
>Hi everybody, in a french C book, the author says that only {fgetc,
>getc, getchar, fgetwc, getwc, getwchar, fgets, gets, fgetws, getws,
>fputc, putc, putchar, fputwc, putwc, putwchar, fputs, puts, fputws}
>are guaranteed to set the end-of-file indicator when the end-of-file
>is reached ...
This is incorrect. In the "obviously wrong" part, putc() is not
going to set the end-of-file indicator, for instance.

But it
is still wrong, and perhaps overly complicated.
All I/O is done "as if" via fgetc() and fputc(). If fgetc() would
have set the end-of-file indicator, any other input-oriented
operation that would have called fgetc() must also set the e-o-f
indicator. (And of course, if fgetc() would have set the error
indicator, any other input-oriented operation that would have called
fgetc() must also set the error indicator. The "would have"s here
simply mean that, deep inside the implementation, scanf() or fread()
or whatever might use something "faster" or "better" than an actual
call to fgetc(), such as an inline expansion of what fgetc() does.
But if they do avoid fgetc() in favor of something "better", they
still have to act *as if* they had made an actual call to fgetc(),
including setting the e-of-f and/or error indicators in the same
way that fgetc() would have.)
(For instance, an implementation might have a macro like this:
#define fast_inlined_getc(f) \
((f)->_readcount > 0 ? --(f)->_readcount, *(f)->_readptr++ : \
fgetc(f))
and it could then use this in the scanf engine. The fgets() and
fread() functions might look directly at f->_readcount:
int fgets(char *buf, size_t bufsize, FILE *stream) {
...
p = memchr(f->_readptr, '\n', min(f->_readsize, room_in_user_buffer));
if (p != NULL) {
/*
* Found entire input line in current buffer. Do a quick
* copy-and-take.
*/
line_len = p - f->_readptr; /* length of the line */
memcpy(buf, f->_readptr, line_len); /* copy it */
f->_readptr += line_len; /* and take it out */
f->_readsize -= line_len; /* of the stdio buffer */
} else {
/*
* Found only part of line in current buffer, or buffer
* is empty. Do whatever is required to copy partial
* line (if any) and read more input, in a loop as needed.
*/
...
}
...
}
At some point, though, these all call fgetc() (or the underlying
code that implements fgetc()) to refill the stdio buffer. It is
this code that handles "read from underlying file or device"
requests, and it is this "read from underlying file or device"
request that encounters the kinds of failures that set the end-of-file
and/or error indicators.)
--
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: gmail (figure it out)
http://web.torek.net/torek/index.html