Ada之常见控制语句介绍
概述(Overview)
在 Ada 子程序的 “is”和“end”之间,是一组有序语句,每句用双引号;结束。这些语句大致可分成三种控制结构:顺序结构,选择结构,循环结构----如果按照前辈们辛辛苦苦的证明:任何程序都可以只由这三种结构完成。以前我们见过的简单程序都是顺序结构,本章里会介绍一下 Ada 里选择结构的if、case 语句和循环结构的 loop 语句及其变种,并介绍顺序结构中以前没讲过的 null 和块语句(block statement),最后是比较有争议的 goto 语句---好像每本教科书上都骂它,说它打破了程序的良好结构。控制结构是一门老话题,Ada95 对它也没作多大改动,语法上和其它语言还是很接近的,但可读性好一点,所有控制结构后都以"end something"结束。
if 语句(if statement)
if 语句判断一个条件是否成立,如果成立,则执行特定的语句,否则跳过这些语句。一般格式如下:
if condition then
statements
end if;
当 condition 的值为 True 时,则执行 statements,否则跳过 statements,执行“end if”后面的语句。
如果当 condition 为 False 也要执行特定语句,则用下面的格式:
if condition then
statements
else
other statements
end if;
这样当条件不成立时,执行other statement,而不是跳过 if 结构。
下面一种格式是为了多个条件判断而用,防止 if 语句过多:
if condition then
statements
elsif condition then
other statements
elsif condition then
more other statements
else
even more other statements
end if;
使用 elsif 的次数没有限制,注意 elsif 的拼写----不是elseif。在这里需要注意一下condition 的值,一定要为布尔型,不像 C 里面,随便填个整数也没事。
下面以简单的一个例子来解释一下 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 的范围,如是负数则输出"It is a negative number",正数输出"It is a positive number",为0则输出"It is 0",以上3种情况如果都没产生,则是因为输入值非 Integer 类型或输入值过大,从而产生异常。case 语句(case Statement)
如果所要判断的变量有多种可能,并且每种情况都要执行不同的操作,if 语句很显然繁了一点,这时就使用 case 语句,格式为:
case expression is
when choice1 => statements
when choice2 => statements
. . .
when others => statements
end case;
判断 expression 的值,如符合某项choice,则执行后面的statement,如果全都不符合时,就执行 others 后的语句。choice 的值不能相同。when others 也可以没有,但不推荐这样做,以免有没估计到的情况产生。因此上例也可改成:
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;
与前面的例子完全等效。
loop 语句(loop Statement)
很多情况下,我们要反复执行同一操作,无疑这时要使用循环结构。循环结构除了最简单的loop语句,还有其变种for 和while语句。
最简单的loop语句格式为:
loop
statements
end loop;
当要退出该循环时,使用 exit 或 exit when 语句。exit表示直接退出该循环,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;
上例循环输出"Enter an Integer number to confirm its range:",要求输入一个整数;当输入值为0时,输出"it is 0",再退出。
for 循环(for loop)
for 循环只是loop的变种,格式如下:
for index in [reverse] range loop
statements;
end loop;
*reverse 是可选的.注意一下,index 是for循环中的局部变量,无需额外声明,只需填入一个合法的标识符即可,在for循环内,不能修改index的值。index的值一般情况下是递增加1,如 for i in 1..100,i的初值为1,每循环一次加1,直至加到100,循环100次结束;有时也需要倒过来,如i初值为100,减到1,则为 for i in reverse 1..100。但range中较大值在前则该循环不进行,如 for i in [reverse]100..1,循环内语句会略过---即变成了空语句。
仍旧是通过修改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次整数后,该程序会自动结束。
while 循环 (while loop)
while 循环则在某条件不成立时结束循环,其格式为:
while condition loop
statements
end loop;
condiotion 和 if 语句中的 condition 一样,都要求为布尔值,在其值为 False 时,循环结束。
还是老套的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时,循环结束。
null 语句(null Satement)
null 语句所做的事就是不做事,大部份情况下就等于没写;但在一些情况下,还是有其作用,如if var > 0 then null end if,如果没有 null,则属于语法错误,缺少了语句。因此 null 用在语法上要求必须有语句,但又不想让程序干什么事的时候。
块语句(Block Statement)
块语句(block statement),就是以一组语句为单位,当作一个独立的块,也常用在循环中,格式为;
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,以此从形式上区分局部变量和全局变量。块语句的用法,还是通过实例来讲解方便:
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;
通过上面的例子,大家可能感觉没什么意思,块结构可有可无---反正还是按语句的先后顺序执行。但如果它用在循环结构中,则还有点用处:
Main_Circle:
begin
loop
statements;
loop
statements;
exit Main_Circle when Found;--* 如果 Found 为 True,则跳出 Main_Circle,而不是该句所在的小循环
statements;
end loop;
statements;
end loop;
end Main_Circlel;
这样就能跳出一堆嵌套循环,接下去执行的语句都在跳出的循环后面。
5.9 Goto语句(Goto Statement)
goto 语句能直接跳到程序的某一处开始执行,使程序结构松散很多,有关编程的教材基本上将它作为碰都不能碰的东西。但在处理异常情况中,goto 还是很方便的---并被有些权威人士推荐;只要别滥用就可以了。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;
快到程序结尾时,又返回到开头<<restart>>处,因此成了无限循环。goto语句在 Ada 里的限制还是挺多的,如不能跳到if,case,for,while里面和其所在子程序外。
更多建议: