Previous | Next | Table of Contents | Index | Program List | Copyright

8.6 Problem Solving: Selecting Array Elements for Processing

Using a Subscript as an Index to an Array

As indicated in the last section, the subscript type of an array may be any discrete type or subtype. In the next few sections, most of the examples will deal with arrays whose subscript type is a subtype of type Positive. We are doing this because it is expedient; you should keep in mind that the features described carry over to other subscript types as well. We will discuss arrays with nonnumeric subscripts in Section 8.9.

Each array reference includes the array name and a subscript enclosed in parentheses. The subscript (sometimes called an index) used to reference an array element must be an expression that is compatible with the declared subscript type. Very often, the subscript type is a subtype with a minimum value of 1 (e.g., (1..MaxSize)). Because the minimum subscript value is positive, it must be an expression whose value is in the range specified by the subscript type. For the array Vacation declared in Example 8.6, the allowable subscript values are the positive integers from 1 through 50.

Example 8.7

Table 8.2 shows some sample statements involving the array X shown in Fig. 8.3. I is assumed to be a Positive variable with value 6. Make sure you understand each statement.

Table 8.2
Some Sample Statements for Array X

Statement					Effect

Ada.Float_Text_IO.Put( X( 4));			Displays 8.0 ( value of X( 4)).
Ada.Float_Text_IO.Put( X( I));			Displays 12.0 ( value of X( 6)).
Ada.Float_Text_IO.Put( X( I)+1.0);		Displays 13.0 ( value of 12.0 + 1.0).
Ada.Float_Text_IO.Put( X( I+1));		Displays 14.0 ( value of X( 7)).
Ada.Float_Text_IO.Put( X( I+I));		Run-time Error: attempt to display X( 12).
Ada.Float_Text_IO.Put( X( 2*I));		Run-time Error: attempt to display X( 12).
Ada.Float_Text_IO.Put( X( 2*I-4));		Displays -54.6 ( value of X( 8)).
Ada.Float_Text_IO.Put( X( Positive( X( 4))));	Displays X( 8).
X( I) := X( I+1);				Assigns 14.0 ( value of X( 7)) to X( 6).
X( I-1) := X( I);				Assigns 14.0 ( new value of X( 6)) to X( 5).
X( I)- 1 := X( I);				Syntax Error: Illegal assignment statment

The last Put statement uses Positive( X( 4)) as a subscript expression. Because this evaluates to 8, the value of X( 8) ( and not X( 4)) is changed. If the value of Positive( X( 4)) were outside the range 1 through 8, Constraint_Error would be raised at execution time.

Two different subscripts are used in the last three assignment statements in the table. The first assignment copies the value of X( 7) into X( 6) (subscripts I+1 and I); the second assignment statement copies the value of X( 6) into X( 5) (subscripts I and I-1). The last assignment statement causes a syntax error, because there is an expression to the left of the assignment symbol, :=.

In Table 8.2, there are two attempts to display element X( 12), which is not in the array. These attempts will result in Constraint_Error being raised.

SYNTAX DISPLAY
Array Reference

Form:
name (subscript)

Example:
X(3*I - 2)

Interpretation:
The subscript must be an expression that is compatible with the subscript-type specified in the declaration for the array name. If the expression is of the wrong data type, a "type mismatch" compilation error will be detected; if the value expression depends on values not known at compile time, Constraint_Error will be raised at execution time if the expression value is out of the subscript range.

Using FOR Loops with Arrays

Often we wish to process the elements of an array in sequence, starting with the first. An example would be entering data into the array or displaying its contents. This can be acccomplished using a FOR loop whose loop control variable (e.g., I) is also used as the array subscript (e.g., X(I)). Increasing the value of the loop control variable by 1 causes the next array element to be processed.

Example 8.8

The array Cubes declared below can be used to store the cubes of the first ten integers (e.g., Cubes(1) is 1, Cubes(10) is 1000).

    Size : CONSTANT Positive := 10;
    SUBTYPE Index IS Positive RANGE 1..Size;
    TYPE IntArray IS ARRAY (Index) OF INTEGER;
    Cubes : IntArray;                 -- array of cubes

The FOR statement

    FOR I IN 1 .. Size LOOP
	Cubes(I) := I * I * I;
    END LOOP;
initializes this array as shown in Fig. 8.7.

Figure 8.7
Array Cubes

Figure 8.7

A better way to write the FOR loop is

    FOR I IN Index LOOP
	Cubes(I) := I * I * I;
    END LOOP;

The behavior of this loop is the same as that of the previous loop: Each element of the array is accessed in sequence. The advantage of writing the loop this way is that, assuming Index is the subscript type of the array, if the bounds of Index are ever changed and the program is recompiled, no other statements will have to change. In cases where an entire array is being referenced in sequence, we will usually use this form of loop control.

Example 8.9

Program 8.8 reads an array of values from the terminal, calculates the average of the values, and displays a table of differences, each showing the given value's difference from the average.

Program 8.8
Table of Differences

WITH Ada.Text_IO;
WITH Ada.Integer_Text_IO;
WITH Ada.Float_Text_IO;
PROCEDURE Show_Differences IS
------------------------------------------------------------------------
--| Computes the average value of an array of data and
--| prints the difference between each value and the average.
--| Author: Michael B. Feldman, The George Washington University 
--| Last Modified: July 1995                                     
------------------------------------------------------------------------
  
  MaxItems : CONSTANT Positive := 8;    -- number of data items   

  SUBTYPE Index IS Positive RANGE 1..MaxItems; 
  TYPE FloatArray IS ARRAY (Index) OF Float;

  X        : FloatArray;             -- array of data   
  Average  : Float;                  -- average value of data   
  Sum      : Float;                  -- sum of the data   

BEGIN -- Show_Differences   

  -- Enter the data.   
  Ada.Text_IO.Put(Item => "Please enter ");
  Ada.Integer_Text_IO.Put(Item => MaxItems, Width=>0);
  Ada.Text_IO.Put(Item => " floating-point numbers > ");
  Ada.Text_IO.New_Line;

  FOR I IN Index LOOP
    Ada.Float_Text_IO.Get(Item => X(I));
  END LOOP;
  Ada.Text_IO.New_Line;

  -- Compute the average value.   
  Sum := 0.0;                        -- Initialize SUM   
  FOR I IN Index LOOP
    Sum := Sum + X(I);               -- Add each element to Sum   
  END LOOP;

  Average := Sum / FLOAT(MaxItems);  -- Find average value   
  Ada.Text_IO.Put(Item => "Average value is ");
  Ada.Float_Text_IO.Put(Item=>Average, Fore=>5, Aft=>2, Exp=>0);  
  Ada.Text_IO.New_Line;

  -- Display the difference between each item and the average.   
  Ada.Text_IO.Put
    (Item => "Table of differences between X(I) and average");
  Ada.Text_IO.New_Line;
  Ada.Text_IO.Put(Item => "   I        X(I)     Difference");  
  Ada.Text_IO.New_Line;

  FOR I IN Index LOOP
    Ada.Integer_Text_IO.Put(Item => I, Width=>4);  
    Ada.Text_IO.Put(Item => "    ");
    Ada.Float_Text_IO.Put(Item=>X(I), Fore=>5, Aft=>2, Exp=>0);  
    Ada.Text_IO.Put(Item => "    ");
    Ada.Float_Text_IO.Put(Item=>X(I)-Average, Fore=>5, Aft=>2, Exp=>0);  
    Ada.Text_IO.New_Line;
  END LOOP;

END Show_Differences;
Sample Run
Please enter 8 floating-point numbers > 
16 12 6 8 2.5 12 14 -54.5

Average value is     2.00
Table of differences between X(I) and average
   I        X(I)     Difference
   1       16.00       14.00
   2       12.00       10.00
   3        6.00        4.00
   4        8.00        6.00
   5        2.50        0.50
   6       12.00       10.00
   7       14.00       12.00
   8      -54.50      -56.50
In this program, the declarations
    MaxItems : CONSTANT Positive := 8;            -- number of data items

    SUBTYPE Index IS Positive RANGE 1..MaxItems;

    TYPE FloatArray IS ARRAY (Index) OF Float;

    X : FloatArray;                               -- array of Float numbers
allocate storage for an array X with subscripts in the range 1..8. The program uses three FOR loops to process the array X. The loop control variable I is also used as the array subscript in each loop.

The first FOR loop

    FOR I IN Index LOOP
	Ada.Float_Text_IO.Get(Item => X(I));
    END LOOP;
is used to read one data value into each array element (the first item is stored in X(1), the second item in X(2), etc.). The Get procedure is called once for each value of I in the range of Index, that is, from 1 to 8; each call causes a new data value to be read and stored in X(I). The subscript I determines which array element receives the next data value. The sample run causes the array to acquire the values shown in Fig. 8.3.

The second FOR loop is used to accumulate (in Sum) the sum of all values stored in the array; this loop will be traced later. The last FOR loop,

    FOR I IN Index LOOP
	Ada.Integer_Text_IO.Put(Item => I, Width=>4);
	Ada.Text_IO.Put(Item => "    ");
	Ada.Float_Text_IO.Put(Item => X(I), Fore=>5, Aft=>2, Exp=>0);
	Ada.Text_IO.Put(Item => "    ");
	Ada.Float_Text_IO.Put(Item => X(I)-Average, Fore=>5, Aft=>2, Exp=>0);
	Ada.Text_IO.New_Line;
    END LOOP;
is used to display a table showing each array element, X(I), and the difference between that element and the average value, X(I) - Average.

The program fragment

    Sum := 0.0;                               -- Initialize SUM
    FOR I IN Index LOOP
	Sum := Sum + X(I);              -- Add each element to SUM
    END LOOP;
accumulates the sum of all eight elements of array X in the variable Sum. Each time the FOR loop is repeated, the next element of array X is added to Sum. The execution of this program fragment is traced in Table 8.3 for the first three repetitions of the loop.

Table 8.3
Partial Trace of FOR Loop of Program 8.10

Statement Part		I	X(I)	Sum	Effect

Sum:= 0;				0	Initializes Sum

FOR I IN Index LOOP	1	16.0		Initializes I to 1
Sum := Sum + X( I)			16.0	Add X(1) to Sum

increment and test I	2	12.0		2 <= 8 is true
Sum := Sum + X( I)			28.0	Add X(2) to Sum

increment and test I	3	2.5		3 <= 8 is true
Sum := Sum + X( I)			30.5	Add X(3) to Sum

In Program 8.8, the subscripted variable X( I) is an actual parameter for the floating-point Get and Put procedures. It is always necessary to read data into an array one element at a time as shown in this example. In most instances it is also necessary to display one array element at a time.

Exercises for Section 8.6

Self-Check

  1. Describe the effect of each statement in Table 8.2 assuming I is 5.
  2. If an array is declared to have ten elements, must the program use all ten of them?
  3. The sequence of statements below changes the initial contents of array X displayed in Fig. 8.3. Describe what each statement does to the array and show the final contents of array X after all statements execute.
    I := 3;
    X(I) := X(I) + 10.0;
    X(I - 1) := X(2 * I - 1);
    X(I + 1) := X(2 * I) + X(2 * I + 1);
    FOR I IN 5 .. 7 LOOP
    	X(I) := X(I + 1);
    END LOOP;
    FOR I IN REVERSE 1..3 LOOP
    	X(I + 1) := X(I);
    END LOOP;
    
  4. Write program statements that will do the following to array X shown in Fig. 8.3.

    a. Replace the third element with 7.0.

    b. Copy the element in the fifth location into the first one.

    c. Subtract the first element from the fourth and store the result in the fifth one.

    d. Increase the sixth element by 2.

    e. Find the sum of the first five elements.

    f. Multiply each of the first six elements by 2 and place each product in an element of the array AnswerArray.

    g. Display all even-numbered elements on one line.


Previous | Next | Table of Contents | Index | Program List | Copyright

Copyright © 1996 by Addison-Wesley Publishing Company, Inc.