Ada記錄的屬性

2018-10-28 09:50 更新

記錄則是由命名分量(named component)組成的復(fù)合類型,即具有不同屬性的數(shù)據(jù)對(duì)象的集合,和C 下的結(jié)構(gòu)(structure)、Pascal 下的記錄(record) 類似。Ada 的記錄比它們提供的功能更強(qiáng),也就是限制更少。同時(shí)記錄擴(kuò)展(record extension)是 Ada95 中類型擴(kuò)展(繼承)機(jī)制的基礎(chǔ),使記錄的地位更加突出,關(guān)于記錄擴(kuò)展詳見 第6章 面向?qū)ο筇匦?,為了避免重?fù),本章對(duì)此不作介紹。

Ada

簡(jiǎn)單記錄(Simple Record)

記錄類型的一般聲明如下:

type record_name is
record
field name 1: type 1;
field name 2: type 2;
...
field name n: type N;
end record;

record_name 是記錄類型的名稱,一大堆 filed name 是記錄的成員名稱,緊跟其后的是該成員的數(shù)據(jù)類型。

如下面的例子:

type Id_Card is
record
Full_Name : String (1..15);
ID_Number : Positive;
Age : Positive;
Birthday : String (1..15);
Familiy_Address : String (1..15);
Family_telephone : Positive;
Job : String(1..10);
end record;
My_Card :Id_Card;

一個(gè)簡(jiǎn)單ID卡的記錄,包含F(xiàn)ull_Name,ID_Number,Age,Birthday,F(xiàn)amiliy_Address,F(xiàn)amily_telephone,Job 這些成員。

訪問和設(shè)置記錄(Access and Set Records)

使用記錄的成員時(shí),只需在記錄和其成員之間用 “.” 隔開即可。如賦予My_Card中的變量 Full_Name 值 Jack Werlch:

My_Card.Full_Name := "Jack Welch ";

設(shè)置記錄成員的值和設(shè)置數(shù)組給人感覺上有點(diǎn)類似,如:

My_Card := ("Jack Welch ", 19830519,45, "Jan 1st 1976 ",
"China ",8127271,"CEO ");

將 ( )中的值依次賦給My_Card 的成員。

相同的數(shù)據(jù)類型的成員一多,無(wú)疑會(huì)使人不大明了,因此也可以:

My_Card := ( Full_Name => "Jack Welch ",
ID_Number => 19830519,
Age => 45,
Birthday => "Jan 1st 1976 ",
Familiy_Address => "China ",
Family_telephone => 8127271;
Job => "CEO ") ;

上面兩種表示法可以混用,但按位值在有名的值前面:

My_Card := ( "Jack Welch ",
19830519,
Age => 45,
Birthday => "Jan 1st 1976 ",
Familiy_Address => "China ",
Family_telephone => 8127271;
Job => "CEO ");

但如果為:

My_Card := ( Full_Name => "Jack Welch ",
ID_Number => 19830519,
Age => 45,
Birthday => "Jan 1st 1976 ",
Familiy_Address => "China ",
8127271;
"CEO ");

則是非法的。

如果幾個(gè)相同類型的成員,賦予同一數(shù)值,也可以:

My_Card := ( Full_Name => "Jack Welch ",
ID_Number | Family_telephone => 19830519,
Age => 45,
Birthday => "Jan 1st 1976 ",
Familiy_Address => "China ",
Job => "CEO ");

上例我們假設(shè) ID_Number 和 Family_telephone 值是一樣的,為19830519,不同成員間用 | 隔開。

記錄類型有時(shí)在聲明也需要默認(rèn)值:

type Id_Card is
record
Full_Name : String (1..100) := "Jack Welch ",
ID_Number : Positive := 19830519,
Age : Positive := 45,
Birthday: String (1..20) := "Jan 1st 1976 ",
Familiy_Address :String (1..100):= "China ",
Family_telephone :Positive := 8127271;
Job : String(1..10) := "CEO ");
end record;
My_Card :Id_Card;

將 Jack Welch 的資料當(dāng)作了 Id_Card 類型的默認(rèn)值,My_Card 無(wú)須賦值,在聲明時(shí)已經(jīng)有了前幾個(gè)例子中所賦的值。

聲明常量記錄如下:

My_Card :constant Id_Card := ( Full_Name => "Jack Welch ",
ID_Number => 19830519,
Age => 45,
Birthday => "Jan 1st 1976 ",
Familiy_Address => "China ",
Family_telephone => 8127271;
Job => "CEO ";)

和創(chuàng)建其它類型的常量類似,只需在該記錄類型前添個(gè) constant。

變體記錄 (Variant Record)

在講變體記錄前,先介紹一下記錄判別式(record discriminant)的概念。判別式(discriminant)以前沒接觸過,這里先簡(jiǎn)單提一下它的定義:一個(gè)復(fù)合類型(除了數(shù)組)可以擁有判別式,它用來確定該類型的參數(shù)(具體參見 RM95 3.7 Discriminant)。也就是說,一個(gè)復(fù)合類型創(chuàng)建時(shí)可以有一些參數(shù),在接下去聲明該類型的變量時(shí),可以通過那些參數(shù)的值來改變變量初始化時(shí)所占用內(nèi)存大小、成員數(shù)量、取值等等。這一節(jié)以及下一節(jié)的無(wú)約束記錄(unconstrained record)的內(nèi)容都在記錄判別式的范圍內(nèi),至于其它復(fù)合類型將在以后講述。

變體記錄,即它的一些成員存在與否取決于該記錄的參數(shù)。如我們將 Id_Card 這個(gè)記錄類型擴(kuò)充一下:

type Id_Card (Age : Positive := 1) is
record
Full_Name : String(1..15);
ID_Number : Positive;
Birthday : String(1..15);
Familiy_Address : String(1..15);
Family_telephone : Positive;
Job : String(1..10);
case Age is
when 1 .. 18 => School_Address : String(1..15);
when 19 .. 60 => Monthly_Income : Integer;
Working_Address: String(1..15);

when others => null; -- 如果 Age 的值不屬于 1..60,成員不改變

end case;
end record;
My_Card : Id_Card ;
Your_Card: Id_Card (Age => 20);

上例中,case Age ... end case 是變體部份,當(dāng) Age 值在 1..18 時(shí),動(dòng)態(tài)創(chuàng)建成員 School_Address;當(dāng) Age 值在 19..60 時(shí),動(dòng)態(tài)創(chuàng)建成員 Monthly_Income,Working_Address;當(dāng) Age 不在 1..60 時(shí),數(shù)據(jù)成員不改動(dòng)。在聲明判別式時(shí)一般應(yīng)賦予一個(gè)默認(rèn)值,如上例 Age 的默認(rèn)值為 1 ,這樣聲明變量 My_Card 時(shí)不帶參數(shù)也可以,默認(rèn)參數(shù)為 1。但如果 Age 沒默認(rèn)值,上例中的 My_Card 聲明是非法的。

因此,記錄 My_Card 有 Full_Name,ID_Number,Birthday,F(xiàn)amiliy_Address,F(xiàn)amily_telephone, Job,School_Address這些成員,因?yàn)?Age 默認(rèn)為 1; 記錄 Your_Card 中 Age 值為 20,因此有 Full_Name,ID_Number,Birthday,F(xiàn)amiliy_Address,F(xiàn)amily_telephone, Job, Monthly_Income,Working_Address 這些成員。

最后注意一下,變體部份要在記錄類型聲明的底部,不能在 Job 或其他成員前面---變體記錄的變量大小是不定的

無(wú)約束記錄(Unconstrained Record)

上面的記錄都是受限定的,如 創(chuàng)建 My_Card 后,它的判別式無(wú)法再被改動(dòng),Monthly_Income,Working_Address這些成員也無(wú)法擁有。但如果 ID_Card 的判別式有了初使值,則還有辦法使記錄動(dòng)態(tài)改變。

如:

type Id_Card (Age : Positive := 1) is
record
Full_Name : String(1..15);
ID_Number : Positive;
Birthday : String(1..15);
Familiy_Address : String(1..15);
Family_telephone : Positive;
Job : String(1..10);
case Age is
when 1 .. 18 => School_Address : String(1..15);
when 19 .. 60 => Monthly_Income : Integer;
Working_Address: String(1..15);
when others => null;
end case;
end record;

My_Card : Id_Card ;-- 以上和上一節(jié)的例子一樣

....

begin

...

My_Card := (17, "Jack Welch ", 19830519, "Jan 1st 1976 ", "China ",8127271,

"CEO ","Shanghai ");

end;

賦值的時(shí)候就有了點(diǎn)特殊。My_Card 在程序內(nèi)部賦值,但與常規(guī)賦值不同,它的第一個(gè)值是判別式的值,后面才是成員的值---成員數(shù)量按照判別式的值動(dòng)態(tài)改變,上例就多了一個(gè) School_Address 成員。這種情況下,編譯器會(huì)分配給 My_Card 可能使用的最大內(nèi)存空間。因此將下句接在上句后面:

My_Card := (17, "Jack Welch ", 19830519, "Jan 1st 1976 ", "China ",8127271,

"CEO ", 78112 ,"Shanghai ");

也是可行的。

上面一些記錄的例子并不好,成員的數(shù)據(jù)類型太簡(jiǎn)單(像生日的數(shù)據(jù)類型,一般是年月日做成員的一個(gè)記錄),字符串類型太多,手工賦值的話還要數(shù)一下有幾個(gè)字符,實(shí)際中也很少這樣的用法,一般還是用函數(shù)來賦值。這點(diǎn)請(qǐng)注意一下。

判別式的其它用途

判別式的另一個(gè)用途是動(dòng)態(tài)決定其成員長(zhǎng)度,如:

type Buffer (Size:Integer) is
record
High_Buffer(1..Size);
Low_Buffer(1..Size);
end record;

這樣 Buffer 兩個(gè)成員的大小就取決于 Size 值,在文本處理中這種用法還是挺好的。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)