how to check the scanf function if it will read more than one number

F

Flash Gordon

pemo said:
Keith Thompson said:
pemo said:
news:[email protected]... [...]
We do. My variant of Richards function is:

int flushln(FILE *f)
{
int ch;

do {
ch = getc(f);
} while (('\n' != ch) && (EOF != ch));
return ch;
}
Would this be acceptable for stdin?

void flushstdin(void)
{
while(getchar() != '\n')
;

return;
}
What if getchar() returns EOF before returning '\n'?

Surely, if there's a \n in the buffer, getchar won't return EOF?

If there's not a \n in the buffer, I can see that testing for EOF might be a
good idea.

Yes, but how do you know if there is (or ever will be) a \n in the input
buffer? Some systems allow the last line of a file to not be terminated
by a line feed, and some systems allow you to redirect a file to
standard input. Combine those two and you have an obvious mechanism for
reaching the end of file before reaching a \n even with stdin.
 
K

Keith Thompson

pemo said:
Surely, if there's a \n in the buffer, getchar won't return EOF?

If there's not a \n in the buffer, I can see that testing for EOF might be a
good idea.

So perhaps you should do something like this:

void flushstdin(void)
{
if (theres_a_newline_in_the_buffer()) {
while(getchar() != '\n')
;
}
else {
int c;
while(c = getchar(), c != '\n' && c != EOF)
;
}
}

Implementing the theres_a_newline_in_the_buffer() function in portable
C is left as an exercise. If you can't think of a way to do it,
perhaps you should just test for EOF.

To answer my own question from upthread, if you reach EOF on stdin
before seeing a '\n' character, your flushstdin() function becomes an
infinite loop; getchar() will repeatedly return EOF, and the condition
will never allow the loop to terminate.
 
K

Keith Thompson

Emmanuel Delahaye said:
pemo a écrit :

No, because stdin can be redirected from a file. EOF must be checked too.

It's not just because stdin can be redirected from a file. EOF can
occur before the end of a line, at least on some systems. (On
Unix-like systems, if you're reading from the keyboard, hitting
control-D twice in the middle of a line generally does this.)
 
C

Chuck F.

pemo said:
.... snip ...
*would* make sense [surely?] to have some way of removing any
unread characters held in the stdin stream?

We do. My variant of Richards function is:

int flushln(FILE *f)
{
int ch;

do {
ch = getc(f);
} while (('\n' != ch) && (EOF != ch));
return ch;
}

Would this be acceptable for stdin?

void flushstdin(void)
{
while(getchar() != '\n')
;

return;
}

No, it doesn't handle EOF. However, if you have flushln available
you can write:

#define flushstdin flushln(stdin)

although I don't know why you would bother.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
 
C

Chuck F.

Keith said:
.... snip ...

Note that there are two different things being discussed here.
One, which is easily implementable in standard C, is discarding
all the remaining characters in a line. The other, which can't
be done in standard C, is discarding all typed characters that
haven't been processed yet, i.e., flushing the typeahead buffer.

I think the former is what the OP really wants.
True. However, lacking the latter, use of the former requires that
one keep track of what routines flush to end of line. For example,
fgets doesn't necessarily, which can make usage awkward. gets (to
Newbies - which is never to be used) does, whilst destroying your
system. The scanf family doesn't, because they put the field
terminating char back in the input stream. My ggets does. The
various bufferless input routines I have published here don't (they
push back the terminating char).

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
 
K

Keith Thompson

Richard Heathfield said:
Emmanuel Delahaye said:


Only to the compiler.

Implying that it's useful to the reader? This was a "return;" at the
very end of a void function; how is that useful at all?
 
M

Moosdau

Richard said:
For the same reason that pressing the handle on your toilet will not get rid
of the water waiting in your sink's tap (or faucet, if you're on that side
of the pond). Flushing is something we do to output, not to input.

thanks.
but what I want to know is the "actual" reason,
not a "logical" one.
e.g.
void f( int*p )
{
if (p->num)
do something;
}
when this function is running, there will be an error.
if I don't know the reason,what I want to know is :
if p is a NULL pointer, p->num will cause the error.

so ,the fflush function works very well on my computer now,
If it cause a potential danger,
I want to know what is it, and what is the condition.
if possible, an example is the best. :)

thanks for all !
 
P

Peter Nilsson

Moosdau said:
thanks.
but what I want to know is the "actual" reason,
not a "logical" one.

The "actual" reason is that the C language standard does not define
a behaviour for fflush() on an input stream.
e.g.
void f( int*p )
{
if (p->num)
do something;
}
when this function is running, there will be an error.
if I don't know the reason,what I want to know is :
if p is a NULL pointer, p->num will cause the error.

so ,the fflush function works very well on my computer now,

Your implementation probably defines a behaviour fflush on
input streams. It would do so as an extension. That extension
is not topical in comp.lang.c.
If it cause a potential danger,
I want to know what is it, and what is the condition.
if possible, an example is the best. :)

void g(FILE *fp)
{
fflush(fp);
}

If fp is purely an input stream, this invokes undefined behaviour. In
other
words, it's as dangerous as f() above.
 
M

Moosdau

Peter said:
Your implementation probably defines a behaviour fflush on
input streams. It would do so as an extension. That extension
is not topical in comp.lang.c.
it do be that.
I think I've already known the answer.
the below is I copied from MSDN:

The fflush function flushes a stream. If the file associated with
stream is open for output, fflush writes to that file the contents of
the buffer associated with the stream.
If the stream is open for input, fflush clears the contents of the
buffer.

Example
// crt_fflush.c
#include <stdio.h>
#include <conio.h>

int main( void )
{
int integer;
char string[81];

/* Read each word as a string. */
printf( "Enter a sentence of four words with scanf: " );
for( integer = 0; integer < 4; integer++ )
{
scanf( "%s", string );
// Security caution!
// Beware allowing user to enter data directly into a buffer
// without checking for buffer overrun possiblity.
printf( "%s\n", string );
}

/* You must flush the input buffer before using gets. */
fflush( stdin ); // fflush on input stream is an extension to the
C standard
printf( "Enter the same sentence with gets: " );
gets( string );
printf( "%s\n", string );
}
Input
This is a test
This is a test
Sample Output
Enter a sentence of four words with scanf: This is a test
This
is
a
test
Enter the same sentence with gets: This is a test
This is a test


then I know,I shouldn't use fflush(stdin) except in VC.
but in VC, it is safe.

thanks to all again !
 
K

Keith Thompson

Moosdau said:
Peter said:
Your implementation probably defines a behaviour fflush on
input streams. It would do so as an extension. That extension
is not topical in comp.lang.c.
it do be that.
I think I've already known the answer.
the below is I copied from MSDN:

The fflush function flushes a stream. If the file associated with
stream is open for output, fflush writes to that file the contents of
the buffer associated with the stream.
If the stream is open for input, fflush clears the contents of the
buffer.

Example
// crt_fflush.c
#include <stdio.h>
#include <conio.h>

int main( void )
{ [snip]
int integer;
char string[81];

/* Read each word as a string. */
printf( "Enter a sentence of four words with scanf: " );
for( integer = 0; integer < 4; integer++ )
{
scanf( "%s", string );
// Security caution!
// Beware allowing user to enter data directly into a buffer
// without checking for buffer overrun possiblity.
printf( "%s\n", string );
}

So MSDN shows an example of a possible buffer overflow and provides a
comment that doesn't give you a clue how to avoid it.
/* You must flush the input buffer before using gets. */
fflush( stdin ); // fflush on input stream is an extension to the
C standard
printf( "Enter the same sentence with gets: " );
gets( string );
printf( "%s\n", string );
}

And the example uses gets() without even warning that it's unsafe.
For nearly all practical purposes, gets() cannot be used safely.

[snip]
then I know,I shouldn't use fflush(stdin) except in VC.
but in VC, it is safe.

Here's a better idea: don't use fflush(stdin) at all. Second best:
don't use fflush(stdin) unless you're certain your code will never be
ported to an implementation that doesn't support it.
 
C

Chuck F.

Moosdau said:
it do be that. I think I've already known the answer. the below
is I copied from MSDN:

The fflush function flushes a stream. If the file associated
with stream is open for output, fflush writes to that file the
contents of the buffer associated with the stream. If the stream
is open for input, fflush clears the contents of the buffer.

Which is typical of Microsoft ignoring standards. They encourage
people to write non-standard code, which is then tied to their own
systems, and thus increases their income.

For general systems where what, if anything, functions as an input
mechanism is not defined, the C language has no control. There is
no way it can possibly anticipate the arrival of input. Thus input
routines, when called, have to await actual input before returning.
There may not be any input buffer, and if there is there is no
defined way of interrogating it for non-emptyness. Thus the
language cannot insist on fflush functioning on input streams, and
any attempt to so do makes the program non-portable.

--
"If you want to post a followup via groups.google.com, don't use
the broken "Reply" link at the bottom of the article. Click on
"show options" at the top of the article, then click on the
"Reply" at the bottom of the article headers." - Keith Thompson
More details at: <http://cfaj.freeshell.org/google/>
 
R

Richard Heathfield

Keith Thompson said:
Implying that it's useful to the reader? This was a "return;" at the
very end of a void function; how is that useful at all?

It's a tiny, tiny advantage, but an advantage nonetheless, at least to me.

My functions generally have one entry point and one exit point. The exit
point is the return statement. So I'm accustomed to writing one in each
function, generally as the /last/ line typed in the first cut of the
function. (The closing brace is typed immediately after the opening brace,
to save me from encountering pairing-up nonsenses later.)

So, when I see a function with no return statement, I find myself thinking
"is this function finished yet?"
 
R

Richard Heathfield

Moosdau said:
thanks.
but what I want to know is the "actual" reason,
not a "logical" one.

I gave you both in my previous reply; as well as the text you quote above, I
also wrote: "Because fflush's behaviour is only defined for streams open
for output or update." That is the actual reason.
if p is a NULL pointer, p->num will cause the error.

The C Standard assures us the code is wrong to dereference a null pointer,
but it does not specify that there will be "an error". It only says the
behaviour is undefined.
so ,the fflush function works very well on my computer now,

That's nice.
If it cause a potential danger,

If you use it in a way it was never intended to be used, that's a potential
danger.
I want to know what is it, and what is the condition.
if possible, an example is the best. :)

Okay, here's an example. Let's say you choose to use fflush(stdin) because
Microsoft say it's okay, and then in five years time Microsoft goes bust
and everyone starts using Macs instead, and you port your code to a Mac and
suddenly it stops working, and the reason it stops working is that you
thought "MSDN" was an acceptable substitute for "The ISO C Standard" and
wrote your code on that basis. Well, if you want to create unnecessary
portability headaches for yourself, that's your lookout.

The irony is that this is such a pointless discussion, since you simply
don't /need/ to "flush" input. Well, I don't, anyway, and I do a /lot/ of
text processing in C.
 
M

Moosdau

Richard said:
Okay, here's an example. Let's say you choose to use fflush(stdin) because
Microsoft say it's okay, and then in five years time Microsoft goes bust
and everyone starts using Macs instead, and you port your code to a Mac and
suddenly it stops working, and the reason it stops working is that you
thought "MSDN" was an acceptable substitute for "The ISO C Standard" and
wrote your code on that basis. Well, if you want to create unnecessary
portability headaches for yourself, that's your lookout.

haha !
The irony is that this is such a pointless discussion, since you simply
don't /need/ to "flush" input. Well, I don't, anyway, and I do a /lot/ of
text processing in C.

but ,seriously , if the ISO can provide a compiler that obey it's
standard absolutely,
how cool will that be!
 
D

Dik T. Winter

>
> thanks.
> but what I want to know is the "actual" reason,
> not a "logical" one.

It is not well-defined in general what flushing the input stream means.
Especially when you are connected through a network. Does it mean
discarding all input that has arrived at the computer where the
program is running? Does it mean discarding also all input that is
still somewhere on the way on the network? And if so how does the
system know what was already on the way when fflush was called and
what was not yet on the way?
 
P

pemo

Keith Thompson said:
So perhaps you should do something like this:

void flushstdin(void)
{
if (theres_a_newline_in_the_buffer()) {
while(getchar() != '\n')
;
}
else {
int c;
while(c = getchar(), c != '\n' && c != EOF)
;
}
}

Implementing the theres_a_newline_in_the_buffer() function in portable
C is left as an exercise. If you can't think of a way to do it,
perhaps you should just test for EOF.

To answer my own question from upthread, if you reach EOF on stdin
before seeing a '\n' character, your flushstdin() function becomes an
infinite loop; getchar() will repeatedly return EOF, and the condition
will never allow the loop to terminate.

Ok, point taken.
 
P

pemo

Richard Heathfield said:
Keith Thompson said:


It's a tiny, tiny advantage, but an advantage nonetheless, at least to me.

My functions generally have one entry point and one exit point. The exit
point is the return statement. So I'm accustomed to writing one in each
function, generally as the /last/ line typed in the first cut of the
function. (The closing brace is typed immediately after the opening brace,
to save me from encountering pairing-up nonsenses later.)

So, when I see a function with no return statement, I find myself thinking
"is this function finished yet?"

It's the same with me - plus - [and it's a similar point] I also have a
personal problem with being as explicit as possible - in that I always try
to be!
 

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
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top