ADA 95教程 控制结构2

循环很重要

您将有很多机会使用这里讨论的所有三种形式的循环,因此研究这些循环是值得的,直到您确定它们在做什么。

请注意三个循环的相似性,以及每个循环都是以分号结尾的完整Ada语句。当我们研究下两个控制结构时,您将看到它们非常相似,并且符合相同的模式。

                               loop <...> end loop; 
   while <BOOLEAN expression>  loop <...> end loop;
   for <loop index> in <range> loop <...> end loop;

译并执行这个程序,注意在循环完成时观察名为Special_Index的变量的值。

这将是您开始熟悉ADA95参考手册(ARM)的一个好机会。学习ARM中的第5.5节,它详细定义了循环语句。除了本节开头的语法语句之外,您会发现它非常容易阅读和理解。您将看到,在本教程的这一节中,我们几乎没有涉及到循环构造,您将开始熟悉ARM。在你获得了一些Ada的经验之后,你会发现ARM是一个有价值的信息来源。

 

现在是条件语句

Example program ------> e_c05_p3.ada

-- Chapter 5 - Program 3
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;

procedure IfDemo is

begin
   for Index in 1..7 loop  -- This contains two simple if statements
      Put("Index is ");
      Put(Index, 3);
      if Index < 4 then
         Put(" so is less than 4");
      end if;
      if Index > 5 then
         Put(" so is more than 5");
      end if;
      New_Line;
   end loop;
   New_Line;

   for Index in 13..17 loop  -- This contains an else clause
      Put("Index is");
      Put(Index, 3);
      if Index < 15 then
         Put_Line(" and is less than 15.");
      else
         Put_Line(" and is 15 or greater.");
      end if;
   end loop;
   New_Line;

   for Index in 13..17 loop  -- This introduces the elsif statement
      Put("Index is");
      Put(Index, 3);
      if Index < 15 then
         Put_Line(" and is less than 15.");
      elsif Index = 15 then
         Put_Line(" and is 15.");
      elsif Index = 16 then
         Put_Line(" and is 16.");
      else
         Put_Line(" and is greater than 16.");
      end if;
   end loop;
   New_Line;

-- This final group of statements contains a loop with a nested if
--   statement, and a loop within the the else part of the nested
--   if statement.

   for Index in 13..17 loop
      Put("Index is");
      Put(Index, 3);
      if Index < 16 then
         if Index > 14 then
            Put(" and is less than 16 and greater than 14.");
         else
            Put(" and is less than or equal to 14.");
         end if;
      else
         Put(" and is 16 or greater.");
         for New_Index in 222..224 loop
           Put(" stutter");
         end loop;
      end if;
      New_Line;
   end loop;

end IfDemo;





-- Result of execution

-- Index is   1 so is less than 4
-- Index is   2 so is less than 4
-- Index is   3 so is less than 4
-- Index is   4
-- Index is   5
-- Index is   6 so is more than 5
-- Index is   7 so is more than 5
--
-- Index is 13 and is less than 15.
-- Index is 14 and is less than 15.
-- Index is 15 and is 15 or greater.
-- Index is 16 and is 15 or greater.
-- Index is 17 and is 15 or greater.
--
-- Index is 13 and is less than 15.
-- Index is 14 and is less than 15.
-- Index is 15 and is 15.
-- Index is 16 and is 16.
-- Index is 17 and is greater than 16.
--
-- Index is 13 and is less than or equal to 14.
-- Index is 14 and is less than or equal to 14.
-- Index is 15 and is less than 16 and greater than 14.
-- Index is 16 and is 16 or greater. stutter stutter stutter
-- Index is 17 and is 16 or greater. stutter stutter stutter

现在,我们将花一些时间研究名为e_c05_p3.ada的程序,并研究条件语句。注意这里,我们甚至不尝试定义任何变量,但是我们将让系统为我们生成隐式循环索引。第8行到第18行中包含的Ada语句是我们现在熟悉的for循环,因此我们将使用它来研究if语句是如何工作的。注意,我们显示Index的值,然后在第11到13行的第一个if语句中使用它。此语句表示如果索引中存储的值小于4,则执行保留字then和end if之间的语句。在本例中,我们在监视器的第12行显示消息。如果索引中存储的值不小于4,则忽略保留字之间的语句,直接转到第14行,在那里我们遇到另一个If语句。如果索引中存储的值大于5,则监视器上会显示另一行。这是最简单的if语句,您会发现它非常有用,事实上,您在前两个示例程序中使用了它。请注意,if条件的计算结果必须是布尔值。

继续下一个循环,即第21行到第29行中的循环,我们会发现一个更复杂的条件语句,if-then-else语句。在这种情况下,如果Index的值小于15,则显示一条消息,否则显示另一条消息。在前面的循环中,我们使用了if语句,其中可能显示消息,也可能未显示消息,但在本循环中,我们使用了if语句,其中每次都会显示一条消息。当然,这与其他编程语言非常相似。

 

现在是多路if语句

第32行到第44行中包含的语句中的循环要复杂一些,因为选择要显示的行有多种可能性。elsif这个词是另一个保留词。在这种情况下,在循环的每次传递过程中,只执行一条语句。保留字else是可选的,如果它不存在,则可能不满足任何条件,因此不会输出任何消息。可以在每个保留字之间放置所需的尽可能多的语句,使得选择可以导致按顺序执行大量语句。

第51行到第67行中给出的最后一个语句给出了循环和if语句嵌套的示例。理解嵌套应该不会有什么困难,在编译和运行这个程序时,应该对输出有很好的理解。

 

多路条件结构

Example program ------> e_c05_p4.ada

  -- Chapter 5 - Program 4
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;

procedure CaseDemo is

begin
   for How_Many in 4..13 loop
      Put("We now have ");
      Put(How_Many, 3);
      Put(" widgets, ");
      case How_Many is
         when 4..6    => Put("which is too few.");
         when 7|9     => Put("but we don't need 7 or 9.");
         when 13      => Put("but that is too many.");
         when 8|10|12 => Put("which is a large even number.");
         when 11      => Put("enough for a football team.");
      end case;
      New_Line;
   end loop;
   New_Line;

   for How_Many in 100..105 loop
      Put("It is now ");
      Put(How_Many, 3);
      Put(" ");
      case How_Many is
         when 100 => Put("The value is 100, and useless.");
         when 101 => for Index in 2..5 loop
                        Put("Puppy ");
                     end loop;
         when 103 => if TRUE then
                        Put("Of course TRUE will always be true.");
                     end if;
         when 105 => null;
         when others => Put("This is one of those not defined.");
      end case;
      New_Line;
   end loop;
end CaseDemo;




-- Result of execution

-- We now have   4 widgets, which is too few.
-- We now have   5 widgets, which is too few.
-- We now have   6 widgets, which is too few.
-- We now have   7 widgets, but we don't need 7 or 9.
-- We now have   8 widgets, which is a large even number.
-- We now have   9 widgets, but we don't need 7 or 9.
-- We now have  10 widgets, which is a large even number.
-- We now have  11 widgets, enough for a football team.
-- We now have  12 widgets, which is a large even number.
-- We now have  13 widgets, but that is too many.
--
-- It is now 100 The value is 100, and useless.
-- It is now 101 Puppy Puppy Puppy Puppy
-- It is now 102 This is one of those not defined.
-- It is now 103 Of course TRUE will always be true.
-- It is now 104 This is one of those not defined.
-- It is now 105

 检查名为e_c05_p4.ada的程序,以获取带有case语句(ada中的多路条件语句)的程序示例。第8行到第20行包含一个循环,循环中包含一个case语句。第12行到第18行包含实际的case语句。变量How_Many是case 选择变量,每次通过循环时,我们都会输入case语句,并在变量How_Many中存储不同的值。当有多少个路径的值为4到6时,我们选择第一条路径,只有那条路径,当它的值为7或9时,我们选择第二条路径,以此类推。竖线在这里是or运算符,意味着如果我们有这两种情况中的任何一种,请执行下面的语句列表。case语句由保留字case、is、when和end case以所示方式组成。必须以某种方式说明所有案例,因为使用case选择器变量的值输入案例是错误的,因为没有为其定义要执行的操作。

 

什么是=>运算符?

“=>”操作符在Ada程序中的许多地方都有使用,我们将在本教程中看到它。它可以松散地定义为“do this”操作符,因为在大多数情况下,它可以被解读为“do this”。例如,在第13行中,该行可以读取“when when_Many is 4 to 6 do this Put statement”。

一个特殊情况,即others。它是可选的,但如果包含,则必须是列出的最后一个。这在本程序的另一个例子,即第27行到第37行的例子中进行了说明。本程序演示了每个案例分支中更复杂的操作,希望您能够毫不费力地辨别每个案例的操作。这是null语句非常有用的地方之一,比如在第35行中,我们真的不想做什么,可以显式地告诉编译器这样做。一定要编译和执行这个程序后,你确定你明白它。case语句在编程中很少出现,但您将使用它,因此您应该彻底理解它。

这将是一个很好的时机来重复本章前面给出的列表,其中添加了if和case语句,以说明控制结构的对称性,以及它们的真实想法。

                               loop <...> end loop;
   while <BOOLEAN expression>  loop <...> end loop;
   for <loop index> in <range> loop <...> end loop;
   if <condition>              then <...> end if;
   case <selector>             is   <...> end case;

邪恶的GOTO声明

Example program ------> e_c05_p5.ada

 -- Chapter 5 - Program 5
with Ada.Text_IO;
use Ada.Text_IO;

procedure GoToDemo is

begin
   goto Some_Place;

<<There>>
   Put_Line("I am now at the There place.");
   goto Stop_This_Mess;

<<Where>>
   Put_Line("I am now at the Where place.");
   goto There;

<<Some_Place>>
   Put_Line("I am now Some_Place.");
   goto Where;

<<Stop_This_Mess>>
   Put_Line("I am now about to end this mess.");

end GoToDemo;




-- Result of execution

-- I am now Some_Place.
-- I am now at the Where place.
-- I am now at the There place.
-- I am now about to end this mess.

 名为e_c05_p5.ada的程序演示了goto语句的用法,这一语句近年来在软件开发人员中名声不佳。这是因为goto可以被滥用,导致几乎不可读的意大利面代码。在某些情况下,使用goto语句会产生非常清晰的代码,当出现这些情况时,应该使用goto语句。事实证明,只要使用迭代(循环)、条件分支和顺序语句,就可以不借助goto语句编写任何逻辑,并且应尽一切努力仅依赖这三个元素。

在开发Ada时,开发人员考虑将goto语句完全排除在语言之外,但它被包含在语言中的原因非常模糊。人们认为,在Ada成为一种流行语言之后,就需要使用自动翻译工具将现有的程序从FORTRAN等较老的语言翻译成Ada。如果没有goto语句,这样的工作是不可能的,因此它被包含在Ada语言中。Modula-2是一种结构非常类似Ada的语言,但没有定义goto语句作为语言的一部分。

goto作为Ada语言的一部分可用,并在本示例程序中进行了说明。对你来说,goto是另一个保留词应该并不奇怪。看起来相当凌乱的双“<<”和“>>”包含了您希望跳转到的标签,其余的应该很容易识别。一定要编译并运行这个程序。

 

最后,一个有用的程序

Example program ------> e_c05_p6.ada

 -- Chapter 5 - Program 6
-- Centigrade to Farenheit temperature table
--
--  This program generates a list of Centigrade and Farenheit
--    temperatures with a note at the freezing point of water
--    and another note at the boiling point of water.

with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;

procedure TempConv is

   Centigrade, Farenheit : INTEGER;

begin
   Put("Centigrade to Farenheit temperature table");
   New_Line(2);
   for Count in INTEGER range -2..12 loop
      Centigrade := 10 * Count;
      Farenheit := 32 + Centigrade * 9 / 5;
      Put("C =");
      Put(Centigrade, 5);
      Put("    F =");
      Put(Farenheit, 5);
      if Centigrade = 0 then
         Put("  Freezing point of water");
      end if;
      if Centigrade = 100 then
         Put("  Boiling point of water");
      end if;
      New_Line;
   end loop;
end TempConv;




-- Result of execution

-- Centigrade to Farenheit temperature table
--
-- C =  -20    F =   -4
-- C =  -10    F =   14
-- C =    0    F =   32  Freezing point of water
-- C =   10    F =   50
-- C =   20    F =   68
-- C =   30    F =   86
-- C =   40    F =  104
-- C =   50    F =  122
-- C =   60    F =  140
-- C =   70    F =  158
-- C =   80    F =  176
-- C =   90    F =  194
-- C =  100    F =  212  Boiling point of water
-- C =  110    F =  230
-- C =  120    F =  248

检查名为e_c05_p6.ada的程序以获得一个真正有用的程序示例,它生成一个摄氏度到华氏度的温度转换表,并在水的冰点和沸点输出一个特殊消息。请注意标题中的程序定义,它确切地定义了它的功能。理解这个程序的每一个细节应该没有问题,当然,除了第8行和第9行中相当神秘的代码。虽然我们已经对它们进行了简要的介绍,但是我们将在本教程的后面部分介绍它们的细节。

 

变量名选择不当

Example program ------> e_c05_p7.ada

  -- Chapter 5 - Program 7
with Ada.Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Integer_Text_IO;

procedure DumbConv is

   X, Y : INTEGER;

begin
   Put("Centigrade to Farenheight temperature table");
   New_Line(2);
   for Count in INTEGER range -2..12 loop
      X := 10 * Count;
      Y := 32 + X * 9 / 5;
      Put("C =");
      Put(X, 5);
      Put("    F =");
      Put(Y, 5);
      if X = 0 then
         Put("  Freezing point of water");
      end if;
      if X = 100 then
         Put("  Boiling point of water");
      end if;
      New_Line;
   end loop;
end;




-- Result of execution

-- Centigrade to Farenheit temperature table
--
-- C =  -20    F =   -4
-- C =  -10    F =   14
-- C =    0    F =   32  Freezing point of water
-- C =   10    F =   50
-- C =   20    F =   68
-- C =   30    F =   86
-- C =   40    F =  104
-- C =   50    F =  122
-- C =   60    F =  140
-- C =   70    F =  158
-- C =   80    F =  176
-- C =   90    F =  194
-- C =  100    F =  212  Boiling point of water
-- C =  110    F =  230
-- C =  120    F =  248

编译并运行e_c05_p6.ada,然后检查名为e_c05_p7.ada的程序,以获取一个使用了一些糟糕的变量名选择并忽略注释的示例。这个程序和你刚学的是同一个程序,因为它做的事情完全一样,但是我相信你会发现它有点难以理解,因为名字在帮助你理解它在做什么方面不是很有用。在本教程的开始部分,我们研究了一个名为e_c02_p1.ada的程序,它的风格非常可笑。没有一个严肃的程序员会编写这样的程序,但是许多程序员似乎很乐意使用类似于本例的样式。

即使在Ada编程开发的早期阶段,您也应该开始培养良好的格式化技能。请记住,Ada的设计是一次编写,多次读取,因此当您的同事发现需要研究您的代码时,输入有意义的长标识符所花费的额外时间将是值得的。

 

编程练习

1.用循环语句和条件语句编写一个程序,输出从出生到21岁的每年的年份和年龄。包括你开始上学的那一年和你高中毕业的那一年。示例输出如下:(Solution)

1938年,我才0岁。

1939年,我才1岁。

...

...

1943年,我5岁,开始上学。

...

等。

2.用case语句重写练习1(Solution)

 

 

---------------------------------------------------------------------------------------------------------------------------

原英文版出处:https://perso.telecom-paristech.fr/pautet/Ada95/a95list.htm

翻译(百度):博客园  一个默默的 *** 的人

posted @ 2021-03-26 07:36  yangjianfeng  阅读(99)  评论(0编辑  收藏  举报