scanf problem with intaking a string *PLS. HELP*

R

Radith

HI all;

I have created a program just to get an understanding of strcpy. (still an
amateur developer).

I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).

Then I go strcpy(second, first). This is just to demonstrate the strcpy
function for myself and it (as far as I know) copies what's in first to
second.

The problem is: * When a user uses spaces in his/her input (e.g. "Hello
World")
--> Only "Hello" will be displayed.

Now I have made sure the array has ample size; I just dont know what's
wrong?

I unfortunately have deleted the source code by mistake (as I was
frustrated); so I can't supply it here; If y'all really need it I wouldn't
ming writing it out again but I think y'all can have a pretty good
understanding from my descriptions.

Please Help. Thanks a lot for it in advance.
 
B

Ben Pfaff

Radith said:
I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).

Then I go strcpy(second, first). This is just to demonstrate the strcpy
function for myself and it (as far as I know) copies what's in first to
second.

The problem is: * When a user uses spaces in his/her input (e.g. "Hello
World")
--> Only "Hello" will be displayed.

This is because %s only reads a single word. It will skip
leading white space, but after that white space causes it to stop
reading.
 
M

Malcolm

Radith said:
I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).
scanf("%s", ptr);

will only read the first word (string of characters separated by whitespace)
into the bufer pointed to by ptr.
You can read a whole line with gets(). Unfortunately the function is flawed,
because the buffer will overrun, probably causing a crash, if the user types
in too many characters. fgets() is even worse if used incorrectly - input is
silently truncated. Why is that worse? Because wrong results are usually
worse than no results. However you can build a solid input function on top
of fgets(), but it is needlessly complicated.
So regrettably there is no easy way of getting a line from the user in ISO
C.
 
K

Keith Thompson

Malcolm said:
Radith said:
I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).
scanf("%s", ptr);

will only read the first word (string of characters separated by whitespace)
into the bufer pointed to by ptr.
You can read a whole line with gets(). Unfortunately the function is flawed,
because the buffer will overrun, probably causing a crash, if the user types
in too many characters. fgets() is even worse if used incorrectly - input is
silently truncated. Why is that worse? Because wrong results are usually
worse than no results. However you can build a solid input function on top
of fgets(), but it is needlessly complicated.
So regrettably there is no easy way of getting a line from the user in ISO
C.

fgets() is worse than gets()?

Nonsense.
 
M

Martijn

[snipped] If y'all really need it [snipped]

Is that your truck in MUD95?

Alright, alright, I'll start contributing serious responses again.
 
M

Michael Mair

Keith said:
Malcolm said:
Radith said:
I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).

scanf("%s", ptr);

will only read the first word (string of characters separated by whitespace)
into the bufer pointed to by ptr.
You can read a whole line with gets(). Unfortunately the function is flawed,
because the buffer will overrun, probably causing a crash, if the user types
in too many characters. fgets() is even worse if used incorrectly - input is
silently truncated. Why is that worse? Because wrong results are usually
worse than no results. However you can build a solid input function on top
of fgets(), but it is needlessly complicated.
So regrettably there is no easy way of getting a line from the user in ISO
C.


fgets() is worse than gets()?

Nonsense.

Well, in a way, it is: It is the closest you can get to a sensible
text input function but falls short, unnecessarily and nastily.
If you consider a function more broken which does not invoke UB
(and quite often segfaults to tell you where you went wrong)
instead of silently truncating and upsetting everything in a
hard-to-catch way, then you can arrive at this conclusion.
IMO, fgets() with sensible return values to communicate, say
EOF/Error/NoNewLineEncountered/NewLineEncountered, would be
quite alright.


Cheers
Michael
 
M

Mark F. Haigh

Michael said:
Keith Thompson wrote:


Well, in a way, it is: It is the closest you can get to a sensible
text input function but falls short, unnecessarily and nastily.
If you consider a function more broken which does not invoke UB
(and quite often segfaults to tell you where you went wrong)
instead of silently truncating and upsetting everything in a
hard-to-catch way, then you can arrive at this conclusion.
<snip>

Huh? UB nearly universally "[upsets] everything in a hard-to-catch
way". Even worse, it often results in security holes.

Well-defined but annoying behavior is certainly not worse, at least in
the sense of the word I am accustomed to.


Mark F. Haigh
(e-mail address removed)
 
C

Chris Croughton

Keith said:
Malcolm said:
I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).


scanf("%s", ptr);

will only read the first word (string of characters separated by whitespace)
into the bufer pointed to by ptr.
You can read a whole line with gets(). Unfortunately the function is flawed,
because the buffer will overrun, probably causing a crash, if the user types
in too many characters. fgets() is even worse if used incorrectly - input is
silently truncated. Why is that worse? Because wrong results are usually
worse than no results. However you can build a solid input function on top
of fgets(), but it is needlessly complicated.
So regrettably there is no easy way of getting a line from the user in ISO
C.

fgets() is worse than gets()?

Nonsense.

Well, in a way, it is: It is the closest you can get to a sensible
text input function but falls short, unnecessarily and nastily.

OK, so it's not a perfect interface, lots of the C library isn't a
perfect interface. Whether it is 'necessary' to have had that interface
is a matter of opinion, but most of the I/O interface wasn't designed,
it "jest growed". It's certainly perfectly usable.
If you consider a function more broken which does not invoke UB
(and quite often segfaults to tell you where you went wrong)
instead of silently truncating and upsetting everything in a
hard-to-catch way, then you can arrive at this conclusion.

I have never had fgets() segfault, except when passing it invalid
parameters. How have you done it? If you give it a valid file pointer,
valid pointer to a data area and a correct length (no greater than the
size of the data area) then if it segfaults you have a faulty
implementation.

fgets() doesn't 'truncate', it simply stops inputting when the buffer is
full. Doing "if (strchr(buffer, '\n'))" will detect whether the line
was complete at that point (strlen() would do as well). You can then
decide whether you want to discard the rest of the data, increase the
buffer size, or whatever. If you don't bother testing then your program
is broken, no more or less than if you ignore returned status.
IMO, fgets() with sensible return values to communicate, say
EOF/Error/NoNewLineEncountered/NewLineEncountered, would be
quite alright.

All that information is available. You can call feof/ferror on the
input stream (fgets() will return NULL if it didn't get anything) and
you can test for newline as above.

Or of course you can write your own input function with the behaviour
you like, it's not hard (indeed, I've rewritten such functions many
times because it was faster than digging out the code I'd written
before).

Chris C
 
L

Lawrence Kirby

Radith said:
I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).
scanf("%s", ptr);

will only read the first word (string of characters separated by whitespace)
into the bufer pointed to by ptr.
You can read a whole line with gets(). Unfortunately the function is flawed,
because the buffer will overrun, probably causing a crash, if the user types
in too many characters.
Correct.

fgets() is even worse if used incorrectly - input is
silently truncated. Why is that worse? Because wrong results are usually
worse than no results.

Often correct input has limited length. In which case fgets() (given a
suitable arguments) will only go "wrong" on invalid input, which is
perfectly reasonable.

Also you imply that gets() would give no results, which is wrong. fgets()
has well defined behaviour on too long input even if it isn't the
behaviour you want, gets() has undefined behaviour. Both can give results,
the difference is that with fgets() the results are well defined and quite
possibly recoverable, with gets() the whole program ceases to be
predictable. There is no sense in which fgets() is worse than gets().
However you can build a solid input function on top
of fgets(), but it is needlessly complicated.
So regrettably there is no easy way of getting a line from the user in ISO
C.

It is easy as long as you stipulate that valid lines must not exceed a
certain size. fgets() will still handle valid input fine and invalid input
in a controlled way.

Lawrence
 
J

John Bode

Michael said:
Keith said:
Malcolm said:
I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).


scanf("%s", ptr);

will only read the first word (string of characters separated by whitespace)
into the bufer pointed to by ptr.
You can read a whole line with gets(). Unfortunately the function is flawed,
because the buffer will overrun, probably causing a crash, if the user types
in too many characters. fgets() is even worse if used incorrectly - input is
silently truncated. Why is that worse? Because wrong results are usually
worse than no results. However you can build a solid input function on top
of fgets(), but it is needlessly complicated.
So regrettably there is no easy way of getting a line from the user in ISO
C.


fgets() is worse than gets()?

Nonsense.

Well, in a way, it is: It is the closest you can get to a sensible
text input function but falls short, unnecessarily and nastily.
If you consider a function more broken which does not invoke UB
(and quite often segfaults to tell you where you went wrong)
instead of silently truncating and upsetting everything in a
hard-to-catch way, then you can arrive at this conclusion.
IMO, fgets() with sensible return values to communicate, say
EOF/Error/NoNewLineEncountered/NewLineEncountered, would be
quite alright.

Well, even though the function interface itself doesn't provide these
values, they can be tested for relatively easily:

if (fgets(buffer, sizeof buffer, stream))
{
if (strchr(buffer, '\n'))
{
/* NewLineEncountered */
}
else
{
/* NoNewLineEncountered */
}
}
else
{
if (feof(stream))
{
/* EOF */
}
else
{
/* Error */
}
}

I mean, The C Way is for the library to do ~90% of what you need it to,
and then fill in the rest by hand. No, I'm not bitter, really.

For all its flaws, fgets() has one chief advantage over gets() -- you
don't run the risk of crashing your program or opening a security hole
*every* time you call it.
 
M

Michael Mair

^^^
one "not" too many :-(
(and quite often segfaults to tell you where you went wrong)
instead of silently truncating and upsetting everything in a
hard-to-catch way, then you can arrive at this conclusion.

<snip>

Huh? UB nearly universally "[upsets] everything in a hard-to-catch
way". Even worse, it often results in security holes.

Well-defined but annoying behavior is certainly not worse, at least in
the sense of the word I am accustomed to.

I just tried to explain how one might regard fgets() as worse than
gets() -- and failed.
Personally, I do not use either and work with getc()- or fread()-based
input or fscanf() if I feel daring.
What I meant is that it is sometimes easier to find a gets() gone wild
than a fgets() treading down the semantics.
The original statement did not come from me but I understand the
sentiment behind it very well.


Cheers
Michael
 
M

Michael Mair

Chris said:
Keith said:
I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).

scanf("%s", ptr);

will only read the first word (string of characters separated by whitespace)
into the bufer pointed to by ptr.
You can read a whole line with gets(). Unfortunately the function is flawed,
because the buffer will overrun, probably causing a crash, if the user types
in too many characters. fgets() is even worse if used incorrectly - input is
silently truncated. Why is that worse? Because wrong results are usually
worse than no results. However you can build a solid input function on top
of fgets(), but it is needlessly complicated.
So regrettably there is no easy way of getting a line from the user in ISO
C.

fgets() is worse than gets()?

Nonsense.

Well, in a way, it is: It is the closest you can get to a sensible
text input function but falls short, unnecessarily and nastily.

OK, so it's not a perfect interface, lots of the C library isn't a
perfect interface. Whether it is 'necessary' to have had that interface
is a matter of opinion, but most of the I/O interface wasn't designed,
it "jest growed". It's certainly perfectly usable.

'Tis, for some values of "perfectly".
^^^
one "not" too many :-(
I have never had fgets() segfault, except when passing it invalid
parameters. How have you done it? If you give it a valid file pointer,
valid pointer to a data area and a correct length (no greater than the
size of the data area) then if it segfaults you have a faulty
implementation.

Umh, see above (one not too many) and <[email protected]>,
my reply to Mark F. Haigh.
I head gets() segfault in other people's code which was much easier
to find than fgets()-related problems.
fgets() doesn't 'truncate', it simply stops inputting when the buffer is
full. Doing "if (strchr(buffer, '\n'))" will detect whether the line
was complete at that point (strlen() would do as well). You can then
decide whether you want to discard the rest of the data, increase the
buffer size, or whatever. If you don't bother testing then your program
is broken, no more or less than if you ignore returned status.


All that information is available. You can call feof/ferror on the
input stream (fgets() will return NULL if it didn't get anything) and
you can test for newline as above.

Or of course you can write your own input function with the behaviour
you like, it's not hard (indeed, I've rewritten such functions many
times because it was faster than digging out the code I'd written
before).

Yep, and usually, getc() based input code is clearer than catching all
the indirect error returns of fgets().

Cheers
Michael
 
M

Michael Mair

John said:
Michael said:
Keith said:
I use scanf("%s", &first) in order to get the input to the variable first
(which is char first[]).

scanf("%s", ptr);

will only read the first word (string of characters separated by whitespace)
into the bufer pointed to by ptr.
You can read a whole line with gets(). Unfortunately the function is flawed,
because the buffer will overrun, probably causing a crash, if the user types
in too many characters. fgets() is even worse if used incorrectly - input is
silently truncated. Why is that worse? Because wrong results are usually
worse than no results. However you can build a solid input function on top
of fgets(), but it is needlessly complicated.
So regrettably there is no easy way of getting a line from the user in ISO
C.

fgets() is worse than gets()?

Nonsense.

Well, in a way, it is: It is the closest you can get to a sensible
text input function but falls short, unnecessarily and nastily.
If you consider a function more broken which does not invoke UB
(and quite often segfaults to tell you where you went wrong)
instead of silently truncating and upsetting everything in a
hard-to-catch way, then you can arrive at this conclusion.
IMO, fgets() with sensible return values to communicate, say
EOF/Error/NoNewLineEncountered/NewLineEncountered, would be
quite alright.

Well, even though the function interface itself doesn't provide these
values, they can be tested for relatively easily:

if (fgets(buffer, sizeof buffer, stream))
{
if (strchr(buffer, '\n'))
{
/* NewLineEncountered */
}
else
{
/* NoNewLineEncountered */
}
}
else
{
if (feof(stream))
{
/* EOF */
}
else
{
/* Error */
}
}

I mean, The C Way is for the library to do ~90% of what you need it to,
and then fill in the rest by hand. No, I'm not bitter, really.

For all its flaws, fgets() has one chief advantage over gets() -- you
don't run the risk of crashing your program or opening a security hole
*every* time you call it.

Thanks for writing it out. See my other two replies to see how my
explanation failed to make sense.
However, the above demonstrates why so many people use fgets() in
the wrong way :-/ As mentioned before: getc() produces clearer code.

Cheers
Michael
 
K

Keith Thompson

Michael Mair said:
I just tried to explain how one might regard fgets() as worse than
gets() -- and failed.
Personally, I do not use either and work with getc()- or fread()-based
input or fscanf() if I feel daring.
What I meant is that it is sometimes easier to find a gets() gone wild
than a fgets() treading down the semantics.
The original statement did not come from me but I understand the
sentiment behind it very well.

There are two separate issues here.

The first is that gets() is broken, and cannot be used safely.
It should be removed from the language (in my opinion, and in the
opinion of many others).

The second is that fgets() has some problems, and can be used either
correctly or incorrectly.

fgets() may be a problem, but gets() is certainly not the solution.
 
C

CBFalconer

Michael said:
John Bode wrote:
.... snip ... .... snip ...
However, the above demonstrates why so many people use fgets() in
the wrong way :-/ As mentioned before: getc() produces clearer code.

My ggets package uses fgets for actual input, but could just as
well use getc. In some systems the results may be more efficient,
depending primarily on whether getc is actually a macro operating
directoy on the stream buffer. However that is not likely to
matter in a function used primarily for interactive input. It
might well reduce the volume of library code needed to link.

To me ggets presents the right interface. It is simple, it always
gets complete lines, and the terminal '\n' is always stripped. Its
error return allows for malloc failure, completion, and the EOF or
error condition (which the user can separate if needed).

int ggets(char **line);
or
int fggets(char **line, FILE *f);
 
M

Mark F. Haigh

Keith Thompson wrote:

fgets() may be a problem, but gets() is certainly not the solution.

Well put. That'll go in the quotes file.


Mark F. Haigh
(e-mail address removed)
 
D

David Mathog

John said:
Well, even though the function interface itself doesn't provide these
values, they can be tested for relatively easily:

if (fgets(buffer, sizeof buffer, stream))
{
if (strchr(buffer, '\n'))

Sure that works but it's horribly inefficient. What if buffer
is 2M in length, why should the program have to (re)scan it
when fgets knew perfectly well that it truncated the buffer? Clearly
a sane replacement for fgets would return a status
value indicating that the truncation took place. I often
wonder just what the designer of fgets was thinking when he
(she?) chose the return value. Clearly a simple int
return value something like this would have worked much
better:
>=0 number of characters read (EOL character stripped)
-1 EOF
-2 Read Error
-3 Buffer Full
(or
N+1 Buffer Full, where N is the number of characters in the buffer)

Even more amazing to me is that subsequent C standards have not
introduced this "sfgets" (sane fgets) so that future C code
wouldn't be forever hobbled by the poor design choices made for fgets.

Regards,

David Mathog
(e-mail address removed)
 
C

CBFalconer

David said:
Sure that works but it's horribly inefficient. What if buffer
is 2M in length, why should the program have to (re)scan it
when fgets knew perfectly well that it truncated the buffer?
Clearly a sane replacement for fgets would return a status
value indicating that the truncation took place. I often
wonder just what the designer of fgets was thinking when he
(she?) chose the return value. Clearly a simple int
return value something like this would have worked much
better:

-1 EOF
-2 Read Error
-3 Buffer Full
(or
N+1 Buffer Full, where N is the number of characters in the
buffer)

Even more amazing to me is that subsequent C standards have not
introduced this "sfgets" (sane fgets) so that future C code
wouldn't be forever hobbled by the poor design choices made for
fgets.

Don't worry about it. Just get and use the portable public domain:

<http://cbfalconer.home.att.net/download/ggets.zip>
 
M

Michael Mair

CBFalconer said:
... snip ...


/* minor editing to emphasize 3 major possibilities - cbf */


... snip ...



My ggets package uses fgets for actual input, but could just as
well use getc. In some systems the results may be more efficient,
depending primarily on whether getc is actually a macro operating
directoy on the stream buffer. However that is not likely to
matter in a function used primarily for interactive input. It
might well reduce the volume of library code needed to link.

To me ggets presents the right interface. It is simple, it always
gets complete lines, and the terminal '\n' is always stripped. Its
error return allows for malloc failure, completion, and the EOF or
error condition (which the user can separate if needed).

int ggets(char **line);
or
int fggets(char **line, FILE *f);

To complete the advertisement:

<http://cbfalconer.home.att.net/download/ggets.zip>

It is certainly a nice, portable and available replacement.

Cheers
Michael
 

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

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top