The final thing we will look at in this chapter is validation of input. We have talked briefly about programs being robust. This means that a program can recover from problems such as letters being entered instead of numbers. All of the previous programs which asked for numbers would crash if you had entered another character instead. These programs are not robust. So how do we make our programs robust so that they do not crash over a little thing like that. We do this by validating the input. The usual way to do this for an integer input, is to read it in as a string, check that each character of the string is in fact a number, then convert the string into a number. So how is it that we do this? First of all, let's draw a picture of a 4 element string. Assume that it is loaded with the second semester computing science course code 3132. Remember that these are characters not numbers. You cannot perform calculations with them.

Figure 2 - Validation of input : A string of character integers

Now you need to look at you idea of what a number is again. In effect what I am saying is that the in element [1] is not the number 3, but in fact it represents 3 * 1,000. So:

The number in element [1], represents 3 * 1,000.

The number in element [2], represents 2 * 100.

The number in element [3], represents 3 * 10.

The number in element [4], represents 2 * 1.

We then convert the characters and then perform the calculations.

Figure 3 - Validation of input : What is a number

So we know how to do the calculations after we have converted the characters into numbers, but how do we convert characters in a string into numbers? The answer is in the ASCII table. Let's look at the fourth element of the string first. In this case it is the character '2'. Can you remember anything in Pascal that can produce a number from a character? How about ORD? Consider this next little program, if you ran it the the result would be that the number 50 would be written to the screen, this is the position in the ASCII table of the character '2'.

Program 4

PROGRAM order(OUTPUT); VAR element : CHAR; BEGIN element := '2'; WRITELN(ORD(element):1); END. { program order }

That's the first step done. We have produced a number from a character. So what do we do next? All we do is to subtract 48 from the result of the ORD operation. In the above program, after the line

WRITELN(ORD(element):1);

add this line

WRITELN(ORD(element) - 48 :1);

Now this will produce the number 2 from the character '2'. We can repeat this operation on each element in a string or array, but how do we make the first element of the string in fig 1. into 3,000? and the second into 100, the third into 30, leaving the fourth as the number 2. The answer to that comes from an algorithm. You may have been told before that writing code is easy, but it's the writing algorithms that is the difficult part. Here is the algorithm I used.

Initialise. Find the length of the string using STRLEN. Set a variable subscript to that length. Set a variable multiplier to 1.

Loop. Convert the element indicated by subscript and multiply by multiplier. Subtract 1 from subscript. Multiply multiplier by 10. Loop again if subscript >= 1.

That's all there is to converting number characters into integers, but this algorithm will produce an integer from any character input. So what we still have to do is to validate that each character is in fact an number character in the first place. We could do this by reading in each character one at a time, check that it is between '0' and '9' inclusively before assigning it to the string element. I have chosen to do it a different way, and used a boolean variable as a VAR parameter of a procedure which I can check after the procedure call. This tells me if any of the elements of the string are not number characters. This is not a better way, it's just a different way.

Program 5

The boolean is_a_digit becomes FALSE if any of the characters in the string are outside the range of number characters. In the main program, this variable is checked after the call of procedure validate, and depending on whether it is TRUE or FALSE a message is written to the screen. If is_a_digit is TRUE the converted and validated number is printed out with the message. Of course any other course of action is open to you as a result of the test on is_a_digit. The main point being that if is_a_digit is FALSE you know that some non-numerical characters were put into the string so you can ask for the number again, or what ever else you want do do.

{ -------------------------------------------------------------- } PROCEDURE validate(VAR is_a_digit : BOOLEAN; VAR number : INTEGER; VAR in_string : STRING); { this procedure validates integer input read in as a string } VAR subscript, multiplier : INTEGER; { local variables } BEGIN is_a_digit := TRUE; multiplier := 1; subscript := STRLEN(in_string); number := 0; WHILE (subscript >= 1) AND is_a_digit DO BEGIN is_a_digit := (in_string[subscript] >= '0') AND (in_string[subscript] <= '9'); number := number + (ORD(in_string[subscript]) - 48) * multiplier; subscript := subscript - 1; multiplier := multiplier * 10; END; END; { procedure validate } { -------------------------------------------------------------- }

On the next page I have put this procedure into a program for you.

Program 6

PROGRAM validation(INPUT,OUTPUT); { this program reads in a string and checks to see if each character is a number } TYPE TEN_ELEMENT_STRING = STRING[10]; VAR number_string : TEN_ELEMENT_STRING; validated_number : INTEGER; good_number : BOOLEAN; { -------------------------------------------------------------- } PROCEDURE validate(VAR is_a_digit : BOOLEAN; VAR number : INTEGER; VAR in_string : TEN_ELEMENT_STRING); { this procedure validates integer input read in as a string } VAR subscript, multiplier : INTEGER; { local variables } BEGIN is_a_digit := TRUE; multiplier := 1; subscript := STRLEN(in_string); number := 0; WHILE (subscript >= 1) AND is_a_digit DO BEGIN is_a_digit := (in_string[subscript] >= '0') AND (in_string[subscript] <= '9'); number := number + (ORD(in_string[subscript]) - 48) * multiplier; subscript := subscript - 1; multiplier := multiplier * 10; END; END; { procedure validate } { -------------------------------------------------------------- } BEGIN { MAIN PROGRAM } WRITE('Enter a number : '); readln(number_string); validate(good_number, validated_number, number_string); IF good_number THEN WRITELN('Input string is a number ',validated_number:1) ELSE WRITELN('Input string has non-numerical elements'); END. { program validation }

Special cases

In programming we like to make all our code take care of all possible conditions. That is we try to make our programs cover the general conditions. Very often though we come across some condition which cannot be covered by the general condition. The only solution is to program a special case. If at some time you wanted to use a WRITELN to print out the number of people who have done something. The problem comes with grammar, I mean that people singular is person. The special case therefore is that you must have a separate WRITELN for the one case in which there is only one person.

IF (people = 1) THEN WRITELN('There was only : ',people,' person') ELSE WRITELN('There were : ',people,' people');

The second case takes care of all other occurrences.