.. _input-validation: Input Validation ################ .. include:: /references.inc .. vim:ft=rst spell: .. seealso:: Text: Chapter 7 As we start writing real C++ programs, you will begin to create programs for those human critters we call "users". They are a strange sort of beings, and there are some new things you need to think about when dealing with them. In this lecture, I want you to think about how your program should act when the user does not do what you ask them to do. As odd as it might seem, they will go off and do other things instead, and you need to anticipate that and keep you program from crashing! This is actually a very interesting topic. You write a program, and it is perfect! You are certain that it will do what it is supposed to do. So, you demonstrate it to your client (or boss) and the unexpected happens: .. code-block:: text $ coolProgram Hello User, enter a number between 1 and 10: 99 And your program blows up! What kind of silly user would do such a thing? Actually many users. Some will do it by mistake, and others will do it on purpose. It gets worse: .. code-block:: text $ coolProgram Hello User, enter a number between 1 and 10: no That is not even a number. What is with these people? Well, it happens, and the moral of this lesson is simple:: Never trust the user to do what you want! So, how do we protect our programs from this insanity? The answer is obvious: Always Check User Input *********************** In the above examples, we are dealing with two kinds of problems: * The user enters the right kind of input, but the wrong value * The user enters the wrong kind of input Of these, the first is easier to deal with, but we must be prepared for the second in the real world! Validation Loop *************** The best way to deal with the first problem is to set up a loop that asks for an input, and inside the loop, check that it is a legal value: .. code-block:: text Print "Enter a Number between 1 and 10" READ input_value WHILE input_value > 10 or input_value < 1 LOOP Print "Invalid input. Try again" READ input_value END LOOP This pattern gets an initial value, then tests it for illegal values at the top of a WHILE-LOOP. If the value is illegal, we display an error message, and ask for another input. The WHILE-LOOP will check the new value and give that silly user yet another chance to enter a good number. (Actually, the program will be stuck until the user does what we want. That may be a problem. Maybe we do not want to let then have more than three shots: .. code-block:: text Print "Enter a Number between 1 anad 10" error_count = 0 READ input_value WHILE input_value > 10 or input_value < 1 LOOP error_count = error_count + 1 IF error_count < 3 THEN Print "Invalid input. Try again" READ input_value ELSE Print "Too many tries, exiting program!" EXIT END IF END LOOP In this example, I am assuming there is a general way to exit the program. There is usually a special system function you can call that will make this happen in most programming languages. Validating String Data ********************** If you expect the user to enter a word, or even a single letter, you have to expect errors that may be as simple as poor typing. The most common problem is case errors: .. code-block:: text Print "Enter yes or no:" Read answer IF answer == "yes" THEN Print "You entered yes" ELSE Print "You entered no" END IF What will display if the user enters "Yes"? Here the problem is that they did what you asked, but provided the correct answer using the wrong case. Is this an error? Well, not really. You should be able to deal with this by converting whatever they typed in to a version in say, lower case, then check that! .. code-block:: text Print "Enter yes or no:" Read answer answer = lower_case(answer) IF answer == "yes" THEN Print "You entered yes" ELSE Print "You entered no" END IF Here, we are assuming that the language provides a function that will take any string as a parameter and convert that string into the same letters in all lower case. Now, we do not care what the user types as long as it is spelled correctly! The test will work. Of course, we still might run into the situation where they spelled the answer wrong: .. code-block:: text Print "Enter yes or no:" Read answer IF answer == "yes" THEN Print "You entered yes" ELSE IF answer == "no" THEN Print "You entered no" ELSE Print "Error input: Try again!" END IF END IF I did not show how to set this up as a loop to get another input, but that is an application of a previous example, so you should be able to figure this out! Validating Patterns =================== In many cases, you expect a defined pattern of characters to be entered. Things like phone numbers, and Social Security numbers should be entered according to a standard pattern, and you need to write a fairly involved function to make sure your input is correct. .. note:: Some programs even go further, they might check the given phone number against a database of known numbers and reject numbers not known to the system. Dealing With Insanity ********************* If you want to handle the really nasty input problems, you have to resort to your own trickery to keep your program from having problems. This is difficult to do properly, but you should be aware that this problem exists when writing programs humans will be running, and learn how to protect your program. Assume the Worst ================ The first step is to assume the user will try something nasty, and just let them type in whatever they like. We will catch this input as a string, and not assume it is the right thing at all. Check the Input String ====================== Once we have the input, we can scan it, character by character, looking for inappropriate characters for the kind of value we expected. In some languages, there are functions that can attempt to convert the string into something like a number, and tell you if that attempt fails. Here is an example from Python: .. code-block:: python data = raw_input("Enter a numner") # this catches the input in a string try: number = int(data) # see if we can convert this string into an integer number except: print("Bad input") data = 0 Not all languages can do this kind of thing, but many modern ones can, since we have been running into this kind of problem for quite a while! We will look at real code to deal with input errors later in the course, when we start writing C++ code.