在 Ada 子程序的 “is”和“end”之間,是一組有序語句,每句用雙引號;結(jié)束。這些語句大致可分成三種控制結(jié)構(gòu):順序結(jié)構(gòu),選擇結(jié)構(gòu),循環(huán)結(jié)構(gòu)----如果按照前輩們辛辛苦苦的證明:任何程序都可以只由這三種結(jié)構(gòu)完成。以前我們見過的簡單程序都是順序結(jié)構(gòu),本章里會介紹一下 Ada 里選擇結(jié)構(gòu)的if、case 語句和循環(huán)結(jié)構(gòu)的 loop 語句及其變種,并介紹順序結(jié)構(gòu)中以前沒講過的 null 和塊語句(block statement),最后是比較有爭議的 goto 語句---好像每本教科書上都罵它,說它打破了程序的良好結(jié)構(gòu)。控制結(jié)構(gòu)是一門老話題,Ada95 對它也沒作多大改動,語法上和其它語言還是很接近的,但可讀性好一點,所有控制結(jié)構(gòu)后都以"end something"結(jié)束。
if 語句判斷一個條件是否成立,如果成立,則執(zhí)行特定的語句,否則跳過這些語句。一般格式如下:
if condition then
statements
end if;
當 condition 的值為 True 時,則執(zhí)行 statements,否則跳過 statements,執(zhí)行“end if”后面的語句。
如果當 condition 為 False 也要執(zhí)行特定語句,則用下面的格式:
if condition then
statements
else
other statements
end if;
這樣當條件不成立時,執(zhí)行other statement,而不是跳過 if 結(jié)構(gòu)。
下面一種格式是為了多個條件判斷而用,防止 if 語句過多:
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 里面,隨便填個整數(shù)也沒事。
下面以簡單的一個例子來解釋一下 if 語句:
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]的語句都是測試 Var 的范圍,如是負數(shù)則輸出"It is a negative number",正數(shù)輸出"It is a positive number",為0則輸出"It is 0",以上3種情況如果都沒產(chǎn)生,則是因為輸入值非 Integer 類型或輸入值過大,從而產(chǎn)生異常。如果所要判斷的變量有多種可能,并且每種情況都要執(zhí)行不同的操作,if 語句很顯然繁了一點,這時就使用 case 語句,格式為:
case expression is
when choice1 => statements
when choice2 => statements
. . .
when others => statements
end case;
判斷 expression 的值,如符合某項choice,則執(zhí)行后面的statement,如果全都不符合時,就執(zhí)行 others 后的語句。choice 的值不能相同。when others 也可以沒有,但不推薦這樣做,以免有沒估計到的情況產(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;
與前面的例子完全等效。
很多情況下,我們要反復執(zhí)行同一操作,無疑這時要使用循環(huán)結(jié)構(gòu)。循環(huán)結(jié)構(gòu)除了最簡單的loop語句,還有其變種for 和while語句。
最簡單的loop語句格式為:
loop
statements
end loop;
當要退出該循環(huán)時,使用 exit 或 exit when 語句。exit表示直接退出該循環(huán),exit when則在符合 when 后面的條件時再退出。再將testrange 改動一下,來了解loop和exit語句。
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:",要求輸入一個整數(shù);當輸入值為0時,輸出"it is 0",再退出。
for 循環(huán)只是loop的變種,格式如下:
for index in [reverse] range loop
statements;
end loop;
*reverse 是可選的.注意一下,index 是for循環(huán)中的局部變量,無需額外聲明,只需填入一個合法的標識符即可,在for循環(huán)內(nèi),不能修改index的值。index的值一般情況下是遞增加1,如 for i in 1..100,i的初值為1,每循環(huán)一次加1,直至加到100,循環(huán)100次結(jié)束;有時也需要倒過來,如i初值為100,減到1,則為 for i in reverse 1..100。但range中較大值在前則該循環(huán)不進行,如 for i in [reverse]100..1,循環(huán)內(nèi)語句會略過---即變成了空語句。
仍舊是通過修改testrange來了解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ù)后,該程序會自動結(jié)束。
while 循環(huán)則在某條件不成立時結(jié)束循環(huán),其格式為:
while condition loop
statements
end loop;
condiotion 和 if 語句中的 condition 一樣,都要求為布爾值,在其值為 False 時,循環(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語句,由while語句來檢測Var的值。當Var值為0時,循環(huán)結(jié)束。
null 語句所做的事就是不做事,大部份情況下就等于沒寫;但在一些情況下,還是有其作用,如if var > 0 then null end if,如果沒有 null,則屬于語法錯誤,缺少了語句。因此 null 用在語法上要求必須有語句,但又不想讓程序干什么事的時候。
塊語句(block statement),就是以一組語句為單位,當作一個獨立的塊,也常用在循環(huán)中,格式為;
identifier:
[declare]
begin
statements
end indentifier;
declare是可選的,如:
Swap:
declare
Temp :Integer;
begin
Temp := V; V:=U; U:=Temp;
end Swap;
其中的Temp為局部變量,Swap 外的語句無法訪問它,Temp也可寫成Swap.Temp,以此從形式上區(qū)分局部變量和全局變量。塊語句的用法,還是通過實例來講解方便:
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;
通過上面的例子,大家可能感覺沒什么意思,塊結(jié)構(gòu)可有可無---反正還是按語句的先后順序執(zhí)行。但如果它用在循環(huán)結(jié)構(gòu)中,則還有點用處:
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í)行的語句都在跳出的循環(huán)后面。
5.9 Goto語句(Goto Statement)
goto 語句能直接跳到程序的某一處開始執(zhí)行,使程序結(jié)構(gòu)松散很多,有關(guān)編程的教材基本上將它作為碰都不能碰的東西。但在處理異常情況中,goto 還是很方便的---并被有些權(quán)威人士推薦;只要別濫用就可以了。Ada 里goto語句格式為:
<<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é)尾時,又返回到開頭<<restart>>處,因此成了無限循環(huán)。goto語句在 Ada 里的限制還是挺多的,如不能跳到if,case,for,while里面和其所在子程序外。
更多建議: