fgets() and scanf() peculiarity

E

Eirik

Hey, all groovy C programmers,

I've read in the FAQ(question 12.18) about how applications skip calls to
(f)gets() after scanf() has been used. How can I avoid this? I know that I
can by putting the fgets() before the scanf(). However, this one is not
always suitable. Do you know of any other ways of avoiding this problem?

--
- Fordi det rotar til måten folk
vanlegvis les tekst på.
- Kvifor?
- Topp-posting.
- Kva er det verste du veit om
i elektronisk post og njus?
 
E

Eric Sosman

Eirik said:
Hey, all groovy C programmers,

I've read in the FAQ(question 12.18) about how applications skip calls to
(f)gets() after scanf() has been used. How can I avoid this? I know that I
can by putting the fgets() before the scanf(). However, this one is not
always suitable. Do you know of any other ways of avoiding this problem?

One way is to use fgets() -- not gets()! -- to read
a whole line into a character array, then use sscanf()
to pick it apart.
 
A

Alan Balmer

Hey, all groovy C programmers,

I've read in the FAQ(question 12.18) about how applications skip calls to
(f)gets() after scanf() has been used. How can I avoid this? I know that I
can by putting the fgets() before the scanf(). However, this one is not
always suitable. Do you know of any other ways of avoiding this problem?

Read it again. Notice that it doesn't say that the call to gets() is
actually skipped, only that it may appear so. Understand why this
happens, and you'll have your answer.
 
E

Eirik

Hey, all groovy C programmers,
One way is to use fgets() -- not gets()! -- to read
a whole line into a character array, then use sscanf()
to pick it apart.

Can you explain this with a piece of code?
 
I

Irrwahn Grausewitz

Eirik said:
Hey, all groovy C programmers,

I've read in the FAQ(question 12.18) about how applications skip calls to
(f)gets() after scanf() has been used. How can I avoid this? I know that I
can by putting the fgets() before the scanf(). However, this one is not
always suitable. Do you know of any other ways of avoiding this problem?

The call to fgets isn't skipped, but returns immediately when it hits
a newline character that was left in the input stream by a previous
invokation of scanf. One way to avoid this is to 'drain' the input
buffer before fgets is called:

int drain_stdin( void )
{
int c;
while ( ( c = getchar() ) != '\n' && c != EOF )
;
return c;
}

.....
.....
scanf( .... );
if ( drain_stdin() != EOF )
fgets( .... );
.....
.....

Or, you can replace the call to scanf with fgets to read an entire
line of input and then parse it. (Look up the sscanf, strto*, strchr,
strcspn, strpbrk, strrchr, strspn, strstr, strtok, is*, strncpy, ...
functions in your library reference manual.)

Regards
 
E

Eric Sosman

Eirik said:
Can you explain this with a piece of code?

char buffer[BIG_ENOUGH];
int hh, mm, dd;

if (fgets(buffer, sizeof buffer, stdin) == NULL) {
/* end-of-file or error: do something */
}
if (sscanf(buffer, "%d:%d:%d", &hh, &mm, &ss) != 3) {
/* something strange in the input: do something */
}
/* Three numbers have been retrieved from one input
* line, and the next fgets() will get a fresh line
*/

Fancier code would check whether fgets() actually read a
complete line; if `BIG_ENOUGH' is too small, fgets() will
stop prematurely. Corrective action might be to ignore the
rest of the line, or to expand a dynamically-allocated
`buffer' and keep on reading.
 
R

Richard Heathfield

Eric said:
Fancier code would check whether fgets() actually read a
complete line; if 'BIG_ENOUGH' is too small, fgets() will
stop prematurely.

BIG_ENOUGH is always big enough. Just avoid TOO_MUCH, because TOO_MUCH is
never enough (cf Steinman, 1981).
 

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,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top