A further type of array is the string. A string is a sequence of characters enclosed (in Ada) in double quotes. Strings are a special type of array referred to as a character arrays. As such we can use standard array operations on strings. For example, we can access any character in a string using an index.
Ada provides a specific predefined data type for character arrays called STRING:
DATA_ITEM_NAME : STRING (N..M);
Where N and M are integers defining the lower and upper bounds for the string/character array.
(Note the similarity with array
declarations.)
We have seen that Ada supports a number of predefined operations on arrays.
catenation | S1&S2 |
---|---|
comparison | S1=S2 |
copy | S1:=S2 |
Which may equally be applied to strings. The concept of slices is also supported. Example program:
-- STRING EXAMPLE -- 29 September 1997 -- Frans Coenen -- Dept Computer Science, University of Liverpool with TEXT_IO ; use TEXT_IO ; procedure STRING_EXAMPLE is NAME1: constant STRING(1..5):= "Frans"; NAME2: STRING(1..15); begin -- Assignment NAME2(1..9):= "P. Coenen"; -- Output PUT("Name = "); PUT(NAME1); PUT(" "); PUT(NAME2(1..9)); NEW_LINE; -- Output individual elements PUT("Initials = "); PUT(NAME1(1)); PUT(". "); -- Output slices PUT(NAME2(1..4)); PUT("."); NEW_LINE; end STRING_EXAMPLE ;
The output from the above will be as follows.
kuban-378 string_example Name = Frans P. Coenen Initials = F. P. C.
Design a Ada program that takes a text string as input, analysis this text string and outputs whether it is a valid password or not (a similar operation, at least in part, to that performed by the passwd UNIX command). A valid password displays the following attributes:
If the string is not a valid password output the reason why. Note the following ASCII equivalents:
ASCII CODE | CHARACTER |
---|---|
33-47, 58-64, 91-96, 123-126 | Special characters |
48-57 | Numeric characters |
65-90 | Upper case letters |
97-122 | Lower case letters |
A top-down analysis of the proposed problem is given below.
We will implement this using four procedures/functions:
NAME | USAGE | TYPE | RANGE |
---|---|---|---|
INPUT_STRING | Input variable | STRING | Unconstrained |
STRING_LENGTH | Global variable | INTEGER | Default |
VALID_FLAG | Global variable | BOOLEAN | TRUE or FALSE |
NAME | USAGE | TYPE | RANGE |
---|---|---|---|
LENGTH | Formal parameter | INTEGER | Default |
NAME | USAGE | TYPE | RANGE |
---|---|---|---|
PS_WORD | Formal parameter | STRING | Unconstrained |
LENGTH | Formal parameter | INTEGER | Default |
CODE | Local variable | INTEGER | Default |
COUNTER | Local variable | INTEGER | Default |
NAME | USAGE | TYPE | RANGE |
---|---|---|---|
PS_WORD | Formal parameter | STRING | Unconstrained |
LENGTH | Formal parameter | INTEGER | Default |
CODE | Local variable | INTEGER | Default |
Complete Nassi-Shneiderman charts for the above are given below:
A flow diagram/chart indicating the broad flow of control through the above is given below.
-- PASSWORD -- 1 October 1997 -- Frans Coenen -- Dept Computer Science, University of Liverpool with TEXT_IO; use TEXT_IO; procedure PASSWORD is INPUT_STRING : STRING(1..20); STRING_LENGTH : INTEGER; VALID_FLAG : BOOLEAN := TRUE; -------------------------------------------------------------------------- -- CHECK LENGTH function CHECK_LENGTH(LENGTH: INTEGER) return BOOLEAN is begin if (LENGTH >= 6 and LENGTH <= 8) then RETURN(TRUE); else PUT_LINE("Password must comprise 6 to 8 characters"); RETURN(FALSE); end if; end CHECK_LENGTH; -------------------------------------------------------------------------- -- CHECK CHARACTERS function CHECK_CHARACTERS(PS_WORD: STRING; LENGTH: INTEGER) return BOOLEAN is COUNTER : INTEGER := 0; CODE : INTEGER; begin for LOOP_PARAMETER in 1..LENGTH loop CODE := CHARACTER'POS(PS_WORD(LOOP_PARAMETER)); if (CODE >= 65 and CODE <= 90) or (CODE >= 97 and CODE <= 122) then COUNTER := COUNTER+1; if COUNTER = 2 then RETURN(TRUE); end if; end if; end loop; PUT("Password must comprise at least two alphabetic "); PUT_LINE("characters"); RETURN(FALSE); end CHECK_CHARACTERS; -------------------------------------------------------------------------- -- CHECK OTHERS function CHECK_OTHERS(PS_WORD: STRING; LENGTH: INTEGER) return BOOLEAN is CODE : INTEGER; begin for LOOP_PARAMETER in 1..LENGTH loop CODE := CHARACTER'POS(PS_WORD(LOOP_PARAMETER)); if (CODE >= 33 and CODE <= 64) or (CODE >= 91 and CODE <= 96) or (CODE >= 123 and CODE <= 126) then RETURN(TRUE); end if; end loop; PUT("Password must comprise at least one numeric or "); PUT_LINE("special character"); RETURN(FALSE); end CHECK_OTHERS; -------------------------------------------------------------------------- begin PUT_LINE("Input a proposed password"); GET_LINE(INPUT_STRING,STRING_LENGTH); -- Check length if not CHECK_LENGTH(STRING_LENGTH) then VALID_FLAG := FALSE; end if; -- Check number of alphabetic characters if not CHECK_CHARACTERS(INPUT_STRING,STRING_LENGTH) then VALID_FLAG := FALSE; end if; -- Check number of other characters if not CHECK_OTHERS(INPUT_STRING,STRING_LENGTH) then VALID_FLAG := FALSE; end if; -- Output result if VALID_FLAG then PUT_LINE("Valid password"); else PUT_LINE("Invalid password"); end if; end PASSWORD;
Note how we have included the ability to type in strings of any length between 1 and 20 and how string types are passed to procedures/functions.
TEST CASE | EXPECTED RESULT |
---|---|
INPUT_STRING | OUTPUT |
aVeryLongPasswordIndeed | invalid |
a | invalid |
password_With_20Char | invalid |
myPass1 | valid |
Input Testing: The input string variable should be tested at its limits, somewhere in middle and outside the limits as indicated by the table to the right.
Path Testing: The flow chart given above identifies the paths through the system. Test cases should be generated to ensure that every path is exercised. The black box test cases given above right will achieve this. However, selection of paths is dependent on a number of compound Boolean expressions some of which are extremely complicated.
A | B |
---|---|
T | T |
T | F |
F | T |
F | F |
Commencing with the CHECK_LENGTH function this incorporates a Boolean expression of the form A and B giving a standard truth table of the form shown to the right. Of course the nature of the variable to be tested (STING_LENGTH) is such that at least one or other of A and B must be true (the string length cannot be both less than 6 and greater than 8 at the same time). Consequently the following set of test cases will be appropriate.
TEST CASE | EXPECTED RESULT |
---|---|
INPUT_STRING | Output |
word777 (STRING_LENGTH 7) | valid |
word99999 (STRING_LENGTH 9) | invalid |
word5 (STRING_LENGTH 5) | invalid |
TEST CASE | EXPECTED RESULT | |
---|---|---|
ASCII CODE | INPUT_STRING | Output |
60 | < | invalid |
65 | A | invalid |
78 | N | invalid |
90 | Z | invalid |
95 | _ | invalid |
97 | a | invalid |
110 | n | invalid |
122 | z | invalid |
130 | } | invalid |
The CHECK_CHARACTER function includes a compound Boolean expression of the form (A and B) or (C and D). Taking all possible combinations into account this would produce a 16 line truth table, i.e. 16 test cases. However, we can reduce the number of test cases given that the data item to be tested is a value in a sequence (0 - 127). In fact (A and B) and (C and D) describe ranges of values. Therefore, in this case it is appropriate to derive tests that cause the selection expression to be tested with the ASCII character codes: 60, 65, 78, 90, 95, 97, 110, 122 and 130, as shown in the table (above right). We should also test the situation where no alphabetic characters occur, one occurs, two occurs and more than two occurs.
A similar approach can be used to test the CHECK_OTHERS function. A suitable set of test cases is given below. Note that due to difficulty inputting ASCII character 127 a test above 126 has not been included.
TEST CASE | EXPECTED RESULT | |
---|---|---|
ASCII CODE | INPUT_STRING | Output |
32 | (space) | invalid |
33 | ! | invalid |
50 | 2 | invalid |
64 | @ | invalid |
78 | N | invalid |
91 | [ | invalid |
94 | ^ | invalid |
96 | ` | invalid |
110 | n | invalid |
123 | { | invalid |
124 | | | invalid |
126 | ~ | invalid |
Example Problem Password Verification.
Created and maintained by Frans Coenen. Last updated 11 October 1999