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
翻译(百度):博客园 一个默默的 *** 的人