REPETITION - FIXED COUNT (FOR) LOOPS


1. REPETITION

A repetition construct causes a group of one or more program statements to be invoked repeatedly until some end condition is met. We can identify two main forms of repetition:

  1. Fixed count loops - repeat a predefine number of times.
  2. Variable count loops - repeat an unspecified number of times.

To which we could add recursion (routine calls itself). We will confine the following discussion to fixed and variable count loops and briefly describe recursion at a later date.

1.1. Pretest and postest loops

In addition both loops can be further classified according to whether they are pretest or postest loops. In the case of a pretest loop the end condition is tested for prior to each repetition, while in the case of a postest loop the end condition is tested for after each repetition. The distinction is usually only applicable to variable count loops. With respect to Ada only pretest loops are supported.

We can illustrate the distinction between pretest and postest loops using flow charts of the form given below:

PRETEST AND POSTEST LOOPS

2. THE ADA LOOP STATEMENT

To perform repetition in Ada a loop statement is used. The general form of a loop statement is as follows:

loop
        < sequence of statements >
end loop

3. FIXED COUNT LOOPS

Fixed count loops (sometimes referred to as for loops) allow a statement to be repeated a "fixed" number of times as specified on entry into the loop. The general form of a fixed count loop in Ada is:

for LOOP_PARAMETER in START_VALUE..END_VALUE loop
        < sequence of statements >
end loop

The START_VALUE and END_VALUE should be discrete type or expression. The LOOP_PARAMETER (also referred to as the control variable) is a data item that is declared automatically. Its type depends on the type of the START_VALUE and END_VALUE.

To avoid infinite repetition the loop parameter must be updated on each repetition. The most straight forward approach to updating is to simply increment the loop parameter by 1 on each repetition. In Ada this incrementation is carried out automatically and is outside of the control of the programmer.

4. EXAMPLE PROBLEM ASCII CODE OUTPUT


4.1 Requirements

Produce a program that outputs the ASCII character set from 4 to 127 (the first few ASCII codes are control characters which can not be handled by all editors/word processors and thus we have excluded them from this exercise).


4.2 Design

NASSI_SHNEIDERMAN CHART

A top down analysis of the problem is presented to the right. This can be implemented using a single fixed count loop embedded in a single (top level) procedure:

  1. ASCII_CODE (top level procedure): Loop through ASCII codes from 4 to 127 and output characters.
    NAMEDESCRIPTIONTYPERANGE
    START_CONDGlobal constantINTEGER4
    END_CONDGlobal constantINTEGER127
    COUNTERGlobal variableINTEGER1..6

An appropriate Nassi-Shneiderman chart is given below. Note the method whereby a loop is incorporated into a Nassi-Shneiderman design.

NASSI_SHNEIDERMAN CHART

The associated flow chart indicating the flow of control through the program is given below.

FLOW CHART

A loop statement

4.3. Implementation

The encoding of the above design is as follows:

-- ASCII CODE
-- 7 August 1997
-- Frans Coenen
-- Dept Computer Science, University of Liverpool

with TEXT_IO;
use TEXT_IO;

procedure ASCII_CODE is
    package INTEGER_INOUT is new INTEGER_IO(INTEGER);
    use INTEGER_INOUT;
    START_COND : constant       := 4;
    END_COND   : constant       := 127;
    COUNTER    : INTEGER is range 1..6 := 1;
begin
    for LOOP_PARAMETER in START_COND..END_COND loop
        PUT(LOOP_PARAMETER, WIDTH=>8);
        PUT(" = ");
        PUT(CHARACTER'VAL(LOOP_PARAMETER));
        COUNTER := COUNTER+1;
        if COUNTER = 6 then
            NEW_LINE;
            COUNTER := 1
        end if;
        end loop;
end ASCII_CODE;

Notes:

  1. Here we have an example of a fixed count ("for") loop.
  2. The data item LOOP_PARAMETER is an identifier that is declared automatically. Its type depends on the values for its start and end data items.
  3. It is considered good programming practice to define the start and end values for the loop parameters as constants rather than "magic numbers".
  4. The start and end values for the parameter in the above case are of type INTEGER.
  5. The loop parameter is incremented by 1 automatically.
  6. We have used the CHARACTER type attribute to translate LATIN-1 (loop parameter) codes to characters.
  7. For convenience we have used the loop counter in the calculation, we are not obliged to do so. If we wished to use it in some arithmetic expression using floating point numbers we would need to carry out the appropriate conversion.

4.4. Testing

The above code contains no input, no ranged data items and no arithmetic expressions. The loop is a fixed count loop and should be exercised with a complete run through. This will be the only testing that is required. The result will be as follows:

       4 =        5 =        6 =        7 =        8 =
       9 =            10 =
      11 =       12 =       13 =
      14 =       15 =       16 =       17 =       18 =
      19 =       20 =       21 =       22 =       23 =
      24 =       25 =       26 =       27 =      28 =
      29 =       30 =       31 =       32 =        33 = !
      34 = "      35 = #      36 = $      37 = %      38 = &
      39 = '      40 = (      41 = )      42 = *      43 = +
      44 = ,      45 = -      46 = .      47 = /      48 = 0
      49 = 1      50 = 2      51 = 3      52 = 4      53 = 5
      54 = 6      55 = 7      56 = 8      57 = 9      58 = :
      59 = ;      60 = <      61 = =      62 = >      63 = ?
      64 = @      65 = A      66 = B      67 = C      68 = D
      69 = E      70 = F      71 = G      72 = H      73 = I
      74 = J      75 = K      76 = L      77 = M      78 = N
      79 = O      80 = P      81 = Q      82 = R      83 = S
      84 = T      85 = U      86 = V      87 = W      88 = X
      89 = Y      90 = Z      91 = [      92 = \      93 = ]
      94 = ^      95 = _      96 = `      97 = a      98 = b
      99 = c     100 = d     101 = e     102 = f     103 = g
     104 = h     105 = i     106 = j     107 = k     108 = l
     109 = m     110 = n     111 = o     112 = p     113 = q
     114 = r     115 = s     116 = t     117 = u     118 = v
     119 = w     120 = x     121 = y     122 = z     123 = {
     124 = |     125 = }     126 = ~     127 =

Note that some of the character codes are unprintable. Note also that:

9=Horizontal tab
10=Line feed/carriage return
27=Escape
32=Space
127=Delete

Example Problem ASCII code Output.


5. EXAMPLE PROBLEM ARITHMETIC PROGRESSION


5.1 Requirements

Design and implement an Ada program that outputs the first N terms of an a.p. (arithmetic progression) of the form:

A, A+D, A+2D, A+3D ...

where A is the first term and D is the common difference. Assume that A and D are integers within the range -1000..1000, and that N is a natural number whose maximum permissible value is 100.


5.2 Design

A top down analysis of the problem is given below:

TOP DOWN ANALYSIS

The identified operations can be implemented using two procedures:

  1. ARITHMETIC_PROGRESSION (Top level procedure): Input data and call to OUTPUT_TERMS.
    NAMEDESCRIPTIONTYPERANGE
    FIRST_TERMGlobal input variableINTEGER-1000..1000
    COMMON_DIFFERENCEGlobal input variableINTEGER-1000..1000
    NUMBER_OF_TERMSGlobal input variableNATURAL0..100
  2. OUTPUT_TERMS (level 2 procedure): Fixed count loop to output terms.
    NAMEDESCRIPTIONTYPERANGE
    FRST_TERMFormal parameterINTEGERDefault
    COM_DIFFFormal parameterINTEGERDefault
    END_VALUEFormal parameterNATURALDefault
    START_CONDITIONLocal constantINTEGER1

An appropriate Nassi-Shneiderman design is given below.

NASSI_SHNEIDERMAN CHART

5.3. Implementation

The encoding of the above design is as follows:

-- ARITHMETIC PROGRESSION
-- 12 September 1997
-- Frans Coenen
-- Dept Computer Science, University of Liverpool

with TEXT_IO;
use TEXT_IO;

procedure ARITHMETIC_PROGRESSION is
    package INTEGER_INOUT is new INTEGER_IO(INTEGER);
    use INTEGER_INOUT;
    FIRST_TERM, COMMON_DIFFERENCE : INTEGER range -1000..1000;
    NUMBER_OF_TERMS               : NATURAL range 0..100;

---------------------------------------------------------------------------------
-- OUTPUT TERMS
    procedure OUTPUT_TERMS(FRST_TERM, COM_DIFF, END_VALUE: INTEGER) is
        START_CONDITION: constant := 1;
    begin
        for LOOP_PARAM in START_CONDITION..END_VALUE loop
            PUT(FRST_TERM+(COM_DIFF*LOOP_PARAM));
            PUT(" ");
        end loop;
        NEW_LINE;
        end OUTPUT_TERMS;
---------------------------------------------------------------------------------

-- TOP LEVEL
begin
    PUT("Input number of terms (integer number 0..100): ");
    GET(NUMBER_OF_TERMS);
    NEW_LINE;
    PUT("Input first term and common difference (integers): ");
    GET(FIRST_TERM);
    GET(COMMON_DIFFERENCE);
    NEW_LINE;
    OUTPUT_TERMS(FIRST_TERM,COMMON_DIFFERENCE,NUMBER_OF_TERMS);
end ARITHMETIC_PROGRESSION;

5.4. TESTING


5.4.1. Black box testing

BVA testing: A suitable set of BVA test cases is given in the table below. Note that (without the use of a computer program) it is extremely arduous to determine output to 99 terms thus we have not included a precise expected result.

TEST CASERESULT
NUMBER_ OF_ TERMSFIRST_ TERMCOMMON_ DIFFERENCEOUTPUT
-1 * * CONSTRAINT_ ERROR
-1 * * CONSTRAINT_ERROR
101 * * CONSTRAINT_ERROR
1-1001 * CONSTRAINT_ERROR
99 1001 * CONSTRAINT_ERROR
1 -999-1001CONSTRAINT_ERROR
99 999 1001CONSTRAINT_ERROR
1 -999 -999-999
99 999 999999, 1998, 2997, 3996 ...

Limit testing: We should also carry out a number of limit tests as indicated in the table given below.

TEST CASERESULT
NUMBER_ OF_ TERMSFIRST_ TERMCOMMON_ DIFFERENCEOUTPUT
-1 * * CONSTRAINT_ ERROR
100-1000-1000-1000, -2000, -3000, -4000 ...
100-1000 1000-1000, 0, 1000, 2000 ...
100 1000-10001000, 0, 1000, 2000 ...
100 1000 10001000, -2000, -3000, -4000 ...
0-1000-1001No output
0-1000 1000No output
0 1000-1000No output
0 1000 1000No output

Arithmetic Testing: We should test inputs with negative, zero and positive sample values. This is appropriate for the FIRST_ TERM and COMMON_DIFFERENCE inputs. The NUMBER_OF_TERMS input cannot have a negative value. We should therefore test this with zero and positive sample values. However, a zero sample value will result in "no passes through the loop", and has been incorporated into loop testing (see below). For the purpose of arithmetic testing we will only use a positive sample value for NUMBER_OF_TERMS. A suitable set of test cases is given below.

TEST CASERESULT
NUMBER_ OF_ TERMSFIRST_ TERMCOMMON_ DIFFERENCEOUTPUT
4-500-500-500, -1000, -1500, -2000
4 0-500, -500, -500, -500
4 500-500, 0, 500, 1000
4-5000, -500, -1000, -1500
4 00, 0, 0, 0
4 5000, 500, 1000, 1500
4-500500, 0, -500, -1000
4 0500, 500, 500, 500
4 500500, 1000, 1500, 2000

5.4.2. White box testing

Loop testing: Where the user controls the number of repetitions in a fixed count loop the loop should be tested (in theory) as follows:

  1. No passes through loop (i.e. skip through loop).
  2. Only one pass through the loop
  3. Two passes through the loop
  4. M passes through the loop where M < END_VALUE
  5. END_VALUE-1, END_VALUE, END_VALUE+1 passes through the loop

The nature of our implementation is such that "END_VALUE+1" test is unnecessary. However, the set of tests given below are appropriate in this case. Note that some of these are repeats of the suggested BVA test cases.

TEST CASERESULT
NUMBER_ OF_ TERMSFIRST_ TERMCOMMON_ DIFFERENCEOUTPUT
042No output
1 4 -2 4
2 0 2 0 2
10 0 0 0 0 0 0 0 0 ...
99 0 -2 0 -2 -4 -6 -8 -10 ...
100-4 2 -4 -2 0 2 4 6 ...

5.4.3 Data validation testing:


Example Problem Arithmetic Progression Report.




Created and maintained by Frans Coenen. Last updated 11 October 1999