By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,559 Members | 1,154 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,559 IT Pros & Developers. It's quick & easy.

using scanf() in while loop

P: n/a
Hello,

I used scanf() in a while loop, which ensures that user input is
valid (must be an integer no greater than 21 or less than 3).
If user enters a number out of the range, or enters non-number,
he/she will be asked to retry.

/* start */

int n;

while(1){
printf("Please enter an integer (3 <= x <= 21): \n");
if(scanf("%d", &n) && (n >= 3) && (n <= 21)){
return n;
}
printf("The input must be a number within the (3, 21) range,
inclusive. Please retry.\n"); //Point A
}

/* End */

In the above code, the first condition (scanf("%d", &n))
tests whether user inputs a number. In my tests, since
the format specifier is %d, my take is that if user enters
anything other than an integer, scanf() will not modify n,
and will by itself return 0 indicating reading data has failed
as a result of type mismatch.

My problem is that when user inputs something other than
an integer, the scanf() never runs again, and this while loop
continues indefinitely.

Weirdly, if I input an integer out of the (3,21) boundary,
it runs correctly and re-prompts me for a new value.

Any opinion is welcome. Thanks in advance

Mar 1 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
obdict wrote:
Hello,

I used scanf() in a while loop, which ensures that user input is
valid (must be an integer no greater than 21 or less than 3).
If user enters a number out of the range, or enters non-number,
he/she will be asked to retry.

/* start */

int n;

while(1){
printf("Please enter an integer (3 <= x <= 21): \n");
if(scanf("%d", &n) && (n >= 3) && (n <= 21)){
return n;
}
printf("The input must be a number within the (3, 21) range,
inclusive. Please retry.\n"); //Point A
}

/* End */

In the above code, the first condition (scanf("%d", &n))
tests whether user inputs a number. In my tests, since
the format specifier is %d, my take is that if user enters
anything other than an integer, scanf() will not modify n,
and will by itself return 0 indicating reading data has failed
as a result of type mismatch.

My problem is that when user inputs something other than
an integer, the scanf() never runs again, and this while loop
continues indefinitely.
scanf() in fact does run again. The problem is that it sees data that
doesn't match your format string sitting on stdin, and thus returns
without touching it. You never take this data off the stream, and so
scanf() just keeps failing. To get around this, one solution is to read
the garbage data off of stdin:

int ch;
while((ch = getchar()) != '\n' && ch != EOF);

Although a better solution may be to not use scanf() at all. You should
also change your scanf() comparison, perhaps to == 1. If scanf() fails
because of end of file, it will return EOF which is negative, and your
current program will interpret this as a successful read.

Hope that helps,

--John

Weirdly, if I input an integer out of the (3,21) boundary,
it runs correctly and re-prompts me for a new value.

Any opinion is welcome. Thanks in advance


Mar 1 '06 #2

P: n/a
That really helped. Thanks a lot, John!

Mar 1 '06 #3

P: n/a
In my view writing such code is not usefull at all. It is consfusing
as well as incorrect. So it is better to devide the range checking and
user input for better clarity of the logic. Though it is always your
wish. Also a character is an number if you see its Ascii equivalent. So
the logic you want to have it invalid in the case of character also.

Mar 1 '06 #4

P: n/a

ab*********@gmail.com wrote:
In my view writing such code is not usefull at all. It is consfusing
as well as incorrect.
What code? I see no code, and no code is correct code.
So it is better to devide the range checking and
user input for better clarity of the logic.
Indeed, but how is this related to C?
Also a character is an number if you see its Ascii equivalent.
No it is not, at least not in C. And what about EBCDIC?
So
the logic you want to have it invalid in the case of character also.


Now I'm really confused.

Advice (do follow it in this group):

- quote what and who you're replying to (if using Google, click on Show
Options, and then on Reply that appears below the headers)
- don't top post
- stay on topic (which is Standard C as defined by ISO)

--
BR, Vladimir

Mar 1 '06 #5

P: n/a

"obdict" <ha******@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...
Hello,

I used scanf() in a while loop, which ensures that user input is
valid (must be an integer no greater than 21 or less than 3).
If user enters a number out of the range, or enters non-number,
he/she will be asked to retry.

/* start */

int n;

while(1){
printf("Please enter an integer (3 <= x <= 21): \n");
if(scanf("%d", &n) && (n >= 3) && (n <= 21)){
return n;
}
printf("The input must be a number within the (3, 21) range,
inclusive. Please retry.\n"); //Point A
}

/* End */

In the above code, the first condition (scanf("%d", &n))
tests whether user inputs a number. In my tests, since
the format specifier is %d, my take is that if user enters
anything other than an integer, scanf() will not modify n,
and will by itself return 0 indicating reading data has failed
as a result of type mismatch.
Not true. For example, if the user enters "123xyz", n will be assigned a
value of 123, the input scan will stop when the "x" is encountered and scanf
will return a value of 3. Subsequent scanf will all fail, each time trying
to read "x".

Best bet is not to use scanf for input. Use fgets instead.

My problem is that when user inputs something other than
an integer, the scanf() never runs again, and this while loop
continues indefinitely.

Weirdly, if I input an integer out of the (3,21) boundary,
it runs correctly and re-prompts me for a new value.

Any opinion is welcome. Thanks in advance


--
Fred L. Kleinschmidt
Boeing Associate Technical Fellow
Technical Architect, Software Reuse Project
Mar 1 '06 #6

P: n/a
Fred Kleinschmidt wrote:
"obdict" <ha******@gmail.com> wrote in message
news:11**********************@i39g2000cwa.googlegr oups.com...

while(1){
printf("Please enter an integer (3 <= x <= 21): \n");
if(scanf("%d", &n) && (n >= 3) && (n <= 21)){
return n;
}
printf("The input must be a number within the (3, 21) range,
inclusive. Please retry.\n"); //Point A
}
For example, if the user enters "123xyz", n will be assigned a
value of 123, the input scan will stop when the "x" is encountered and scanf

^^^^^ will return a value of 3. Subsequent scanf will all fail, each time trying ^^^^^^^^^^^^^^^^^^^^^^^^ to read "x".


Not exactly true either :)

<quote src="man 3 scanf">
RETURN VALUE
[...] If an error or end-of-file occurs after conversion has
begun, the number of conversions which were successfully
completed is returned.
</quote>
tmp$ cat foo.c
#include <stdio.h>

int main(void) {
int m, n=0;
m = scanf("%d", &n);
printf("Value read: %d\n", n);
printf("Value returned: %d\n", m);
return 0;
}

tmp$ gcc -W -Wall -Werror -std=c89 -pedantic -O2 foo.c -ofoo
tmp$ echo "123xyz" | ./foo
Value read: 123
Value returned: 1

--
If you're posting through Google read <http://cfaj.freeshell.org/google>
Mar 2 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.