Ada之常见控制语句介绍

2018-11-13 12:50 更新

 概述(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 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里面和其所在子程序外。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号