Ada数组的类型
数组是一种复合数据类型(composite type),包含多个同一种类型的数据元素。数组元素的名称用指定的下标表示,这些下标是离散数。数组的值则是一个由这些元素的值构成的合成值(composite value)。Ada 下的数组和其它语言很相似,只是多了一些“宽松”的规定,如无约束数组、动态数组,更加方便了用户。字符串类型 String,Wide_String 等则是数组元素为字符型的数组类型。
简单数组(Simple Array)
数组类型的一般声明格式如下:
type array_name is array (index specification) of type;
array_name 是该数组类型的名称;index specification 指明该数组类型的元素下标;type 是已经定义了的一个数据类型,表示每个元素的数据类型。
通常情况下,数组类型的使用方式和下例相同:
type Total is range 1 .. 100; -- 声明一个整型 Total,取值范围 1..100。
type Wages is array (Total) of Integer;-- 声明一个数组类型Wages,该类型有100个Integer元素。
Unit1 : Wages; -- 声明一个Wages类型的变量 Unit1,具有100个 Integer 元素,下标取值 1 .. 100。
Wages 的声明也可改为
type Wages is array (1 .. 100) of Integer;
效果是一样的,只是从维护性的角度来讲还是由 Total 来决定 Wages 的下标比较好。
Ada 数组的 index specification 是离散数,可以是一个范围,也可以是枚举类型,而不是单纯的一个表示数组大小的数值,这点和 C 、Pascal 有所区别 。数组元素的下标也不需要一定从 0 或从 1 开始,例如:
type First_Name is( Bill, Jack, Tom );
type Enrollment is array ( First_Name ) of Integer;
Var : Enrollment; -- 数组 Var 有 3 个 Integer 元素,Var (Bill)、Var (Jack)、Var (Tom)。
type NO is array (-5 .. 100) of Integer;
X : NO; -- 数组 X 有 105 个 Integer 元素,第一个元素是 X (-5),最后一个是 X (100)。
匿名数组(Anonymous Array)
如果嫌上一节中的 Unit1 的声明过程麻烦,也可以直接声明:
Unit1 : array (1 .. 100) of Integer;
虽然更为精简了,但不推荐这样使用数组。这种数组没有明确的类型,被称为匿名数组(anonymous array),既不能作为子程序的参数,也无法同其它数组混用----即使声明一样。通常情况下应避免出现这种情况
无约束数组(Unconstrained Array)
像上面的例子,数组有几个元素在声明数组类型时已经决定,而不是在声明该类型的数组变量时决定,当然这样的好处是明确的知道每个数组会占用多少空间,控制起来也方便。但如同我们先前提及的一样,字符串类型 String,Wide_String 是数组类型,而用户输入的字符串却是不定的,如果它们的长度也预先定好了,使用字符串时无疑会造成内存空间浪费或不够用,这时一般是使用无约束数组---其声明和一般数组类型相同,只是没有规定它的长度---其长度在声明该类型的数组变量时决定。
如 String 类型的声明:
subtype Positive is Integer range 1..Integer'Last;
type String is array (Positive range <>) of Character;
type Wide_String is array (Positive range <>) of Wide_Character;
< > 表示当声明该无约束数组类型的变量时,需要在( )中指定一个范围。如创建一个变量 Path_Name, 长度为1024:
Path_Name: String (1 .. 1024);
如果没有指定该数组的大小,如:
Path_Name: String;
是不合法的。
当然范围也无须从 1 开始,Path_Name:String (7..1030) 和上例表示的字符串长度一样,只是下标不同而已。如果有一个函数 Get_Path (Path_Name :in out String),将当前路径名赋给参数 Path_Name,只要是 String 类型的参数就可以通用,长度也无须计较---函数出错或不处理不符合长度要求的字符串则是另一回事。
这里强调一下字符串类型的赋值问题,假如将 Path_Name 赋予"/root/",可以在一开始就赋值:
Path_Name :String := "/root/";
这样 Path_Name 的长度就自动成为6。但如果
Path_Name :String(1..10) := "/root/";
则会引起错误(看上去很正确),因为还缺4个字符,应为
Path_Name :String(1..10) := "/root/ ";
或采用从理论上讲麻烦点实际上根本不会这么做的方案:
Path_Name:String (1..10);
Path_Name(1) := '/';
Path_Name(2) := 'r';
...
Path_Name(6) :='/';
这点是和其它语言有所不同,也是很不方便的一点
动态数组 (Dynamic Array)
数组大小也可以在运行时动态决定,而不是在程序的源代码中就决定。如:
X : Positive := Y;
Var : array (1 .. X) of Integer;
这样 Var 的大小就由 X 来决定了,X 多大它也多大。只是这样做相当不妙,假设 Y 值是用户输入的,它的大小,甚止于输入的到底是什么,就根本无法确定,如果过大或负数或非Positive 类型都会产生麻烦。一般情况下还是用在子程序中:
procedure Demo (Item :string) is
copy : String(Item'First..Item'Last) := Item;
double: String(1..2*Item'Length) := Item & Item; --Item'First,Item'Last等都是数组属性,& 是将两个字符串相连,参见下文。
begin
...
end Demo;
这样的话,对于动态数组的操作与用户没有多大关系,保证了安全性
多维数组(Multidimensional Array)
前面提及的数组用法对多维数组也适用,只是多维数组的声明和元素的表示略有不同。如定义一个矩阵:
type Marix is array (1 .. 100,1..100) of Integer;
Var :Marix;---Var有 100x100个元素,分别为 Var(1,1),Var(1,2)....Var(100,99),Var(100,100)。
上例的Matrix是二维数组,多维数组的 index_specification 由多个范围组成,每个范围由,隔开。