# 6 Arrays

## Overview

Most languages provide arrays of one sort of another. Those provided by Ada are most similar to Pascal's, with the inclusion of several very handy features.

Unconstrained arrays, dynamic arrays and array attributes are some of the extras offered.

## Simple arrays

Generally when declaring an array, a type definition would be created first, and an array would be declared using this definition.

```type Stack is array (1..50) of Integer;
Calculator_Workspace : stack;

type stock_level is Integer range 0..20_000;
type pet is (dog,budgie,rabbit);
type pet_stock is array(pet) of stock_level;

store_1_stock:pet_stock;
store_2_stock:pet_stock;
```

In general the declaration of an array has this form:

```type array_name is array (index specification) of type;
```

Some points to note:

* The index specification can be a type (e.g. pet).

* The index specification can be a range (e.g. 1..50).

Index values must be of a discrete type.

## Anonymous arrays

Arrays can also be declared directly, without using a predefined type.

```no_of_desks : array(1..no_of_divisions) of integer;
```

This is known as an anonymous array (as it has no explicit type) and is incompatable with other arrays - even those declared exactly the same. Also they cannot be used as parameters to subprograms. In general it is better to avoid them.

## Accessing and setting arrays

To access an element of an array

```if store_1_stock(dog) > 10 then ...
```

It is instructive to note that accessing an Ada array is indistinguishable from calling a function in all respects.

To store a value into an array...

```store_2_stock(rabbit) := 200;
```

## Array aggregates

The values of an array can all be assigned at once, using an aggregate. An aggregate must specify a value for every array element.

```store_1_stock := (5,4,300);
```

The values in the aggregate are assigned in order to the values in the array.

It is also possible to use a named version of the aggregate where the individual elements of the array are named.

```store_1_stock := (dog => 5, budgie => 4, rabbit => 300);
```

It is illegal to combine both notations in the one aggregate.

```store_1_stock := (5,4,rabbit=>300);	-- illegal
```

Aggregates can also be used in declarations in exactly the same manner, using either notation.

```store_1_stock:pet_stock := (5,4,300);
```

A discrete range can also be included in the aggregate.

```store_1_stock := (dog..rabbit=>0);
```

The others option is particuarly useful in setting all elements of an array to a given value. In these situations type qualification is often required.

```new_shop_stock:pet_stock := (others := 0);
```

Consider the following declarations:

```declare	type numbers1 is array(1..10) of integer;	type numbers2 is array(1..20) of integer;	a	:numbers1;	b	:numbers2;begin	a := (1,2,3,4, others => 5);end;
```

The Ada language doesn't like this; if you mix the others option with either positional or named association then you have to qualify it with a type mark:

```a: = numbers1'(1,2,3,4, others => 5);
```

## Constant arrays

Constant arrays can be defined. In this case all elements should be initialised through the use of an aggregate when declared.

```type months is (jan, feb,mar,....,dec);subtype month_days is integer range 1..31;type month_length is array (jan..dec) of month_days;days_in_month:constant month_length := (31,28,31,30,...,31);
```

## Array attributes

Attributes associated with arrays are as follows.

```array_name'first	-- lower bound of the arrayarray_name'last	-- upper bound of the arrayarray_name'length 	-- the number of elements in the array			-- array_name'last-array_name'first +1array_name'range	-- the subtype defined by			-- array_name'first . . array_name'last
```

If the array is multi dimensional then the index should be specified e.g. array_name'range(n) supplies the range for the nth index.

This facility is very useful for stepping through arrays

```for i in array_name'range loop
...
end loop
```

This guarantees that every element will be processed.

## Unconstrained array types

Unconstrained array types allow us to declare array types that are identical in all respects to normal array types except one - we don't declare how long they are.

The declaration of an unconstrained array defines a class of arrays that have the same element type, the same index type and the same number of indices.

```subtype positive is integer range 1..integer'last;
type string is array (positive range <>) of character;
```

The <> represents a range that has to be specified when a variable of type string is declared (filling in the blank when declaring a variable).

The type string can be used to define a large class of character arrays, identical except in the number of elements in the array.

To create an actual array, we have to provide a index constraint for the type.

```My_Name : String (1..20);
```

Here the index constraint is the range 1..20. The advantage of this is that all strings declared are of the same type, and can thus be used as parameter to subprograms. This extra level of abstraction allows for more generalised subprograms.

To process every element of an a variable that is derived from an unconstrained array type requires the use of array attributes such as a'range, a'first etc. as we cannot be sure what index values incoming arrays may have, such as below.

```My_Name    : String (1..20);
My_Surname : String (21..50);
```

Unconstrained arrays are typically implemented with an object that stores the bounds, as well as a pointer to the actual array.

## Standard array operations

There are several operations that can be applied to arrays as a whole and not just the individual components.

## Assignment

An entire array can be assigned the value of another array. Both arrays must be of the same type. If they are of the same unconstrained type then they both must have the same number of elements.

```declare	my_name	:string(1..10)	:="Dale      ";	your_name	:string(1..10)	:="Russell   ";	her_name	:string(21..30)	:="Liz       ";	his_name	:string(1..5)	:="Tim  ";begin	your_name := my_name;	your_name := her_name;	-- legal, both have same number of					-- elements	his_name  := your_name;	-- will cause an error, same type but 		          		-- different lengthend;
```

## Test for equality, inequality

The tests for equality and inequality are available for (almost) every Ada type. Two arrays are equal if each element of the array is equal to the corresponding element of the other array.

```if array1 = array2 then....
```

## Concatenation

Two arrays can be concatenated using the & operator.

```declare
type vector is array(positive range <>) of integer;

a	: vector (1..10);
b	: vector (1..5):=(1,2,3,4,5);
c	: vector (1..5):=(6,7,8,9,10);
begin
a := b & c;
Put_Line("hello" & " " & "world");
end;
```

## Ordering operations

The operators <,<=,>,>= can all be applied to one dimensional arrays. They are of most benefit when comparing arrays of characters.

```"hello" < "world"	-- returns true
```

## Dynamic arrays

The length of an array can be determined at run time, rather than being specified by the programmer when writing the program.

```declare	x	: Integer := y	--y declared somewhere else	a	: array (1..x) of integer;begin	for i in a'range loop		...	end loop;end;procedure demo(item	:string) is	copy	:string(item'first..item'last) := item;	double:string(1..2*item'length) := item & item;begin	...
```

Note that this does not easily allow the user's input to decide the size of the array, and should not be thought of as a device for achieving this. The second example is much more typical of it's use.

to the index...