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

M

moosdau

my code:
do
{
printf("please input the dividend and the divisor.\n");
if(!scanf("%d%d",&dend,&dor))
{
temp1=1;
fflush(stdin);
}
else
temp1=0;
}while(temp1==1);

it seems that it only depend on the first number it read.
if I input " a 32 ", it could know there is a error,
but if I input " 32 a ",
it accept that.

thanks in advance.
 
T

tmp123

moosdau said:
my code:
do
{
printf("please input the dividend and the divisor.\n");
if(!scanf("%d%d",&dend,&dor))
{
temp1=1;
fflush(stdin);
}
else
temp1=0;
}while(temp1==1);

it seems that it only depend on the first number it read.
if I input " a 32 ", it could know there is a error,
but if I input " 32 a ",
it accept that.

thanks in advance.


Hi,

In "man scanf", I suggest you to read chapter "return values".

Kind regards.
 
M

moosdau

do you mean the linux os?
but I'm using windows,so I can't use the "man" command.
could you tell me plz?
 
?

=?ISO-8859-1?Q?=22Nils_O=2E_Sel=E5sdal=22?=

moosdau said:
do you mean the linux os?
but I'm using windows,so I can't use the "man" command.
could you tell me plz?
For windows, look up the function at
http://msdn.microsoft.com/

(A little hint is that scanf returns the nr of successfully
assigned items)
 
K

Keith Thompson

moosdau said:
my code:
do
{
printf("please input the dividend and the divisor.\n");
if(!scanf("%d%d",&dend,&dor))
{
temp1=1;
fflush(stdin);
}
else
temp1=0;
}while(temp1==1);

it seems that it only depend on the first number it read.
if I input " a 32 ", it could know there is a error,
but if I input " 32 a ",
it accept that.

scanf() returns the number of items assigned. If you give it " 32 a ",
it will assign 32 to dend and fail to assign a value to dor; scanf()
will then return 1. If you want to assign both values, you need to
check whether scanf() returned 2.

You should pick a better name than "temp1". The simplest thing to do
is to assign the result of scan() to a variable, and test the value
of that variable. Pseudo-code follows:

do {
printf("...\n");
items_read = scanf(...);
} while (items_read != 2);

Don't use fflush(stdin). The fflush() function is defined only for
output streams.

scanf() can be very tricky, it can leave unread garbage in your input
stream, and it can be difficult to figure out just what it's doing. A
better approach is to use fgets() to read an entire line, then use
sscanf() to get information from the line you've read.
 
T

tmp123

moosdau said:
do you mean the linux os?
but I'm using windows,so I can't use the "man" command.
could you tell me plz?

Mna pages are also available in hundreds of www servers.
 
C

Chuck F.

moosdau said:
>
do you mean the linux os? but I'm using windows,so I can't use
the "man" command. could you tell me plz?

Include context. Without it we have no idea what you mean. See my
sig, and the reference therein, for how to do this.

On Windoze you are probably either using Microsoft VC, or some port
of GCC. With the gcc versions you very likely have info (the
command) available, especially if you have installed DJGPP or
Cygwin. Otherwise the VC help system will probably lead you to a
discussion of scanf.

On this windoze system the command:

C>info libc alpha scanf

brings up a screen that begins as follows:

scanf
=====

Syntax
------

#include <stdio.h>

int scanf(const char *format, ...);

Description
-----------

This function scans formatted text from `stdin' and stores it in
the variables pointed to by the arguments. *Note scanf::.
.... and so forth ...

--
"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/>
 
M

moosdau

Keith said:
scanf() returns the number of items assigned. If you give it " 32 a ",
it will assign 32 to dend and fail to assign a value to dor; scanf()
will then return 1. If you want to assign both values, you need to
check whether scanf() returned 2.

You should pick a better name than "temp1". The simplest thing to do

sorry,because I copied it from a long code,
if I named every variant with its meaning, there must be too many
temporary variants.
so ......
is to assign the result of scan() to a variable, and test the value
of that variable. Pseudo-code follows:

do {
printf("...\n");
items_read = scanf(...);
} while (items_read != 2);

Don't use fflush(stdin). The fflush() function is defined only for
output streams.


Thanks very much!!
but I don't know very clearly why shouldn't I use the fflush function.
if there is not any usable data in the input stream,
could I use it to clear the input stream?
if not , could you please tell me why?

scanf() can be very tricky, it can leave unread garbage in your input
stream, and it can be difficult to figure out just what it's doing. A
better approach is to use fgets() to read an entire line, then use
sscanf() to get information from the line you've read.

thanks for your suggestion!

 
R

Richard Heathfield

moosdau said:

[...] I don't know very clearly why shouldn't I use the fflush function.
if there is not any usable data in the input stream,

Because fflush's behaviour is only defined for streams open for output or
update.
could I use it to clear the input stream?

Not as far as the C language is concerned, no.
if not , could you please tell me why?

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.

If you want to discard from stdin everything up to and including a
particular character, you can use this function:

#include <stdio.h>

int DiscardFromStream(FILE *fp, int lim)
{
int ch;
while((ch = getc(fp)) != lim && ch != EOF)
{
continue;
}
return ch == EOF;
}

/* example usage */
int main(void)
{
int ch;
puts("Type a letter, and press ENTER.");
ch = getchar();
if(0 == DiscardFromStream(stdin, '\n'))
{
printf("You pressed %c\n", ch);
puts("Type another letter, and press ENTER.");
ch = getchar();
if(0 == DiscardFromStream(stdin, '\n'))
{
printf("You pressed %c\n", ch);
}
}
return 0;
}
 
P

pemo

Thanks very much!!
but I don't know very clearly why shouldn't I use the fflush function.
if there is not any usable data in the input stream,
could I use it to clear the input stream?
if not , could you please tell me why?

There's no easy way to purge stdin, esp when it's already potentially empty,
i.e., most [all that I can think of right now] std functions that could
potentially test for this will *wait* if stdin is empty, e.g., getchar,
scanf, gets, fgets, feof, ... it's a toughie, and I would suggest that, *if*
your code need *not* be portable, and *if* your implementation of fflush
works on stdin ok, well, you should perhaps stick with it then! I'll get
flamed for suggesting this of course - or - better still, someone will come
up with a portable way to flush stdin ;-)
 
R

Richard Heathfield

pemo said:
I would suggest
that, *if* your code need *not* be portable, and *if* your implementation
of fflush works on stdin ok, well, you should perhaps stick with it then!

Bad advice. Better to avoid the problem completely, which is trivial.
I'll get flamed for suggesting this of course - or - better still,
someone will come up with a portable way to flush stdin ;-)

That doesn't make sense, since flushing is not something we do to input.
I've already posted a portable way to discard characters from stdin until a
delimiter is encountered.

I never, ever have to solve this problem in my own code, because I capture
all text input a line at a time. Why don't you just do that too?
 
F

Flash Gordon

moosdau said:
sorry,because I copied it from a long code,
if I named every variant with its meaning, there must be too many
temporary variants.
so ......

If that is a problem it sounds like your function is too long and it
should be split in to multiple functions.
Thanks very much!!
but I don't know very clearly why shouldn't I use the fflush function.
if there is not any usable data in the input stream,
could I use it to clear the input stream?
if not , could you please tell me why?

<snip>

You should not use it in input streams because it is not defined. That
means anything can happen, from what you expect to your computer growing
arms and hands and punching you in the nose. More likely effects, if it
appears to work on your current system, are you doing an update and it
suddenly not doing what you expect but either doing nothing or giving
some kind of access violation error.

If you want to clear the input stream you have to decide on what you
mean, possibly reading the rest of the line, and do that. If you really
do want to throw away anything the user has typed so far (what if input
is piped in from a file though!) and get the next thing the user types,
then you can't do that in standard C and will have to use system
specific routines.
 
P

pemo

Richard Heathfield said:
pemo said:


Bad advice. Better to avoid the problem completely, which is trivial.

But, I'd wager, not as trivial as scanf("%d", &n); fflush(stdin); if it were
fully supported? Aren't you talkig about something like this?

char buffer[100];

int n;

if(fgets(buffer, sizeof(buffer), stdin))
{
if(sscanf(buffer, "%d", &n))
{
printf("w00t, we read an int! (%d)\n", n);
}
}
That doesn't make sense, since flushing is not something we do to input.
I've already posted a portable way to discard characters from stdin until
a
delimiter is encountered.

I know what you mean [the 'logic' of it], but as this scanf type question is
often asked here, it obviously does make sense in that context - e.g., since
scanf is provided, and as that function is invariably the function that's
used in tutorials, it *would* make sense [surely?] to have some way of
removing any unread characters held in the stdin stream?
I never, ever have to solve this problem in my own code, because I capture
all text input a line at a time. Why don't you just do that too?

Sure, it's a good way to handle the problem, but see my wager.
 
C

Chuck F.

pemo said:
.... snip ...

I know what you mean [the 'logic' of it], but as this scanf type
question is often asked here, it obviously does make sense in
that context - e.g., since scanf is provided, and as that
function is invariably the function that's used in tutorials, it

Not in good tutorials.
*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;
}

--
"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/>
 
P

pemo

Chuck F. said:
pemo said:
... snip ...

I know what you mean [the 'logic' of it], but as this scanf type
question is often asked here, it obviously does make sense in
that context - e.g., since scanf is provided, and as that
function is invariably the function that's used in tutorials, it

Not in good tutorials.

I didn't think that there were any????
*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;
}
 
E

Emmanuel Delahaye

moosdau a écrit :
do you mean the linux os?
but I'm using windows,so I can't use the "man" command.
could you tell me plz?

google 'man <item>' works too...
 
E

Emmanuel Delahaye

pemo a écrit :
There's no easy way to purge stdin, esp when it's already potentially empty,
i.e., most [all that I can think of right now] std functions that could
potentially test for this will *wait* if stdin is empty, e.g., getchar,
scanf, gets, fgets, feof, ... it's a toughie, and I would suggest that, *if*
your code need *not* be portable, and *if* your implementation of fflush
works on stdin ok, well, you should perhaps stick with it then! I'll get
flamed for suggesting this of course - or - better still, someone will come
up with a portable way to flush stdin ;-)

It's a design issue. Using the proper input function in the proper way
avoids these problems of pending characters. The canonic way :

char line[PROPER_SIZE];

if (fgets(line, sizeof line, stdin) != NULL)
{
/* search */
char *p = strchr(line, '\n');
if (p != NULL)
{
/* kill */
*p = 0;
}
else
{
/* purge */
int c;
while ((c = fgetc(stdin)) != '\n' && c != EOF)
{
}
}
}

stick this into some getline() function of your own, add the required
headers (<stdio.h> and <string.h>) and you have a decent input function
for life.
 
K

Keith Thompson

pemo said:
Would this be acceptable for stdin?

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

return;
}

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

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.
 
P

pemo

Keith Thompson said:
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.
 
E

Emmanuel Delahaye

pemo a écrit :
Would this be acceptable for stdin?

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

return;
}

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

Note that the 'return;' is useless.
 

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,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top