gets, fgets Question

H

herrcho

int get_lines(char *lines[])
{
int n = 0;
char buffer[80];

puts("Enter one line at time; enter a blank when done");

while ((n < MAXLINES) && (gets(buffer) !=0 ) && (buffer[0] != '\0'))
{
if ((lines[n] = malloc(strlen(buffer)+1)) == NULL)
return -1;
strcpy (lines[n++], buffer);
}
return n;
}

the above code is from the book ' Teach yourself C '
it's for reading a row at a time, and if i just press enter without any
input, the loop terminates.

Question..

1. gets(buffer) !=0 --> what does this mean ?
as far as i know, 'gets' function returns NULL when error occurs,
so it means gets(buffer) !=NULL ?
either of them is alright ?

2. I'd like to change the while statement using fgets.
so i tried the below

while ((n < MAXLINES) && (fgets(buffer,80,stdin) !=0 ) &&
(buffer[0] != '\0'))
BUT !!
the loop doesn't end when i press enter without any input.
i guess (buffer[0] != '\0')) is wrong..

Thanks in advance..

BTW ,, i saw a group, comp.lang.c.moderated,, what's the difference ?
 
R

Robert Stankowic

herrcho said:
int get_lines(char *lines[])
{
int n = 0;
char buffer[80];

puts("Enter one line at time; enter a blank when done");

while ((n < MAXLINES) && (gets(buffer) !=0 ) && (buffer[0] != '\0'))
{
if ((lines[n] = malloc(strlen(buffer)+1)) == NULL)
return -1;
strcpy (lines[n++], buffer);
}
return n;
}

the above code is from the book ' Teach yourself C '

Burn the book ;)
it's for reading a row at a time, and if i just press enter without any
input, the loop terminates.

Question..

1. gets(buffer) !=0 --> what does this mean ?
as far as i know, 'gets' function returns NULL when error occurs,
so it means gets(buffer) !=NULL ?
either of them is alright ?
Yes


2. I'd like to change the while statement using fgets.

Bravo :)
so i tried the below

while ((n < MAXLINES) && (fgets(buffer,80,stdin) !=0 ) &&
(buffer[0] != '\0'))
BUT !!
the loop doesn't end when i press enter without any input.
i guess (buffer[0] != '\0')) is wrong..
Yes
The gets function reads a line from the standard input stream stdin and
stores it in buffer. The line consists of all characters up to and including
the first newline character ('\n'). gets then replaces the newline character
with a null character ('\0') before returning the line. In contrast, the
fgets function retains the newline character.
You see?
regards
Robert
 
R

Richard Bos

herrcho said:
int get_lines(char *lines[])
{
int n = 0;
char buffer[80];

puts("Enter one line at time; enter a blank when done");

while ((n < MAXLINES) && (gets(buffer) !=0 ) && (buffer[0] != '\0'))
{
if ((lines[n] = malloc(strlen(buffer)+1)) == NULL)
return -1;
strcpy (lines[n++], buffer);
}
return n;
}

the above code is from the book ' Teach yourself C '

Ditch that book. Now. Any book teaching you to use gets() is a time
bomb.
1. gets(buffer) !=0 --> what does this mean ?
as far as i know, 'gets' function returns NULL when error occurs,

No, it doesn't, since NULL is a part of your source code, not an object.
When an error occurs (at least, an error that gets() is capable of
detecting, the poor blind thing), gets() returns a null pointer.

Now, the way to encode a null pointer in your code is to use a null
pointer constant in a pointer context. Pointer context is simple:
whenever something is compared or assigned to a pointer, that's a
pointer context. In this case, gets() returns a pointer, and your 0 or
NULL is compared to it, so that part's OK.

A null pointer constant is either an integer constant with the value 0
(0, or ('-'-'-'), or (!sizeof(char))...), or such an integer cast to
void *. So 0 is a null pointer constant, and if you compare the return
value of gets() to 0, what happens is that this null pointer constant is
turned into a null pointer, and compared to the return value.
Note that it is _not_ the other way around, as people sometimes think:
no pointers are converted and then compared to a numerical 0. This is
why, for example, this:

int false_null_pointer=0;
if (fgets(x,y,z)==false_null_pointer) ...

is not guaranteed to work. It must be a null pointer _constant_.

And NULL? NULL is simply a macro which is defined to be some null
pointer constant. The implementation gets to choose which null pointer
constant, but a valid null pointer constant, anyway.
either of them is alright ?

NULL and 0 are equivalent in this (pointer) context, yes.
2. I'd like to change the while statement using fgets.
so i tried the below

while ((n < MAXLINES) && (fgets(buffer,80,stdin) !=0 ) &&
(buffer[0] != '\0'))
BUT !!
the loop doesn't end when i press enter without any input.
i guess (buffer[0] != '\0')) is wrong..

Yes. fgets(), unlike gets(), always leaves the final '\n' in the buffer,
if there is one. This is how you can tell whether fgets() read all input
or returned because its buffer was full.
BTW ,, i saw a group, comp.lang.c.moderated,, what's the difference ?

Erm... c.l.c.m. is moderated?

Richard
 
J

John Bode

herrcho said:
int get_lines(char *lines[])
{
int n = 0;
char buffer[80];

puts("Enter one line at time; enter a blank when done");

while ((n < MAXLINES) && (gets(buffer) !=0 ) && (buffer[0] != '\0'))
{
if ((lines[n] = malloc(strlen(buffer)+1)) == NULL)
return -1;
strcpy (lines[n++], buffer);
}
return n;
}

the above code is from the book ' Teach yourself C '

Just to echo all the other responses, any book that advocates the use
of gets() in any context is suspect. Putting gets() anywhere in your
code introduces a point of failure.
it's for reading a row at a time, and if i just press enter without any
input, the loop terminates.

Question..

1. gets(buffer) !=0 --> what does this mean ?
as far as i know, 'gets' function returns NULL when error occurs,
so it means gets(buffer) !=NULL ?
either of them is alright ?

Essentially, yes. On a successful read, gets() will return the
address of the buffer you're reading into. If it encounters an EOF or
error on the standard input stream, it will return the null pointer
value. A literal 0 in a pointer context is understood to represent
the null pointer value.
2. I'd like to change the while statement using fgets.

Good for you. It's safer than gets(), anyway.
so i tried the below

while ((n < MAXLINES) && (fgets(buffer,80,stdin) !=0 ) &&
(buffer[0] != '\0'))
BUT !!
the loop doesn't end when i press enter without any input.
i guess (buffer[0] != '\0')) is wrong..

Unlike gets(), fgets() stores the newline character as part of the
array. So you'll need to change that test to

(buffer[0] != '\0' && buffer[0] != '\n')
Thanks in advance..

BTW ,, i saw a group, comp.lang.c.moderated,, what's the difference ?

It's a moderated newsgroup, meaning messages are first examined by a
moderator for content before they actually appear in the newsgroup.
There's a FAQ on moderation...somewhere...ah, here it is:

http://www.swcp.com/~dmckeon/mod-faq.html

In short, c.l.c.m doesn't suffer from endless flame wars, trolls, and
general off-topic nonsense.
 
D

Dan Pop

In said:
int get_lines(char *lines[])
{
int n = 0;
char buffer[80];

puts("Enter one line at time; enter a blank when done");

while ((n < MAXLINES) && (gets(buffer) !=0 ) && (buffer[0] != '\0'))
{
if ((lines[n] = malloc(strlen(buffer)+1)) == NULL)
return -1;
strcpy (lines[n++], buffer);
}
return n;
}

the above code is from the book ' Teach yourself C '
it's for reading a row at a time, and if i just press enter without any
input, the loop terminates.

Does the book also tell what happens when the user types 100 characters
before pressing the Enter key?
Question..

1. gets(buffer) !=0 --> what does this mean ?
as far as i know, 'gets' function returns NULL when error occurs,
so it means gets(buffer) !=NULL ?
either of them is alright ?

Yes, provided one of the headers defining NULL has been included. NULL,
however, makes your code more readable, so it is preferable to a naked 0.
2. I'd like to change the while statement using fgets.
so i tried the below

while ((n < MAXLINES) && (fgets(buffer,80,stdin) !=0 ) &&
(buffer[0] != '\0'))
BUT !!
the loop doesn't end when i press enter without any input.
i guess (buffer[0] != '\0')) is wrong..

Good guess! Make it (buffer[0] != '\n')). NEVER use a function before
carefully reading its specification. gets/fgets and puts/fputs are
tricky pairs.
BTW ,, i saw a group, comp.lang.c.moderated,, what's the difference ?

Being moderated, c.l.c.m has a lot less off-topic content, but the
moderation process kills the response time: you post it today, it will
show up tommorrow and the first responses will come the day after
tomorrow. In the best case scenario, you get the first answers the
next day, but still have to wait one more day, for reactions to the
first "batch" of responses. In the "wild" c.l.c, you can have a full
blown thread in a couple of hours.

Dan
 
B

Barry Kimelman

int get_lines(char *lines[])
{
int n = 0;
char buffer[80];

puts("Enter one line at time; enter a blank when done");

while ((n < MAXLINES) && (gets(buffer) !=0 ) && (buffer[0] != '\0'))
{
if ((lines[n] = malloc(strlen(buffer)+1)) == NULL)
return -1;
strcpy (lines[n++], buffer);
}
return n;
}

the above code is from the book ' Teach yourself C '
it's for reading a row at a time, and if i just press enter without any
input, the loop terminates.

Question..

1. gets(buffer) !=0 --> what does this mean ?
as far as i know, 'gets' function returns NULL when error occurs,
so it means gets(buffer) !=NULL ?
Correct.
either of them is alright ?
Yes. Either should work ok.
2. I'd like to change the while statement using fgets.
so i tried the below

while ((n < MAXLINES) && (fgets(buffer,80,stdin) !=0 ) &&
(buffer[0] != '\0'))
BUT !!
the loop doesn't end when i press enter without any input.
i guess (buffer[0] != '\0')) is wrong..

Thanks in advance..

BTW ,, i saw a group, comp.lang.c.moderated,, what's the difference ?

while ( (n < MAXLINES) && (fgets(buffer,sizeof(buffer),stdin)
!= 0 ) && (buffer[0] != '\n') ) {
 
T

Tom Zych

herrcho said:
while ((n < MAXLINES) && (gets(buffer) !=0 ) && (buffer[0] != '\0'))

No one else so far has explained exactly *why* gets() is poison
(though Dan Pop hinted at it), and the FAQ doesn't seem to address
it explicitly either, so burn this in 2-meter-high letters on your
mind's eye:

NEVER USE GETS()!!!

gets() is one of those unfortunate things that really shouldn't be
in C at all, but we're stuck with it. At least my compiler (gcc)
always warns you not to use it. They all should. And the damned C
books that fail to warn you about it should be set on fire, then
stuffed into all of their authors' orifices. (Making an exception
for the old ones like K&R, from before anyone knew how serious the
problem was.)

The thing about gets() is, it takes input directly from standard
input, and it has no protection against buffer overflow. A very
easily exploited combination.

Let's say I know a certain program is running on your networked
computer, and it uses gets() to read commands from the network; an
email delivery daemon, for example. Suppose I have the source code
of this program, and I know (or correctly guess) what kind of
processor you're using. Let's say the programmer thought it would
be safe to use a 512-byte buffer. No one would overflow such a
long buffer, right?

Not by accident, probably. But I'm going to do it on purpose,
muhaha! With carefully crafted data. Which gets() will happily
gulp, overflowing its buffer, and obligingly deposit in the memory
beyond the buffer. Where its executable code is.

Evil laugh. I now own your email program. And it's running with
system privileges, so I own your system, too. This is not
theoretical; crackers and worms have actually done this with
programs that use gets(). The Great Worm, which infected 6,000
large UNIX systems in 1988, exploited the use of gets() in a
daemon (among other security holes).

But, you're thinking, I'm just writing little test programs to
learn C. True. No one's going to exploit your homework to break
into your machine. But you really don't want to get into the habit
of using this evil, evil function.

So, to repeat:

NEVER USE GETS()!!!
 
D

Dan Pop

In said:
herrcho said:
while ((n < MAXLINES) && (gets(buffer) !=0 ) && (buffer[0] != '\0'))

No one else so far has explained exactly *why* gets() is poison
(though Dan Pop hinted at it), and the FAQ doesn't seem to address
it explicitly either,

When did they drop

12.23: Why does everyone say not to use gets()?

from the FAQ?

Dan
 
T

Tom Zych

When did they drop
12.23: Why does everyone say not to use gets()?
from the FAQ?

12.23 explains that the buffer may overflow. A newcomer to C may not
realize how dangerous this is. It sounds like an ordinary, everyday
bug, instead of a security-breaking, critical bug.
 
P

Peter Nilsson

Tom Zych said:
12.23 explains that the buffer may overflow. A newcomer to C may not
realize how dangerous this is. It sounds like an ordinary, everyday
bug, instead of a security-breaking, critical bug.

Why would a newbie think that an ordinary everyday bug was not worth
fixing?!

[I know why professionals dont! :) I just don't understand why people who
still have shreads of ideals, and fewer time and budgetry constraints,
wouldn't consider it worth fixing. ;-)]
 
T

Tom Zych

Why would a newbie think that an ordinary everyday bug was not worth
fixing?!
[I know why professionals dont! :) I just don't understand why people who
still have shreads of ideals, and fewer time and budgetry constraints,
wouldn't consider it worth fixing. ;-)]

What 12.23 doesn't make sufficiently clear, IMHO, is that using
gets() is THE classic example of a bug that shouldn't be introduced
in the first place :)
 
D

Dan Pop

In said:
Why would a newbie think that an ordinary everyday bug was not worth
fixing?!
[I know why professionals dont! :) I just don't understand why people who
still have shreads of ideals, and fewer time and budgetry constraints,
wouldn't consider it worth fixing. ;-)]

What 12.23 doesn't make sufficiently clear, IMHO, is that using
gets() is THE classic example of a bug that shouldn't be introduced
in the first place :)

And what is the classical example of a bug that can be introduced in your
programs? ;-)

Dan
 

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

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top