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

8.2 Control Structures: Records as Subprogram Parameters

A record can be passed as a parameter to a function or procedure, provided that the actual parameter is of the same type as its corresponding formal parameter. The use of records as parameters can shorten parameter lists considerably because one parameter (the record variable) can be passed instead of several related parameters.

Reading a Record

Ada normally uses procedures to read data from the terminal or a file. The Get procedures available in the input/output packages are defined only for individual values, not for records. To read a record, we can use a call of the appropriate Get to read each field. It is common to read an entire record at once, so it makes sense to define a procedure for doing this; the body of the procedure will contain the individual Get calls for each record field.

Example 8.4

Program 8.2 contains a procedure GetPoint to read a point in the x-y plane and a function Distance, which calculates the distance between two points P1 = (X1 ,Y1) and P2 = (X2 , Y2) . The formula used to calculate the distance d is

      _________________________
d = \/( X2 - X1)2 + ( Y2 - Y1)2
The main program requests the coordinates of two points from the user, then calculates and displays the distance between them. Notice how straightforward it is to write and call subprograms with record parameters.

Program 8.2
Distance between Two Points

WITH Ada.Text_IO;
WITH Ada.Float_Text_IO;
WITH Ada.Numerics.Elementary_Functions;
USE  Ada.Numerics.Elementary_Functions;
PROCEDURE Distance_between_Points IS
------------------------------------------------------------------------
--| Finds the distance between two points on the x-y plane.   
--| Author: Michael B. Feldman, The George Washington University 
--| Last Modified: July 1995                                     
------------------------------------------------------------------------

  TYPE Point IS RECORD
    X : Float;
    Y : Float;
  END RECORD;

  Point1 : Point;              -- one data point   
  Point2 : Point;              -- the other data point   

  PROCEDURE GetPoint(Item: OUT Point) IS
  -- Pre: none
  -- Post: the point, Item, is defined with values from the user

  BEGIN

    Ada.Text_IO.Put(Item => "Enter X coordinate (floating point) > ");
    Ada.Float_Text_IO.Get(Item => Item.X);
    Ada.Text_IO.Put(Item => "Enter Y coordinate (floating point) > ");
    Ada.Float_Text_IO.Get(Item => Item.Y);

  END GetPoint;


  FUNCTION Distance(P1 : Point; P2 : Point) RETURN Float IS
  -- Pre: P1 and P2 are defined
  -- Post: returns the Cartesian distance between the points

  BEGIN

    RETURN Sqrt((P2.X-P1.X) ** 2 + (P2.Y-P1.Y) ** 2);

  END Distance;

BEGIN -- Distance_between_Points   

  Ada.Text_IO.Put(Item => "First Point");
  Ada.Text_IO.New_Line;
  GetPoint(Item => Point1);
  Ada.Text_IO.Put(Item => "Second Point");
  Ada.Text_IO.New_Line;
  GetPoint(Item => Point2);
  Ada.Text_IO.Put(Item => "Distance between points is ");
  Ada.Float_Text_IO.Put
    (Item => Distance(Point1, Point2), Fore=>1,Aft=>2,Exp=>0);
  Ada.Text_IO.New_Line;

END Distance_between_Points;
Sample Run
First Point
Enter X coordinate (floating point) > 3
Enter Y coordinate (floating point) > 4
Second Point
Enter X coordinate (floating point) > 9
Enter Y coordinate (floating point) > 12
Distance between points is 10.00

Record Aggregate Assignment

When an entire record must be assigned at one time, it is unnecessary to assign each field in a separate assignment statement. Instead, you can use an aggregate. An aggregate is just a list of all the field values in the record, separated by commas and enclosed in parentheses. An aggregate looks like a parameter list in a procedure call: The values can just be listed in sequence (positional association) or given with their names (named association). Generally we will use the latter form because it is clearer and easier to understand.

A record Clerk of type Employee, as used above, could be filled in with an aggregate assignment as follows:

    Clerk :=
    	(ID => 1234,
    	Name => "Caryn Jackson       ",   
    	Gender => Female,
    	NumDepend => 2, 
    	Rate => 7.50);
We have listed the fields in the order in which they were declared in the type definition, but in fact we could have put them in any order because the field names help the compiler (and the human reader) make the association.

It is permissible to write an aggregate assignment without specifying the field names, for example,

    Clerk := (1234,"Caryn Jackson       ", Female, 2, 7.50);
However, this form, called positional association, is not nearly as clear and also requires that the fields be listed exactly in the order in which they appear in the type definition. We will generally use the first, or named association, form of record aggregate assignment.

Exercises for Section 8.2

Self-Check

  1. What does the program segment below do? Provide the declarations for variables Exam1 and Exam2.
    PrintStat (Exam1);
    Exam2 := Exam1;
    Exam2.High := Exam2.High - 5.0;
    PrintStat (Exam2);
    

Programming

  1. Write a procedure to read in the data for a record variable of type CatalogueEntry. See Self-Check Exercise 2 at the end of Section 8.1.


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

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