Newbie: How to input a string?

J

JJ

I've just been studying C. I have some outdated experience with
Pascal and Fortran which might be throwing me off.

From the Deitel book I've been reading, it seems I have these three
options for stdin input:

getchar()
scanf
gets

getchar is tedious because I have to do a character by character loop.
scanf stops at the first space, so if I try to input a sentence, this
is no good.
when I try to use gets my compiler tells me it is dangerous to use.

(1) why is gets dangerous
(2) what is the proper way to input one whole line of text?

Thanks.
 
J

Jack Klein

I've just been studying C. I have some outdated experience with
Pascal and Fortran which might be throwing me off.

From the Deitel book I've been reading, it seems I have these three
options for stdin input:

getchar()
scanf
gets

getchar is tedious because I have to do a character by character loop.
scanf stops at the first space, so if I try to input a sentence, this
is no good.
when I try to use gets my compiler tells me it is dangerous to use.

Always check a newsgroup's FAQ (Frequently Asked Questions) list
before posting.
(1) why is gets dangerous

This is a FAQ, specifically: "12.23 Why does everyone say not to use
gets()?" at http://www.eskimo.com/~scs/C-faq/q12.23.html
(2) what is the proper way to input one whole line of text?

This is covered in the same FAQ as above.

Get the entire FAQ, link in my signature.
 
R

Richard Heathfield

JJ said:
I've just been studying C. I have some outdated experience with
Pascal and Fortran which might be throwing me off.

From the Deitel book I've been reading, it seems I have these three
options for stdin input:

getchar()

Ewwww. Yes, you can get characters that way, but getting an entire line that
way can be /very/ tedious (although it is possible to wrap the tedium up
into a function which you can use over and over again).

Ewwwww. If you want to use scanf, ask Dan Pop about it. He's the only expert
I know of who likes it.

Ewwwwww. Just Say No. No overrun protection, you see.
getchar is tedious because I have to do a character by character loop.
Right.

scanf stops at the first space, so if I try to input a sentence, this
is no good.

Well, it /can/ be done, but it's painful.
when I try to use gets my compiler tells me it is dangerous to use.
Right.

(1) why is gets dangerous

You have no way to tell it how big your buffer is. Therefore, it has no way
to know when to stop.

(2) what is the proper way to input one whole line of text?

The least annoying standard library function for this is fgets(), but
fgets() - which does /not/ have the same problem that gets() does - has its
own problems instead. You see, if your buffer isn't big enough to store the
whole line, fgets() won't read the whole line into it (fair enough, but it
means you have to check for it). Furthermore, to let you know when it /has/
finally finished reading the line, it leaves the newline character ('\n')
in there, and typically you have to chop this out yourself.

I discuss all this in a little more detail, and present a solution that can
read an entire line, at http://users.powernet.co.uk/eton/c/fgetdata.html
 
P

pradeepag

1. Never use gets(). Because it is impossible to tell without knowing the
data in advance how many characters gets() will read, and because
gets() will continue to store characters past the end of the buffer, it
is extremely dangerous to use. It has been used to break computer
security.
2.Use fgets() instead.
For example;

#include <stdio.h>

int main(){

char charArray[256];

printf("Enter your sentence here: ");
fgets(charArray, 255,stdin);
printf("%s\n",charArray);
return 0;
}
Pradeepag
 
E

Emmanuel Delahaye

In said:
#include <stdio.h>

int main(){

char charArray[256];

printf("Enter your sentence here: ");

The output sentence not being a complete line ('\n' is missing), you probably
need:
fflush (stdout);

to stay portable...
fgets(charArray, 255,stdin);

Why 255?

fgets (charArray, sizeof charArray, stdin);

is just fine. You don't need to waste a char.
 
J

JJ

Thanks to everyone, that was very helpful, especially Richard's
http://users.powernet.co.uk/eton/c/fgetdata.html.

This leads me to two new questions.

(1) Since the fgets function does not return the length (up to \n) of
the string read in, is there an easy way, without once again resorting
to a char by char while loop, to get the length of the string?
Essentially I want to remove the \n at the end, for which I need the
length.

(2) I was reading about fgets here
http://www.crasseux.com/books/ctutorial/fgets.html#fgets. It says:
The fgets ("file get string") function is similar to the gets
function. This function is deprecated -- that means it is obsolete and
it is strongly suggested you do not use it -- because it is dangerous.
It is dangerous because if the input data contains a null character,
you can't tell. Don't use fgets unless you know the data cannot
contain a null. Don't use it to read files edited by the user because,
if the user inserts a null character, you should either handle it
properly or print a clear error message. Always use getline or
getdelim instead of fgets if you can.

What do you all think of this?

Thanks again.
 
R

Richard Heathfield

JJ said:
Thanks to everyone, that was very helpful, especially Richard's
http://users.powernet.co.uk/eton/c/fgetdata.html.

This leads me to two new questions.

(1) Since the fgets function does not return the length (up to \n) of
the string read in, is there an easy way, without once again resorting
to a char by char while loop, to get the length of the string?

No. You can use strlen(), but guess how a typical strlen implementation
works? Still, if you need to know the length, use strlen, since it's your
best shot at a fast solution.
Essentially I want to remove the \n at the end, for which I need the
length.

Well, you can do this:

#include <string.h>

/* this function returns 0 if there was no newline to chomp */
int chomp(char *s)
{
int chomped = 0;
char *p = strchr(s, '\n');
if(p != NULL)
{
chomped = 1;
*p = '\0';
}
return chomped;
}
(2) I was reading about fgets here
http://www.crasseux.com/books/ctutorial/fgets.html#fgets. It says:
The fgets ("file get string") function is similar to the gets
function. This function is deprecated -- that means it is obsolete and
it is strongly suggested you do not use it -- because it is dangerous.

That's nonsense, which you can safely ignore.
It is dangerous because if the input data contains a null character,
you can't tell.

You know it won't, because a text file can't contain null characters (if it
contains null characters, it isn't a text file), and you /only/ use fgets
on text files. Easy.
 
M

Mark McIntyre

Thanks to everyone, that was very helpful, especially Richard's
http://users.powernet.co.uk/eton/c/fgetdata.html.

This leads me to two new questions.

(1) Since the fgets function does not return the length (up to \n) of
the string read in, is there an easy way, without once again resorting
to a char by char while loop, to get the length of the string?

either
a) use an array thats large enough to hold the largest possible string
you could read in or
b) read into a buffer, if there's more resize it and so on till you
get the whole string.
(2) I was reading about fgets here
http://www.crasseux.com/books/ctutorial/fgets.html#fgets. It says:
The fgets ("file get string") function is similar to the gets
function. This function is deprecated -- that means it is obsolete and
it is strongly suggested you do not use it --

This is absolutely not true.
because it is dangerous.
It is dangerous because if the input data contains a null character,
you can't tell.

True but muddle-headed. Remember fgets gets a *string*. By definition,
a string cannot contain a null. So talk of nulls in the context of
fgets is meaningless.
Don't use fgets unless you know the data cannot
contain a null.

Well, since fgets is a string reader, this is axiomatic !! Here's a
better take on it:

1) use fgets to get lines of text.
2) use fread to get binary data.

Note that pretty much by by definition, text cannot include nulls or
other unprintable characters, while binary data can contain both.
Don't use it to read files edited by the user because,

This is stupid. fgets is a splendid function for reading user input.
if the user inserts a null character,

IME users virtually NEVER insert nulls into text files. What a weird
idea!
you should either handle it
properly or print a clear error message.
true.

Always use getline or
getdelim instead of fgets if you can.

neither of which is C - they may be unix functions, I dunno.
What do you all think of this?

Its very muddled.
 
R

Richard Heathfield

Mark said:
either
a) use an array thats large enough to hold the largest possible string
you could read in or
b) read into a buffer, if there's more resize it and so on till you
get the whole string.

How will that help him to get the length of the string?

<snip>
 
P

Paul Hsieh

I've just been studying C. I have some outdated experience with
Pascal and Fortran which might be throwing me off.

From the Deitel book I've been reading, it seems I have these three
options for stdin input:

getchar()
scanf
gets

None of these are any good, and fgets is at best a compromise. I've
written a little ditty on the subject here:

http://www.pobox.com/~qed/userInput.html
 
D

Dave Thompson

JJ wrote:

That's nonsense, which you can safely ignore.


You know it won't, because a text file can't contain null characters (if it
contains null characters, it isn't a text file), and you /only/ use fgets
on text files. Easy.

Not absolutely. The standard does not require that text files support
containing nulls, but it allows it, and most filesystems today and
therefore (always?) implementations built on them do support it. Some
(text) editors make it impossible or at least quite difficult to enter
a null, but others make it easy, maybe even unintentionally, and there
is (almost?) always the possibility of moving a file from one tool or
system where it is easy to another where it otherwise isn't.

One can argue that it isn't worth the effort to handle text lines
containing nulls, other than by implicitly truncating, since there are
no clearly generally correct semantics, and I would probably agree,
but you can't automatically rule it out.

Also, I could come up with cases -- although not many -- where it
makes sense to use fgets on a binary file, because (and where) it
contains snippets of text -- although no nulls *in those snippets*.

- David.Thompson1 at worldnet.att.net
 

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,139
Messages
2,570,806
Members
47,353
Latest member
TamiPutnam

Latest Threads

Top