fgets() and extra characters...

S

santosh

Hi,

A book that I'm currently using notes that the fgets() function does
not
return until Return is pressed or an EOF or other error is encountered.

It then at most (in the absence of EOF/error), returns n-1 characters
plus
a appended null character.

Now, my question is:

If during a call to fgets(), (say with n == 64 and stdin), the user
happens
to enter much more than 64 characters, say 128, 256 or something like
that, fgets() would return with first 63 characters and a appended null

character only when the user presses Enter.

What would happen to the other characters? Can I assume that they would

be saved in a libc or OS level buffer and if so, upto what extent?

If fgets() blocks until Enter is pressed, am I correct in the
assumption that
successive calls to fgets() to retrieve the remaining characters would
fail,
since Enter is pressed by the user only once?

I'm confused as to the behaviour fgets() would exhibit under the above
conditions. None of the books or Standard Library documentation seem to

mention it.

Thanks.
 
E

Eric Sosman

santosh wrote On 12/06/05 07:21,:
Hi,

A book that I'm currently using notes that the fgets() function does
not
return until Return is pressed or an EOF or other error is encountered.

It then at most (in the absence of EOF/error), returns n-1 characters
plus
a appended null character.

Now, my question is:

If during a call to fgets(), (say with n == 64 and stdin), the user
happens
to enter much more than 64 characters, say 128, 256 or something like
that, fgets() would return with first 63 characters and a appended null

character only when the user presses Enter.

What would happen to the other characters? Can I assume that they would

be saved in a libc or OS level buffer and if so, upto what extent?

The characters not yet read by fgets() remain unread,
and are still on the stream ready for you to read them
with another fgets() or with getc() or whatever you like.

The "up to what extent" answer depends on the operating
system, and on the device from which the stream obtains its
input (remember, input needn't always come from a keyboard).
Consult the O/S documentation for details like the maximum
length of input lines obtained from keyboards, from sockets,
from disk files, ...
If fgets() blocks until Enter is pressed, am I correct in the
assumption that
successive calls to fgets() to retrieve the remaining characters would
fail,
since Enter is pressed by the user only once?

fgets() does not block until Enter is pressed; fgets
just keeps on reading until it receives a newline, fills
the buffer, or encounters end-of-file or error. fgets()
is completely unaware of Enter or of any other key -- or
of mice, light-pens, voice-activated input devices, you
name it. Management of all such devices is the job of
the operating system, which will deliver input characters
to fgets() when it feels like doing so. Again, consult
the O/S documentation.
I'm confused as to the behaviour fgets() would exhibit under the above
conditions. None of the books or Standard Library documentation seem to

mention it.

I hope your confusion is less than it was.
 
P

pete

santosh said:
Hi,

A book that I'm currently using notes that the fgets() function does
not
return until Return is pressed or an EOF or other error is encountered.

It then at most (in the absence of EOF/error), returns n-1 characters
plus
a appended null character.

Now, my question is:

If during a call to fgets(), (say with n == 64 and stdin), the user
happens
to enter much more than 64 characters, say 128, 256 or something like
that, fgets() would return with first 63 characters and a appended null

character only when the user presses Enter.

What would happen to the other characters? Can I assume that they would

be saved in a libc or OS level buffer and if so, upto what extent?

If fgets() blocks until Enter is pressed, am I correct in the
assumption that
successive calls to fgets() to retrieve the remaining characters would
fail,
since Enter is pressed by the user only once?

I'm confused as to the behaviour fgets() would exhibit under the above
conditions.
None of the books or Standard Library documentation seem to

mention it.

The OK_input function in this post:
http://groups.google.com/group/comp.lang.c/msg/623d442eaf6cc380
was the last time that I wrote anything with fgets.
It was intended to give reasonable responses
to two kittens fighting on the keyboard.

Now I use this method:
http://groups.google.com/group/comp.lang.c/msg/27bbc52f5be7f3be
If rc equals 0, that means that a zero length string
was entered and the array will contain garbage.

The one caveat, is that if the string length
excedes the LENGTH macro,
then the extra characters just get eaten.

It's good for text files too:
http://groups.google.com/group/comp.lang.c/msg/84e8b7bb11a2c6b8
 
E

Emmanuel Delahaye

santosh a écrit :
Now, my question is:

If during a call to fgets(), (say with n == 64 and stdin), the user
happens
to enter much more than 64 characters, say 128, 256 or something like
that, fgets() would return with first 63 characters and a appended null
> character only when the user presses Enter.
Correct.


What would happen to the other characters? Can I assume that they would
be saved in a libc or OS level buffer and if so, upto what extent?

They are stored somewhere, and can be read by the next call of any input
function like fgets() or fgetc() without any wait (unlesse a '\n' is
read, that denotes that the entire line has finally been read.

Just try it.
If fgets() blocks until Enter is pressed, am I correct in the
assumption that
successive calls to fgets() to retrieve the remaining characters would
fail,
since Enter is pressed by the user only once?

I'm confused as to the behaviour fgets() would exhibit under the above
conditions. None of the books or Standard Library documentation seem to

mention it.

Actually it's well explained about fgetc() in the K&R. The input
functions are based on the fgetc() functions.
 
P

pemo

pete said:
The OK_input function in this post:
http://groups.google.com/group/comp.lang.c/msg/623d442eaf6cc380
was the last time that I wrote anything with fgets.
It was intended to give reasonable responses
to two kittens fighting on the keyboard.

Now I use this method:
http://groups.google.com/group/comp.lang.c/msg/27bbc52f5be7f3be
If rc equals 0, that means that a zero length string
was entered and the array will contain garbage.

The one caveat, is that if the string length
excedes the LENGTH macro,
then the extra characters just get eaten.

It's good for text files too:
http://groups.google.com/group/comp.lang.c/msg/84e8b7bb11a2c6b8

Disclaimer: I'm kinda blind to this 'sort of problem', as - like a lot of
folk(I truly suspect) - since I [can almost] remember - I've only asked the
OS to give me the user's input for quite some time now [20+ years or so].

Had a look at your code [very briefly], but, as I'm tired-out right now, I
found myself saying "ok. So I'm dumb. But what's wrong with fgets()?" And
[but I would like to vote: let's just give-up on scanf()]?"

..
 
P

pete

pemo said:
But what's wrong with fgets()?" And

fgets gives you all the options
to do whatever you want with all of the input,
but it can be complicated to use,
depending on what you want to do.
[but I would like to vote: let's just give-up on scanf()]?"

If you've decided that discarding the end characters
of lines which excede the buffer size is acceptable,
then using fscanf to read lines is very easy.
If not, then use fgets.
 
P

pemo

pete said:
pemo wrote:
If you've decided that discarding the end characters
of lines which excede the buffer size is acceptable,
then using fscanf to read lines is very easy.
If not, then use fgets.

Sorry, don't get that - it sounds like it ought to read

"If you've decided that discarding the end characters
of lines which excede the buffer size is acceptable,
then using fgets to read lines is very easy.
If not, then use fscanf.

Presumably using fscanf with stdin isn't recommended for buffer overrun
reasons?
 
S

santosh

santosh said:
Hi,

A book that I'm currently using notes that the fgets() function does not
return until Return is pressed or an EOF or other error is encountered.
<snip>

Thanks again to all of you.

I've found through experimentation that fgets() in conjunction with
feof(),
ferror() and clearerr() is as robust as it can get for input from
stdin.

The only 'little issue' is if there happens to be a EOF character
amidst
the normal input, all characters entered after the EOF seem to be
lost...
 
R

Richard Tobin

santosh said:
The only 'little issue' is if there happens to be a EOF character
amidst the normal input, all characters entered after the EOF seem to
be lost...

Different operating systems have different ideas about end-of-file, so
you need to find out about the system you are using and probably can't
solve your "little issue" in completely portable C.

For example:

In unix, there's something you can type on the keyboard that indicates
the end of the input. Usually it's control-D. But this doesn't
involve any "end-of-file character" being sent to the program, it
just causes the read to return and afterwards feof() will be true.
Calling clearerr() will let you read more characters. You can send
a control-D character without any implication of end-of-file by
using some escape character.

Similarly, unix files don't have any end-of-file character at the end;
the file's length is stored with it so there's no need for such a
thing.

I believe that Microsoft Windows behaves differently, marking the end
of the file by having a control-Z character in the stream. This is a
problem if that character can actually occur in the data. Opening the
file in binary mode may help, but may also have other implications.

-- Richard
 
F

Flash Gordon

pemo said:
Sorry, don't get that - it sounds like it ought to read

"If you've decided that discarding the end characters
of lines which excede the buffer size is acceptable,
then using fgets to read lines is very easy.
If not, then use fscanf.

No, I think Pete's post reads correctly.
Presumably using fscanf with stdin isn't recommended for buffer overrun
reasons?

No, it's generally not recommended because it can be hard to use,
however if used correctly there is no risk of buffer overflows.

In this particular case, I believe you could get fscanf to read a
maximum of N characters on a line then discard everything up to and
including the new line character. With fgets on the other hand
everything after what fitted in the buffer will still be there and you
will have to read it.
 
J

Joe Wright

Richard said:
Different operating systems have different ideas about end-of-file, so
you need to find out about the system you are using and probably can't
solve your "little issue" in completely portable C.

For example:

In unix, there's something you can type on the keyboard that indicates
the end of the input. Usually it's control-D. But this doesn't
involve any "end-of-file character" being sent to the program, it
just causes the read to return and afterwards feof() will be true.
Calling clearerr() will let you read more characters. You can send
a control-D character without any implication of end-of-file by
using some escape character.

Similarly, unix files don't have any end-of-file character at the end;
the file's length is stored with it so there's no need for such a
thing.

I believe that Microsoft Windows behaves differently, marking the end
of the file by having a control-Z character in the stream. This is a
problem if that character can actually occur in the data. Opening the
file in binary mode may help, but may also have other implications.

Microsoft inherited ^Z from CP/M. The CP/M directory defined a file's
size in 128-byte unit records. Fine for binary files but not for text.
If you would concatenate one text file to another, you had to know
precisely where the first ended. Hence the eof character, ^Z.

Because Microsoft inherited also lots of files from CP/M and because
backward compatibility was important, MS accommodates (to this day) the
^Z in text files. I don't know of any MS file system that actually
requires it.

Note that if you open a MS text file in binary mode you will see not
only any 0x1a (^Z) character but also the 0x0d (^M) carriage return just
before the end of each line.
 

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

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top