getchar() after EOF

M

Michael Brennan

If a call to getchar() returns EOF, is the behavior
defined if another getchar() call is made? Will it
return EOF again?

The reason I'm asking: if I have a function that uses
getchar() repeatedly, and it returns EOF after some bytes,
do I need the function to handle the EOF right there,
or, can I just wait until the next time my function executes,
and handle it there, if EOF will be returned by the first call
to getchar().

Thanks!

/Michael
 
W

Walter Roberson

If a call to getchar() returns EOF, is the behavior
defined if another getchar() call is made? Will it
return EOF again?

Yes. Though in my reading of C89, it might plausibly set the
error indicator as it does so.

The reason I'm asking: if I have a function that uses
getchar() repeatedly, and it returns EOF after some bytes,
do I need the function to handle the EOF right there,
or, can I just wait until the next time my function executes,
and handle it there, if EOF will be returned by the first call
to getchar().

What would you do with the EOF's returned in the itermediate
calls? If you were planning on storing them, then remember that
EOF is an int, not a char
 
J

Jim Cook

If a call to getchar() returns EOF, is the behavior
defined if another getchar() call is made? Will it
return EOF again?

7.19.7.6 of the standard says this:
"The getchar function returns the next character from the input stream
pointed to by stdin. If the stream is at end-of-file, the end-of-file
indicator for the stream is set and getchar returns EOF."

I believe that a stream, once at end-of-file remains at end-of-file
unless reverse positioning happens. However, I cannot find a direct
statement about this in the standard.
 
W

Walter Roberson

7.19.7.6 of the standard says this:
"The getchar function returns the next character from the input stream
pointed to by stdin. If the stream is at end-of-file, the end-of-file
indicator for the stream is set and getchar returns EOF."
I believe that a stream, once at end-of-file remains at end-of-file
unless reverse positioning happens.

Though clrerror() will clear the EOF indicator as well as the
error indicator.
 
M

Michael Brennan

Walter said:
What would you do with the EOF's returned in the itermediate
calls? If you were planning on storing them, then remember that
EOF is an int, not a char

My function puts chars returned by getchar() in a string and returns it.
If it encounters an EOF, I want to notify that to the caller, maybe by
returning NULL. But that won't work if I encounter the EOF directly
after some chars in the same function run since I can't return both the
string and NULL, so I've come up with three options.

1. indicate end-of-file some other way, by using an argument or
2. save the EOF in a static variable and return NULL if it is set
3. just call getchar() again the next time the function runs and return
NULL when that EOF is read.

Which one would be best of these? or is there an even better way?
 
C

CBFalconer

Michael said:
My function puts chars returned by getchar() in a string and returns it.
If it encounters an EOF, I want to notify that to the caller, maybe by
returning NULL. But that won't work if I encounter the EOF directly
after some chars in the same function run since I can't return both the
string and NULL, so I've come up with three options.

1. indicate end-of-file some other way, by using an argument or
2. save the EOF in a static variable and return NULL if it is set
3. just call getchar() again the next time the function runs and return
NULL when that EOF is read.

Which one would be best of these? or is there an even better way?

None. Text files in C consist of complete lines, terminated with
'\n'. The problem does not arise when you transmit things on
encountering a '\n'. Thus:

int ch; /* note this is an int */
char buffer[SOMESIZE+1];
int i;

i = 0;
while (EOF != (ch = getchar())) {
if ('\n' == ch) {
dosomethingwith(buffer);
buffer = '\0';
i = 0;
}
else if (i < SOMESIZE) buffer[i++] = ch;
else youareoverunningthebuffer();
}
/* file is all read */


--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 
M

Michael Brennan

CBFalconer said:
None. Text files in C consist of complete lines, terminated with
'\n'. The problem does not arise when you transmit things on
encountering a '\n'. Thus:

Does that mean that there always will be a '\n' before an EOF, and
that 'A','B','C',EOF will never occur?
What if the last line in a file does not end with a '\n', or
if a user signals EOF on stdin before pressing return.
Will a '\n' be appended automatically?
int ch; /* note this is an int */
char buffer[SOMESIZE+1];
int i;

i = 0;
while (EOF != (ch = getchar())) {
if ('\n' == ch) {
dosomethingwith(buffer);
buffer = '\0';
i = 0;
}
else if (i < SOMESIZE) buffer[i++] = ch;
else youareoverunningthebuffer();
}
/* file is all read */
 
K

Keith Thompson

Michael Brennan said:
My function puts chars returned by getchar() in a string and returns it.
If it encounters an EOF, I want to notify that to the caller, maybe by
returning NULL. But that won't work if I encounter the EOF directly
after some chars in the same function run since I can't return both the
string and NULL, so I've come up with three options.

1. indicate end-of-file some other way, by using an argument or
2. save the EOF in a static variable and return NULL if it is set
3. just call getchar() again the next time the function runs and
return NULL when that EOF is read.

Which one would be best of these? or is there an even better way?

Using a static variable can cause problems.

Note that fgets() does something very similar to what you're doing.
Take a look at what it does, and consider handling EOF in the same
way.
 
E

Eric Sosman

CBFalconer wrote On 06/12/06 14:44,:
None. Text files in C consist of complete lines, terminated with
'\n'.

We could say that "well-formed" text files or "text files
written by portable programs" consist only of '\n'-terminated
lines, but it's a stretch to say that "all" text files are so
nicely put together. The Standard explicitly mentions the
possibility that a file of text lines might not end in '\n'
(7.19.2/2, right after it says what a "line" is).

The consequences are two: First, a portable program should
always write complete '\n'-terminated lines, because the
implementation might require the terminator and might misbehave
without it. Second, a portable program should be prepared to
deal with a text stream that lacks its final '\n', because the
implementation might allow them.
The problem does not arise when you transmit things on
encountering a '\n'.

... unless the final '\n' is missing. It "shouldn't" be
missing, but the Standard does not say that it "shall not" be
missing, so the eventuality must be considered. Some plausible
responses:

- Accept the EOF-terminated "line" as valid, and process
it like any other line. Variations: leave the line's
data "bare," or synthesize a '\n' for it. (If you like
to strip the '\n' from each normal line, distinguishing
between these variations becomes a problem for philosophers
more than for programmers.)

- Howl, complain, protest, and sulk, possibly by calling
abort() or exit(EXIT_FAILURE) or something of the kind.
Bad data (if you choose to call the '\n'-less line "bad,"
which is a reasonable choice) is bad data, and ought to
be detected and rejected.
Thus: [...]

Simply ignoring the suspect "line" and carrying on as if
everything were hunky-dory isn't a course I'd choose.
 
K

Keith Thompson

Michael Brennan said:
Does that mean that there always will be a '\n' before an EOF, and
that 'A','B','C',EOF will never occur?
What if the last line in a file does not end with a '\n', or
if a user signals EOF on stdin before pressing return.
Will a '\n' be appended automatically?

No. C99 7.19.2p2 says:

A text stream is an ordered sequence of characters composed into
*lines*, each line consisting of zero or more characters plus a
terminating new-line character. Whether the last line requires a
terminating new-line character is implementation-defined.

Unfortunately, the standard isn't clear about what's supposed to
happen in an implementation where the terminating new-line is required
if it's not actually present; presumably it's undefined behavior.

But on many systems, the terminating new-line *isn't* required. On
such a system, if you have a file consisting of the three characters
'A', 'B', and 'C' followed by end-of-file, fgets(), for example, will
give you the string "ABC" without a '\n'.
 
C

CBFalconer

Michael said:
Does that mean that there always will be a '\n' before an EOF, and
that 'A','B','C',EOF will never occur?
What if the last line in a file does not end with a '\n', or
if a user signals EOF on stdin before pressing return.
Will a '\n' be appended automatically?
No. However the code below will still function correctly. At exit
from the loop, if the buffer is non-empty (detected by i > 0) the
system has allowed a final line without a '\n'. Note that a file
can be empty, when the first call to getchar returns EOF. The line
"buffer = '\0';" should precede "dosomethinwith(buffer);" to
ensure that buffer holds a valid C string. The code also ALWAYS
absorbs the '\n'.
int ch; /* note this is an int */
char buffer[SOMESIZE+1];
int i;

i = 0;
while (EOF != (ch = getchar())) {
if ('\n' == ch) {
dosomethingwith(buffer);
buffer = '\0';
i = 0;
}
else if (i < SOMESIZE) buffer[i++] = ch;
else youareoverunningthebuffer();
}
/* file is all read */


--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
Also see <http://www.safalra.com/special/googlegroupsreply/>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top