The biggest problem when working with standard input is that it's reliant on the user properly responding. If the user does not type the right number or format of input, the application cannot be expected to perform properly. This is the old garbage in, garbage out maxim and the reason you'll want to validate input before working with it.
The validity of many answers can be checked with relative ease. For example:
Seeing if an age variable is greater than 0 but less than, say, 120
Checking that an answer is equal to Yes or No (or Y, y, N, n)
Comparing an input against the logical values (like C and F in the temperature-conversion application)
In other cases—such as a temperature conversion where the inputted number can be any value—validation is trickier. One technique you can use involves the scanf() function itself. Because that function returns the number of items it read in, you can use that returned value to determine if the input matched the assumed type. To explain more clearly, let's rewrite the temp_conversion application. This new version will also make use of a technique for ignoring extraneous input (see the sidebar).
1. | |
2. | Declare a third char variable (Script 5.5): char junk; Script 5.5. Input validation requires thought and testing but is crucial to reliable, professional applications. Here, the act of reading input is written as the tested condition before any calculations are made.The junk variable will be used within a while loop to help read in and discard extraneous input (see the sidebar, “Ignoring Input”). |
3. | Rewrite the scanf() line so that it's part of a conditional: if (scanf ("%f %c", &temp_i, &which_i) == 2) { The scanf() function will return the number of items it successfully read in. As it has been formatted in this example to receive a float followed by a character, if the keyed input was correct, scanf() should return the number 2 as two values were read and assigned to variables. That knowledge allows you to place the entire scanf() code within a conditional. The condition specifically checks if the scanf() function returns a value that is equal to 2. If this condition is true, you know that one float and one character were successfully read in and you can proceed with the calculations. If you find this syntax to be too complicated, you can rewrite it like so: int n; n = scanf ("%f %c", &temp_i, &which_i); if (n == 2) { |
4. | Make all of the functionality of the original program part of the if conditional. The switch and if-else conditionals that were at the heart of the original application are now the resulting code for the if part of the main (scanf()) conditional. |
5. | Complete the main conditional: } else { printf ("You failed to use the proper syntax. "); } If the scanf() function does not return the number 2, a problem occurred and this message is printed. |
6. | |
7. | |
8. | Save the file as temp_conversion2.c, compile, and debug as necessary. |
9. | Run the application, keying in both valid (Figure 5.12) and invalid (Figure 5.13) input. Figure 5.12. After adding more input validation, the application works as it had before if the input is entered correctly.Figure 5.13. The input is now validated so that no conversions are attempted using improper input. |
There are many ways to validate input; which you use depends on the type, number, and format of the input expected. In this chapter you've seen a couple of options (using scanf() and checking values against a switch). The most important thing to know is that you should not assume people will always properly use an application.
Some validation can be accomplished using the ctype.h library. It adds several functions, such as isalpha(), isdigit(), and isspace(), that check if a single character is of a certain type. The ctype.h file also adds conversion functions to your applications. These functions include tolower() and toupper(), for converting the cases of single characters.