在 Ada 子程序的 “is”和“end”之間,是一組有序語(yǔ)句,每句用雙引號(hào);結(jié)束。這些語(yǔ)句大致可分成三種控制結(jié)構(gòu):順序結(jié)構(gòu),選擇結(jié)構(gòu),循環(huán)結(jié)構(gòu)----如果按照前輩們辛辛苦苦的證明:任何程序都可以只由這三種結(jié)構(gòu)完成。以前我們見過(guò)的簡(jiǎn)單程序都是順序結(jié)構(gòu),本章里會(huì)介紹一下 Ada 里選擇結(jié)構(gòu)的if、case 語(yǔ)句和循環(huán)結(jié)構(gòu)的 loop 語(yǔ)句及其變種,并介紹順序結(jié)構(gòu)中以前沒講過(guò)的 null 和塊語(yǔ)句(block statement),最后是比較有爭(zhēng)議的 goto 語(yǔ)句---好像每本教科書上都罵它,說(shuō)它打破了程序的良好結(jié)構(gòu)??刂平Y(jié)構(gòu)是一門老話題,Ada95 對(duì)它也沒作多大改動(dòng),語(yǔ)法上和其它語(yǔ)言還是很接近的,但可讀性好一點(diǎn),所有控制結(jié)構(gòu)后都以"end something"結(jié)束。
if 語(yǔ)句判斷一個(gè)條件是否成立,如果成立,則執(zhí)行特定的語(yǔ)句,否則跳過(guò)這些語(yǔ)句。一般格式如下:
if condition then
statements
end if;
當(dāng) condition 的值為 True 時(shí),則執(zhí)行 statements,否則跳過(guò) statements,執(zhí)行“end if”后面的語(yǔ)句。
如果當(dāng) condition 為 False 也要執(zhí)行特定語(yǔ)句,則用下面的格式:
if condition then
statements
else
other statements
end if;
這樣當(dāng)條件不成立時(shí),執(zhí)行other statement,而不是跳過(guò) if 結(jié)構(gòu)。
下面一種格式是為了多個(gè)條件判斷而用,防止 if 語(yǔ)句過(guò)多:
if condition then
statements
elsif condition then
other statements
elsif condition then
more other statements
else
even more other statements
end if;
使用 elsif 的次數(shù)沒有限制,注意 elsif 的拼寫----不是elseif。在這里需要注意一下condition 的值,一定要為布爾型,不像 C 里面,隨便填個(gè)整數(shù)也沒事。
下面以簡(jiǎn)單的一個(gè)例子來(lái)解釋一下 if 語(yǔ)句:
000 -- filename: ifInteger.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure testrange is
004 Var : Integer;
005 begin
006 Put ("Enter an Integer number to confirm its range:");
007 Get (Var);
008 if Var in Integer'First .. -1 then
009 Put_Line ("It is a negative number");
010 elsif Var in 1 .. Integer'Last then
011 Put_Line ("It is a positive number");
012 else
013 Put_Line ("It is 0");
014 end if;
015 end testrange;
[007] 輸入值 Var;[008]-[014]的語(yǔ)句都是測(cè)試 Var 的范圍,如是負(fù)數(shù)則輸出"It is a negative number",正數(shù)輸出"It is a positive number",為0則輸出"It is 0",以上3種情況如果都沒產(chǎn)生,則是因?yàn)檩斎胫捣?Integer 類型或輸入值過(guò)大,從而產(chǎn)生異常。如果所要判斷的變量有多種可能,并且每種情況都要執(zhí)行不同的操作,if 語(yǔ)句很顯然繁了一點(diǎn),這時(shí)就使用 case 語(yǔ)句,格式為:
case expression is
when choice1 => statements
when choice2 => statements
. . .
when others => statements
end case;
判斷 expression 的值,如符合某項(xiàng)choice,則執(zhí)行后面的statement,如果全都不符合時(shí),就執(zhí)行 others 后的語(yǔ)句。choice 的值不能相同。when others 也可以沒有,但不推薦這樣做,以免有沒估計(jì)到的情況產(chǎn)生。因此上例也可改成:
000 -- filename: ifInteger.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure testrange is
004 Var : Integer;
005 begin
006 Put ("Enter an Integer number to confirm its range:");
007 Get(Var);
008 case Var is
009 when Integer'First .. -1 =>
010 Put_Line ("It is a negative number");
011 when 1 .. Integer'Last =>
012 Put_Line ("It is a positive number");
013 when others =>
014 Put_Line ("It is 0");
015 end case;
016 end testrange;
與前面的例子完全等效。
很多情況下,我們要反復(fù)執(zhí)行同一操作,無(wú)疑這時(shí)要使用循環(huán)結(jié)構(gòu)。循環(huán)結(jié)構(gòu)除了最簡(jiǎn)單的loop語(yǔ)句,還有其變種for 和while語(yǔ)句。
最簡(jiǎn)單的loop語(yǔ)句格式為:
loop
statements
end loop;
當(dāng)要退出該循環(huán)時(shí),使用 exit 或 exit when 語(yǔ)句。exit表示直接退出該循環(huán),exit when則在符合 when 后面的條件時(shí)再退出。再將testrange 改動(dòng)一下,來(lái)了解loop和exit語(yǔ)句。
000 -- filename: ifInteger.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure testrange is
004 Var : Integer;
005 begin
006 loop
007 Put ("Enter an Integer number to confirm its range:");
008 Get(Var);
009 case Var is
010 when Integer'First .. -1 =>
011 Put_Line ("It is a negative number");
012 when 1 .. Integer'Last =>
013 Put_Line ("It is a positive number");
014 when others =>
015 Put_Line ("It is 0");
016 end case;
017 exit when Var = 0;
018 end loop;
019 end testrange;
上例循環(huán)輸出"Enter an Integer number to confirm its range:",要求輸入一個(gè)整數(shù);當(dāng)輸入值為0時(shí),輸出"it is 0",再退出。
for 循環(huán)只是loop的變種,格式如下:
for index in [reverse] range loop
statements;
end loop;
*reverse 是可選的.注意一下,index 是for循環(huán)中的局部變量,無(wú)需額外聲明,只需填入一個(gè)合法的標(biāo)識(shí)符即可,在for循環(huán)內(nèi),不能修改index的值。index的值一般情況下是遞增加1,如 for i in 1..100,i的初值為1,每循環(huán)一次加1,直至加到100,循環(huán)100次結(jié)束;有時(shí)也需要倒過(guò)來(lái),如i初值為100,減到1,則為 for i in reverse 1..100。但range中較大值在前則該循環(huán)不進(jìn)行,如 for i in [reverse]100..1,循環(huán)內(nèi)語(yǔ)句會(huì)略過(guò)---即變成了空語(yǔ)句。
仍舊是通過(guò)修改testrange來(lái)了解for:
000 -- filename: ifInteger.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure testrange is
004 Var : Integer;
005 begin
006 for i in 1..10 loop
007 Put ("Enter an Integer number to confirm its range:");
008 Get(Var);
009 case Var is
010 when Integer'First .. -1 =>
011 Put_Line ("It is a negative number");
012 when 1 .. Integer'Last =>
013 Put_Line ("It is a positive number");
014 when others =>
015 Put_Line ("It is 0");
016 end case;
017 exit when Var = 0;
018 end loop;
019 end testrange;
如果不輸入0,在輸入10次整數(shù)后,該程序會(huì)自動(dòng)結(jié)束。
while 循環(huán)則在某條件不成立時(shí)結(jié)束循環(huán),其格式為:
while condition loop
statements
end loop;
condiotion 和 if 語(yǔ)句中的 condition 一樣,都要求為布爾值,在其值為 False 時(shí),循環(huán)結(jié)束。
還是老套的testrange:
000 -- filename: ifInteger.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure testrange is
004 Var : Integer;
005 begin
006 while Var /= 0 loop
007 Put ("Enter an Integer number to confirm its range:");
008 Get(Var);
009 case Var is
010 when Integer'First .. -1 =>
011 Put_Line ("It is a negative number");
012 when 1 .. Integer'Last =>
013 Put_Line ("It is a positive number");
014 when others =>
015 Put_Line ("It is 0");
016 end case;
017 end loop;
018 end testrange;
這里取消了exit when語(yǔ)句,由while語(yǔ)句來(lái)檢測(cè)Var的值。當(dāng)Var值為0時(shí),循環(huán)結(jié)束。
null 語(yǔ)句所做的事就是不做事,大部份情況下就等于沒寫;但在一些情況下,還是有其作用,如if var > 0 then null end if,如果沒有 null,則屬于語(yǔ)法錯(cuò)誤,缺少了語(yǔ)句。因此 null 用在語(yǔ)法上要求必須有語(yǔ)句,但又不想讓程序干什么事的時(shí)候。
塊語(yǔ)句(block statement),就是以一組語(yǔ)句為單位,當(dāng)作一個(gè)獨(dú)立的塊,也常用在循環(huán)中,格式為;
identifier:
[declare]
begin
statements
end indentifier;
declare是可選的,如:
Swap:
declare
Temp :Integer;
begin
Temp := V; V:=U; U:=Temp;
end Swap;
其中的Temp為局部變量,Swap 外的語(yǔ)句無(wú)法訪問(wèn)它,Temp也可寫成Swap.Temp,以此從形式上區(qū)分局部變量和全局變量。塊語(yǔ)句的用法,還是通過(guò)實(shí)例來(lái)講解方便:
000 -- filename: swap.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure Swap is
004 V:Integer := 1;
005 U:Integer := 2;
006 begin
007 PutVU1:
008 begin
009 Put("V is:"); Put(V); New_Line;
010 Put("U is:"); Put(U); New_Line;
011 end PutVU1;
012 Swap:
013 declare
014 Temp :Integer;
015 begin
016 Temp := V; V:=U; U:=Temp;
017 end Swap;
018 Put_Line ("After swap");
019 PutVU2:
020 begin
021 Put("V is:"); Put(V); New_Line;
022 Put("U is:"); Put(U); New_Line;
023 end PutVU3;
024 end Swap;
通過(guò)上面的例子,大家可能感覺沒什么意思,塊結(jié)構(gòu)可有可無(wú)---反正還是按語(yǔ)句的先后順序執(zhí)行。但如果它用在循環(huán)結(jié)構(gòu)中,則還有點(diǎn)用處:
Main_Circle:
begin
loop
statements;
loop
statements;
exit Main_Circle when Found;--* 如果 Found 為 True,則跳出 Main_Circle,而不是該句所在的小循環(huán)
statements;
end loop;
statements;
end loop;
end Main_Circlel;
這樣就能跳出一堆嵌套循環(huán),接下去執(zhí)行的語(yǔ)句都在跳出的循環(huán)后面。
5.9 Goto語(yǔ)句(Goto Statement)
goto 語(yǔ)句能直接跳到程序的某一處開始執(zhí)行,使程序結(jié)構(gòu)松散很多,有關(guān)編程的教材基本上將它作為碰都不能碰的東西。但在處理異常情況中,goto 還是很方便的---并被有些權(quán)威人士推薦;只要?jiǎng)e濫用就可以了。Ada 里goto語(yǔ)句格式為:
<<Label>>
statements;
goto Label;
如將上例改為:
000 -- filename: swap.adb
001 with Ada.Text_IO; use Ada.Text_IO;
002 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
003 procedure Swap is
004 V:Integer := 1;
005 U:Integer := 2;
006 begin
007 <<restart>>
008 PutVU1:
009 begin
010 Put("V is:"); Put(V); New_Line;
011 Put("U is:"); Put(U); New_Line;
012 end PutVU1;
013 Swap:
014 declare
015 Temp :Integer;
016 begin
017 Temp := V; V:=U; U:=Temp;
018 end Swap;
019 Put_Line ("After swap");
020 PutVU2:
021 begin
022 Put("V is:"); Put(V); New_Line;
023 Put("U is:"); Put(U); New_Line;
024 end PutVU2;
025 goto restart;
026 end swap;
快到程序結(jié)尾時(shí),又返回到開頭<<restart>>處,因此成了無(wú)限循環(huán)。goto語(yǔ)句在 Ada 里的限制還是挺多的,如不能跳到if,case,for,while里面和其所在子程序外。
更多建議: