CS 214 Lab 7: Ada


Begin by copying the program skeleton average.adb from the class directory into your new directory. Then use your favorite text editor to open the file, and take a moment to study it, to see how much of our basic algorithm it implements.

Ada is far more concerned with type-safety than C++, and so a bit more care is required to use its arrays. More precisely, if we wish to pass an array to a subprogram, Ada requires the argument array and the parameter array to be declared using the same type-name. We will therefore begin by declaring an array type named Vector, capable of storing an arbitrary number or Float values.

Array Declarations

In Ada, a new type can be declared using the form:

   TypeDec         ::= type identifier is TypeStructure ;
where identifier is the name of the type being declared, and TypeStructure defines the structure of the new type. For a 1-dimensional array type, Ada permits a variety of structures fitting the following pattern:
   TypeStructure      ::= array ( IndexDef ) of ElementType
   IndexDef           ::= ConstrainedRange | UnconstrainedRange
   ConstrainedRange   ::= ConstantExpression .. ConstantExpression
                          | DiscreteTypeId
   UnconstrainedRange ::= DiscreteTypeId range <>
Since we wish to define an unconstrained array type (i.e., an array type that can be an arbitrary size), we apply these rules and add the following type declaration to the beginning of average.adb:
   type Vector is array ( Positive range <>) of Float;
With this statement, we are declaring Vector as the name of a new type, whose structure is an array indexed by Positive (but unspecified) integers, and whose elements are Float values. Note that unlike C++, Ada uses parentheses for its arrays.

Now that we have our Vector array type declared, we can proceed to use this type to declare our array variables. Recall that Ada variable declarations have the form:

   VariableDec       ::= IdentifierList : Type Initializer ;
   IdentifierList    ::= identifier MoreIds
   MoreIds           ::= , identifier MoreIds | Ø
   Initializer       ::= := ConstantExpression
To initialize the elements of an array variable to specific values, we need to know Ada's syntax for an array literal, which is as follows:
   ArrayLiteral      ::= ( Expression, Expression MoreExpressions )
                         | (Expression MoreExpressions , others =>Expression )
   MoreExpressions   ::= , Expression MoreExpressions | Ø
Ada will not allow us to create an array whose size is zero (or even one), so use this information to define array0 as a Vector containing two zero values; and define array1 as a Vector variable initialized to the values 9.0, 8.0, 7.0, 6.0. Note that when an unconstrained array-type variable is initialized using an array literal, the size of the array is the number of values in the literal.

Subprograms with Array Parameters

To write subprogram average(), we must declare an array parameter, and check its length: if its length is zero, return 0.0; otherwise compute the sum of the values in that array and return that sum divided by the number of values in the array. Since the subprogram returns a single value, we define it as a function subprogram.

An array parameter can be declared using syntax similar to that of a normal array object:

   FunctionParamDec ::=   IdentifierList : Type
Ada arrays are "smarter" than C++ arrays (i.e., they know their size). We therefore need pass no other information beyond the array itself.

Recalling that Ada functions have this form:

   FunctionDef     ::=   function identifier( ParameterDecList ) return Type is
                            Declarations
                         begin
                            Statements
                         end identifier;
use the preceding information to define a stub for our function, so that it has a single parameter named anArray of type Vector, and returns a Float value.

To fill in the body of the function, we can use the Ada if statement to check the value of the size of anArray. Ada arrays have a number of attributes, some of which are as follows:

   ArrayAttributeExpr ::= identifier ' Attribute
   Attribute          ::= Length | First | Last | Range | ...
These attributes may be used as follows: for an array variable A: Use this information to implement the if statement required by our algorithm for function average().

To sum the values in anArray, we will need to implement our own sum() function. This function will need a local variable total in which to accumulate the sum of the array's values, and will use the ada for-loop to iterate through the array's index values. Recall that the syntax of the for loop is

  ForLoop        ::= for identifier in Range
                     loop
                         Statements
                     end loop
where Range specifies the range of values through which identifier is to iterate. Using this information, we can implement the Sum() function as follows:

  function sum(A: Vector) return Float is 
    Total : Float := 0.0; 
  begin 
    for I in A'Range 
    loop 
      Total := Total + A(I); 
    end loop; 
    return Total; 
  end sum; 
Ada requires that every identifier be declared before it is used. Since our average() function will use sum(), this means that you should define sum() before the definition of average().

You now have most of the functionality needed to complete the average() function in average.adb. Do so, including the necessary documentation for the function.

The one remaining problem is that Ada does not permit us to mix integers and reals in an arithmetic expression, so the division of the sum of the values in the array (a real) by the number of values in the array (an integer) generates a compilation error. To resolve this without losing any information, we should convert the (integer) number of values to a real value. This can be accomplished by using the Float() conversion function. The expression:

   Float( IntegerExpression )
will convert IntegerExpression into a real value. Use this within your division subexpression to convert the number of values in the array from an integer to a real.

Compile and test your code for correctness. When this much is correct, continue to the following experiment.

Experiment. Because we used A'Range in the for loop of sum(), we did not have to specify index values for anArray. Comment out the first line of your for loop (the line that refers to A'Range). Replace it with an equivalent line that uses a ConstrainedRange (see the BNF above), starting with the index of the first element of anArray, ending with the index of its last element. Then recompile and retest your code for correctness.

To Turn In. When your program uses these values correctly, use script to create a file in which you cat your file, compile it, and show that it works correctly.

That concludes the Ada part of this lab.


Calvin > CS > 214 > Labs > 07 > Ada


This page maintained by Joel Adams.