COMPOUND DATA TYPES AND ARRAYS


1. INTRODUCTION TO COMPOUND DATA TYPES

The available basic types can be extended by adding compound types made up of existing basic types (and/or other compound types). Compound types are usually programmer defined. There are some standard compound types which can be constructed in most imperative languages. These include:

  1. Arrays
  2. Strings
  3. Records

We will be discussing the first two of these.


2. ARRAYS

The most straight forward (and oldest) form of compound data type is the array. All the types we have considered so far have been scaler (data items of the types considered can only have one value). In an array a data item consists of a numbered collection of similar components. As such it can be viewed as simply a series of data items, all of the same type, stored in a series of locations in memory such that a single value is held at each location.

ARRAY STRUCTURE

2.1. Features of arrays

  1. Items in arrays are called elements.
  2. Specific elements in an array can be identified through the use of an index
  3. In Ada indexes must be discrete (e.g. integers, characters or "enumerated" values).
  4. The first index in an array is called the lower bound and the last the upper bound.

3. ARRAY DECLARATIONS

When declaring arrays we are doing two things:

  1. Declaring the type of the array.
  2. Declaring the nature of the index

In Ada, to declare an array data item we use a declaration statement of the form:

DATA_ITEM_NAME : array  <index_definition> of TYPE ;

Alternatively we can create an array data type as follows:

type ARRAY_TYPE_NAME is array  <index_definition> of TYPE ;

and then create an "instance" of this type:

DATA_ITEM_NAME : ARRAY_TYPE_NAME ;

The keyword array used here is often referred to as a type constructor in that it "constructs" a particular type (an array type in this case). Indexes in Ada can then be defined in a number of ways as follows:

  1. In terms of a lower and upper bound only. Format:
    (LOWER_BOUND..UPPER_BOUND)
    
    Example declarations:
    ARRAY1  : array (1..10) of INTEGER ;
    
    type ARRAY_T1 is array ('A'..'Z') of INTEGER ;
    ARRAY2  : ARRAY_T2 ;
    
    N_VALUE : INTEGER ;
    LENGTH  : constant INTEGER := 4;
    ARRAY3  : array (N_VALUE..N_VALUE+LENGTH) of FLOAT ;
    
    START_VALUE : CHARACTER := 'A';
    END_VALUE   : CHARACTER := 'Z';
    type ARRAY_T1 is array (START_VALUE..END_VALUE) of CHARACTER ;
    ARRAY4      : ARRAY_T4
    
  2. In terms of the index type supported by a lower and and upper bound. Format:
    (INDEX_TYPE range LOWER_BOUND..UPPER_BOUND)
    
    Example declaration:
    ARRAY3 : array (CHARACTER range 'a'..'z') of INTEGER;
    
    N_VALUE : INTEGER ;
    LENGTH  : constant INTEGER := 10;
    type ARRAY_TYPE3 is array (NATURAL range N_VALUE..N_VALUE+LENGTH)
                    of FLOAT;
    
  3. In terms of a particular data type. Format:
    (INDEX_TYPE)
    
    Example declaration:
    type ITEMS is range 1..100;
    ARRAY4 : array (ITEMS) is FLOAT;
    
    type INDEX_TYPE is range 'x'..'z';
    type ARRAY_TYPE4 is array (INDEX_TYPE) of INTEGER;
    

4. ASSIGNMENT

Given knowledge of the index for an array element we can assign a value to that element (or change its value) using an "assignment" operation. Example:

ARRAY1(1):= 4;

Here we have an array data item (named ARRAY1) and we have assigned a value of 4 to element 1 of this array. Note how we have specified the element number using the parenthesised notation.

Ada also supports the concept of array aggregates which allow all the elements of an array to be assigned to simultaneously on initialisation:

MY_ARRAY : array (1..10) of integer := (9, 8, 7, 6, 5, 4, 3, 2, 1, 0);

or during processing:

MY_ARRAY := (9, 8, 7, 6, 5, 4, 3, 2, 1, 0);

In both cases we have assigned the sequence of integers from 9 to 0 to a 10 element array data item.

Ada also supports a short hand whereby we can assign assign the same value to a sequence of elements as follows:

MY_ARRAY:= (5, 4, 3, 2, 1, other => 0);

or

MY_ARRAY:= (other => 9);

5. EXAMPLE PROBLEM METRES TO YARDS FEET AND INCHES CONVERSION


5.1 Requirements

Design and create an Ada program that, when presented with a distance given in Metres converts it to a distance measure comprising Yards, Feet and Inches (1 Metre = 39.37 Inches). Output the result in whole Yards, Feet and inches. Assume that the distance to be processed is a posetive integer between 1 and 1x10^6 Metres.


6.2 Design

A top-down analysis of the proposed problem is given below.

TOP DOWN ANALYSIS

We will represent the imperial distance using a user defined type IMPERIAL_DIST comprising a three element with indexes of type INTEGER and elements of type NATURAL. We can then identify the following procedures:

  1. DISTANCE_CONVERSION (top level procedure): Input, call to CONVERT and OUTPUT. Include type definition for IMPERIAL_DIST.
    NAMEUSAGETYPERANGE
    METRESINPUT_VARIABLEPOSITIVE1..1000000
    YFI_DISTLocal variable (array)IMPERIAL_DISTn.a.
  2. CONVERT (level 2 function): Convert to inches and then to imperial units. Return value of type IMPERIAL_DIST.
    NAMEUSAGETYPERANGE
    METRESFormal parameterPOSITIVEDefault
    INCHESLocal variableFLOATDefault
    YFIReturn variable (array)IMPERIAL_DISTn.a.
  3. OUTPUT (level 2 procedure): Output array result.
    NAMEUSAGETYPERANGE
    YFI_OUTPUTFormal parameter (array)IMPERIAL_DISTn.a.

A complete Nassi-Shneiderman design for the above is given below:

NASSI_SHNEIDERMAN CHART

5.3. Implementation

-- DISTANCE CONVERSION
-- 15 August 1997
-- Frans Coenen
-- Dept Computer Science, University of Liverpool

with TEXT_IO;
use TEXT_IO;

procedure DISTANCE_CONVERT is
    LOWER_BOUND       : constant := 1;
    UPPER_BOUND       : constant := 3;
    CONVERSION_FACTOR : constant := 39.37;
    package FLOAT_INOUT is new FLOAT_IO(FLOAT);
    use FLOAT_INOUT;
    package INTEGER_INOUT is new INTEGER_IO(INTEGER);
    use INTEGER_INOUT;
    type IMPERIAL_DIST is array (LOWER_BOUND..UPPER_BOUND) of NATURAL;
    METRES   : POSITIVE range 1..1000000;
    YFI_DIST : IMPERIAL_DIST;

    ------------------------------------------------------------
    -- CONVERT
    function CONVERT(METRES: POSITIVE) return IMPERIAL_DIST is
        INCHES : FLOAT;
        YFI    : IMPERIAL_DIST;
    begin
    -- Metes to inches
        INCHES := FLOAT(METRES)*CONVERSION_FACTOR;
    -- Yards
        YFI(1) := INTEGER(INCHES/36.0-0.5);
        INCHES := INCHES - FLOAT(YFI(1)*36);
    -- Feet
        YFI(2) := INTEGER(INCHES/12.0-0.5);
    -- Inches
        YFI(3) := INTEGER(INCHES - FLOAT(YFI(2)*12));
        RETURN(YFI);
    end CONVERT;
    ------------------------------------------------------------
    -- OUTPUT
    procedure OUTPUT(YFI_OUTPUT: IMPERIAL_DIST) is
    begin
        PUT(YFI_OUTPUT(LOWER_BOUND));
        PUT(" Yards, ");
        PUT(YFI_OUTPUT(LOWER_BOUND+1));
        PUT(" Feet, ");
        PUT(YFI_OUTPUT(LOWER_BOUND+2));
        PUT_LINE(" Inches");
    end OUTPUT;
    ------------------------------------------------------------

-- TOP LEVEL
begin
    PUT_LINE("Input distance in Metres and decimals of Metres:");
    GET(METRES);
    NEW_LINE;
    YFI_DIST := CONVERT(METRES);
    OUTPUT(YFI_DIST);
end DISTANCE_CONVERT;

Note. We have subtracted 0.5 in the arithmetic expressions INTEGER(INCHES/36.0-0.5) and INTEGER(INCHES/12.0-0.5) because the INTEGER conversion function rounds to the nearest whole integer. In this case we do not want this to happen.


6.4. Testing

TEST CASEEXPECTED RESULT
METRESOUTPUT
0CONSTRAINT_ERROR
1{1, 0, 3}
2{2, 0, 7}
999999{1093610, 0, 1}
1000000{1093611, 0, 4}
1000001CONSTRAINT_ERROR

6.4.1 Black Box Testing

BVA and Limit Testing: A set of appropriate Limit and BVA test cases are presented in the table to the right.

Arithmetic testing: We should include test cases to ensure correct operation of arithmetic expressions. In this case it is appropriate to test each such expression with positive and zero sample values where applicable. Some of this is taken in to consideration by the above BVA and Limit tests. However, we should include a test where a positive number of feet result (rather than zero). An appropriate test case is given in the table below.

TEST CASEEXPECTED RESULT
METRESOUTPUT
4{4, 1, 1}

Example Problem Metres to Yards, Feet and Inches Conversion Report.




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