Arrays
Arrays: Overview
Two Sample Programs
- printall.adb (prettified) - This program reads 10 integers and
prints them and their squares, forward and in reverse.
- printsome.adb (prettified) - This program reads 10 integers and
prints them and their squares, forward and in reverse.
Simple Array Declaration
- Array bounds can be any integers:
procedure demo is
squares: array (1 .. 10) of integer;
begin
for i in 1 .. 10 loop
squares(i) := i ** 2;
end loop;
end demo;
Array Bounds are Flexible
- Array bounds can be any integers:
procedure demo is
squares: array (-10 .. 10) of integer;
begin
for i in -10 .. 10 loop
squares(i) := i**2;
end loop;
end demo;
Later we will see that other types of bounds are possible
Aggregate Assignment
- An entire array can be assigned in one statement
procedure demo is
squares: array (1 .. 5) of integer;
begin
squares := (1, 4, 9, 16, 25); -- aggregate assignment
for i in 1 .. 10 loop
put(squares(i));
end loop;
end demo;
Note that the size of the aggregate must match the declaration
Aggregate Assignment with Keywords
- Can use indices to specify elements of array in the aggregate value
procedure demo is
values1: array (1 .. 50) of integer;
values2: array (1 .. 50) of integer;
begin
values1 := (2 => 4, 4 => 16, 5 => 25, 3 => 9, others => 0); -- set remaining to 0
values2 := (others => 0); -- set all to 0
end demo;
Aggregate: Compared with Java
- Java uses the aggregate to define the size:
int[] a = {1, 4, 9, 16, 25}
Java only allows the aggregate in the declaration
Java has a strange syntax
int[] a = {1, 4, 9, 16, 25,} // How big is this array?
Array Types
- squares has an anonymous type
- More common to create a named array type
- Example:
procedure demo is
type IntArray is array(1 .. 10) of Integer;
squares: IntArray;
cubes: IntArray;
begin
for i in 1 .. 10 loop
squares(i) := i**2;
cubes(i) := i * squares(i);
end loop;
end demo;
Advantages of Named Array Types
- Easy to make changes to your code
- Required for parameters of array types:
procedure demoArrayError is
-- Declare a new type
type IntArray is array (1 .. 10) of Natural;
procedure p(a: IntArray) is -- named type required
begin
put(a(1));
end p;
-- Declare a variable
myArray: IntArray;
begin -- demo
p(myArray);
end demoArrayError;
Error message - This statement:
procedure p(a: array(1..10) of integer) is
- causes this error: anonymous array definition not allowed here
Can do assignment and equality tests on arrays
Array Assignment and Equality Tests
- Can perform assignment and equality tests on arrays
type Myarray is array (1 .. 3) of Integer;
a, b: Myarray;
...
a := (10, 20, 30);
b := (others => 0);
if a = b then ...
b := a;
if a = b then ...
Only allowed if both operands are of the same named type
Equality test does an element by element equality test
Assignment does an element by element assignment
Java Array Operations
- How does this compare to the Java:
int[] a = {10, 20, 30};
int[] b = {0, 0, 0};
if (a == b) ...
a = b;
if (a == b) ...
Reference and Value Semantics
- When describing element by element operations, we say that Ada has value
semantics
- When describing reference operations, we say that Java has reference
semantics
- Semantics refers to the meaning of a statement
Array Attributes
- Attributes of array types:
- 'first
- 'last
- 'range
- 'length
- Attributes of array variables:
- 'first
- 'last
- 'range
- 'length
- Example:
procedure demo is
type IntArray is array(2 .. 5) of Integer;
squares: IntArray := (4, 9, 16, 25);
begin
put(IntArray'length);
put(IntArray'last);
put(squares(IntArray'first));
for i in IntArray'range loop
put(squares(i));
end loop;
put(squares'length);
put(squares'last);
put(squares(squares'first));
for i in squares'range loop
put(squares(i));
end loop;
end demo;
Filling the array using integer_text_io.Get (sumcountprocs2.adb)
Fixed Bounds
- Array bounds are fixed at COMPILE TIME and cannot be changed
a: array(1 .. 10) of integer;
...
a: array(1 .. 5) of integer; -- ERROR
Procedures only work for given size array
type ArrayType1 is array(1 .. 10) of integer;
type ArrayType2 is array(1 .. 20) of integer;
procedure putArray(a: ArrayType1)
-- Doesn't work for ArrayType2
How can we gain more flexibility: Unconstrained arrays
- With declare/begin/end blocks (see below)
- As parameters
Declare Blocks
- Variables can be declared anywhere - with a declare/begin/end block
- Example:
procedure declare_example is
size: natural;
begin
get(size);
declare
a: array(1 .. size) of Integer;
begin
for i in a'range loop
get(a(i));
end loop;
end;
-- put(a'last); -- Error. Out of scope
end declare_example;
Scope of a is the declare block
Unconstrained Arrays
- Allow postponing definition of exact bounds of an array
- Example (Actual bounds must be a range of Naturals):
type IntArray is array(Natural range <>) of Integer;
Array bounds are given when actual array is declared:
type IntArray is array(Natural range <>) of Integer;
myArray1: Intarray(1 .. 4) := (10, 20, 30, 40);
myArray2: Intarray(1 .. 5) := (10, 20, 30, 40, 50);
Variables of unconstrained types can be compared and
assigned:
procedure tryunc is
type IntArray is array(Natural range <>) of Integer;
myArray1: Intarray(1 .. 4) := (10, 20, 30, 40);
myArray2: Intarray(1 .. 5) := (10, 20, 30, 40, 50);
begin
if myArray1 = myArray2 then -- What happens here?
put_line("same");
else
put_line("diff");
end if;
myArray2 := myArray1;
end tryunc;
Equality tests are okay.
Assignment gives a warning and raises runtime error if sizes
are different.
Unconstrained Arrays as Parameters
- Unconstrained arrays are particularly useful as parameters
procedure tryunc is
type IntArray is array(Natural range <>) of Integer;
function sumEmUp(a: IntArray) is
sum: Natural := 0;
begin
for i in a'range loop
sum := sum + a(i);
end loop;
return sum;
end sumEmUp;
myArray1: Intarray(1 .. 4) := (10, 20, 30, 40);
myArray2: Intarray(1 .. 5) := (10, 20, 30, 40, 50);
begin
put(sumEmUp(myArray1));
put(sumEmUp(myArray2));
end tryunc;
Allows declaring parameters that can be arrays of any size
- Attributes are useful (ie necessary!) in getting the sizes
Declare Blocks and Unconstrained Arrays
- We can combine declare blocks and unconstrained arrays?
- Example:
with ada.text_io; with ada.integer_text_io;
use ada.text_io; use ada.integer_text_io;
procedure declare_example2 is
type My_Array_Type is array(Natural range <>) of Integer;
procedure put(a: My_Array_Type) is
begin
for i in A'range loop
put(a(i));
end loop;
end put;
size: natural;
begin
get(size);
declare
a: My_Array_Type(1 .. size);
begin
for i in a'range loop
get(a(i));
end loop;
put(a);
end;
end declare_example2;
Concatenation
procedure tryunc is
type IntArray is array(Natural range <>) of Integer;
function sumEmUp(a: IntArray) is
sum: Natural := 0;
begin
for i in a'range loop
sum := sum + a(i);
end loop;
return sum;
end sumEmUp;
myArray1: Intarray(1 .. 4) := (10, 20, 30, 40);
myArray2: Intarray(1 .. 5) := (10, 20, 30, 40, 50);
begin
put(sumEmUp(myArray1 & myArray2));
end tryunc;
Strings
- Strings are declared to be unconstrained arrays of characters
type String is array(Natural range <>) of Character;
More information on Strings is here
Where is String declared??
Explains why this works:
if s(i .. j) = s(k .. l) then
Array Slices
- Any array can be sliced (ie treat a subarray as the entire array)
- Example:
s: String := "Hi Mom!");
put(s(3 .. 5) & "?");
s(4) := 'T';
put(s);
s(4 .. 6) := "Bob";
put(s);
s(4 .. 4) := "R";
put(s);
Note that strings are mutable
- In contrast, Java strings are immutable
Pictures of execution show value semantics
More on slices
Multidimensional Array
- Ada has true multidimensional arrays
- It also has arrays of arrays, which is like Java
- Need to finish these notes ...