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

8.8 Problem Solving: Reading Part of an Array

Usually we don't know exactly how many elements there will be in an array. For example, if we are processing exam scores, there might be 150 students in one class, 200 in the next, and so on. In this situation, we can declare an array that will accommodate the largest class. Only part of this array will actually be processed for a smaller class.

Example 8.12

The array Scores declared below can accommodate a class of up to 250 students. Each array element can contain an integer value between 0 and 100.

    MaxSize : CONSTANT Positive := 250;
    MaxScore : CONSTANT Positive := 100;
    SUBTYPE ClassIndex  IS Positive RANGE 1..MaxSize;
    SUBTYPE ClassRange  IS Natural RANGE 0..MaxSize;
    SUBTYPE ScoreRange  IS Natural RANGE 0..MaxScore;
    TYPE ScoreArray IS ARRAY (ClassIndex) OF ScoreRange;
    
    Scores : ScoreArray;
    ClassSize : ClassRange;
Procedure ReadScores in Program 8.12 reads up to 250 exam scores. It displays a warning message when the array is filled. The actual number of scores read is returned as the value of ClassSize.

Program 8.12
Procedure ReadScores

PROCEDURE ReadScores (Scores : OUT ScoreArray;
                      ClassSize : OUT ClassRange) IS
-- Reads an array of exam scores (Scores)
-- for a class of up to MaxSize students.
-- Pre : None
-- Post: The data values are stored in array Scores.
--       The number of values read is stored in ClassSize.
  
  Sentinel : CONSTANT Integer := -1;  -- Sentinel value   
  TempScore : Integer;              -- Temporary storage for a score   
  TempSize : ClassRange;

BEGIN

  Ada.Text_IO.Put
    (Item => "Enter next score after the prompt or -1 to stop.");
  Ada.Text_IO.New_Line;

  TempSize := 0;                         -- initial class size   
  -- Read each array element until done.   
  LOOP
    -- invariant:
    --   No prior value read is Sentinel and
    --   ClassSize <= MaxSize
      
    Robust_Input.Get(Item => TempScore, 
                     MinVal => Sentinel,
                     MaxVal => ScoreRange'Last);

    EXIT WHEN (TempScore = Sentinel) OR (ClassSize = MaxSize);

    TempSize := TempSize + 1;
    Scores(TempSize) := TempScore;     -- Save the score   

  END LOOP;      
  -- assert:
  --   Last value read is Sentinel or
  --   TempSize is MaxSize
    
  IF TempSize = MaxSize THEN
    Ada.Text_IO.Put(Item => "Array is filled.");  
    Ada.Text_IO.New_Line;
  END IF;

  ClassSize := TempSize;

END ReadScores;
In any subsequent processing of array Scores, the variable ClassSize should be used to limit the number of array elements processed. Only the subarray with subscripts 1..ClassSize is defined. All array elements with subscripts larger than ClassSize are still undefined and should not be manipulated. ClassSize should be passed as a parameter to any procedure that processes the partially filled array.

Exercises for Section 8.8

Self-Check

  1. In procedure ReadScores, what prevents the user from entering more than MaxSize scores?
  2. What is the range of data values that can be entered? What is the range of data values that can be stored in the array?
  3. Why can't we use a FOR loop instead of a WHILE loop in procedure ReadScores?


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

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