Validating keyboard input

B

bildad

The following 'book example' of validating input seems to be incomplete.
Since it is a beginner's book it may be intentional for simplicity. But
I would like to know how to make this program work for all invalid
input. Just for example, if user inputs 'abc' an error is caught, but if
user inputs '432' the program hangs. Any clarification appreciated.

Thanks,

Bill


#include <stdio.h>

int main(void)
{
float temp_i, temp_o;
char which_i, which_o;
char junk;

printf("Enter a temperature and indicate\n");
printf("if it's Fahrenheit or Celsius [##.# C/F]: ");
if (scanf("%f %c", &temp_i, which_i) == 2)
{
switch (which_i)
{
case 'C':
case 'c':
temp_o = (temp_i * (9.0/5.0)) + 32;
which_o = 'F';
break;

case 'F':
case 'f':
temp_o = (temp_i - 32) * (5.0/9.0);
which_o = 'C';
break;

default:
which_o = 0;
break;
}
if (which_o)
{
printf("%0.1f %c is %0.1f %c.\n",
temp_i, which_i, temp_o, which_o);
}
else
{
printf("You failed to enter C or F.\n");
}
}
else
{
printf("You failed to use the proper syntax.\n");
}

do {
junk = getchar();
} while (junk != '\n');

getchar();

return 0;
}
 
M

Malcolm

bildad said:
The following 'book example' of validating input seems to be incomplete.
Since it is a beginner's book it may be intentional for simplicity. But I
would like to know how to make this program work for all invalid input.
Just for example, if user inputs 'abc' an error is caught, but if user
inputs '432' the program hangs. Any clarification appreciated.

Thanks,

Bill


#include <stdio.h>

int main(void)
{
float temp_i, temp_o;
char which_i, which_o;
char junk;

printf("Enter a temperature and indicate\n");
printf("if it's Fahrenheit or Celsius [##.# C/F]: ");
if (scanf("%f %c", &temp_i, which_i) == 2)
{
switch (which_i)
{
case 'C':
case 'c':
temp_o = (temp_i * (9.0/5.0)) + 32;
which_o = 'F';
break;

case 'F':
case 'f':
temp_o = (temp_i - 32) * (5.0/9.0);
which_o = 'C';
break;

default:
which_o = 0;
break;
}
if (which_o)
{
printf("%0.1f %c is %0.1f %c.\n",
temp_i, which_i, temp_o, which_o);
}
else
{
printf("You failed to enter C or F.\n");
}
}
else
{
printf("You failed to use the proper syntax.\n");
}

do {
junk = getchar();
} while (junk != '\n');

getchar();

return 0;
}

The problem is that scanf() eats whitespace, so the newline is consumed if
you enter a valid number, but not if you enter alphabetical characters
(because the function stalls on the first non-digit).

Then the program hits the getchar() lines, because only one field has been
converted. I suspect it won't hang if you enter a few characters.

It's not well written, but scanf() is a hard function to use in a solid
fashion. In production code you would probably call a line gobbling function
(fgets has its own problems) and then use sscanf().
 
K

Keith Thompson

bildad said:
The following 'book example' of validating input seems to be
incomplete. Since it is a beginner's book it may be intentional for
simplicity. But I would like to know how to make this program work for
all invalid input. Just for example, if user inputs 'abc' an error is
caught, but if user inputs '432' the program hangs. Any clarification
appreciated.

It doesn't really hang; it just waits for you to input a
non-whitespace character.
#include <stdio.h>

int main(void)
{
float temp_i, temp_o;
char which_i, which_o;
char junk;

printf("Enter a temperature and indicate\n");
printf("if it's Fahrenheit or Celsius [##.# C/F]: ");
if (scanf("%f %c", &temp_i, which_i) == 2)

The format string consists of 3 directives:

"%f" reads a number in floating-point format.

" " reads input up to the first non-whitespace character.

"%c" reads a single character, which may or may not be whitespace.

So if the user types "432" followed by a newline, the "%f" consumes
the "432", and the " " consumes the newline (and any whitespace
following it). As soon as the user types a non-whitespace character
(such as 'F' or 'C'), the scanf() will consume it and finish.

Or rather, it would if the third argument to the scanf() call were
correct. Given the "%c" directive, the corresponding argument needs
to be a pointer-to-char; you've given it a char. Change "which_i" to
"&which_i".

For better error handling, if you want to require all the input to be
on one line, you can use fgets() to read the entire line, then use
sscanf() to validate and parse it. sscanf(), unlike scanf(), fails
immediately if the input is incomplete, rather than waiting for more
input to appear.

You should also handle the case of fgets() reading an incomplete line.
 

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,994
Messages
2,570,223
Members
46,813
Latest member
lawrwtwinkle111

Latest Threads

Top