Fortran程序设计基本计算选择控制结构.docx
《Fortran程序设计基本计算选择控制结构.docx》由会员分享,可在线阅读,更多相关《Fortran程序设计基本计算选择控制结构.docx(14页珍藏版)》请在冰豆网上搜索。
Fortran程序设计基本计算选择控制结构
第10章基本计算
(二)选择控制结构
在上章我们可以看到,赋值语句之所以能够驱动计算过程的运行,除了赋值语句本身构成完整的运算求值指令之外,计算机本身所具有的串行机制保证了,只要把执行语句与说明语句串列下来,然后保证数据对象流的畅通,计算机就能够按照语句序列的次序依次执行下来,从而完成相应的计算任务。
不过分析一下我们的实际计算任务,就会发现真正完全可以只需要按照一个固有计算序列算下来,就可以完成计算的问题只是少数简单的问题而已,稍微复杂点的问题往往都需要在计算过程当中出现某种判别问题,使得计算途径可以分支,对不同的情形,会有不同的计算途径与不同的计算结果;还会出现反复进行同一种运算,然后再在适当的条件下跳出循环的情形,如果只是使用串行序列来描述此时的运算过程,会使得程序的写作充满重沓的语句。
显然这些类型的计算任务,或者是语句串行序列无法描述的,或者是描述发生令人难以忍受的。
个人收集整理勿做商业用途
所以一种描述计算过程的语言,除了可以构成串行的计算序列之外,还必须能够控制这个序列有可能出现的选择分支与循环的情形,这就是所谓语言的控制结构。
个人收集整理勿做商业用途
本章和下章,我们将分别讨论FORTRAN所提供的两种类型的控制结构以及相应的控制语句:
•选择控制结构;
•循环控制结构。
把程序序列当中的控制结构清晰地加以强调出来,实际上既有助于程序的阅读,也是符合人的思维的清晰性原则的,因此控制结构的规范化正是编程语言追求结构化的一个主要着力点,但是在早期FORTRAN版本里面,并没有完全意识到结构化编程风格的重要性,因此引入了一些常常破坏结构的转移控制语句,而FORTRAN语言的现代版本还没有完全放弃它们,但不提倡使用,这些转移控制语句我们在下章也将简略地讨论到。
个人收集整理勿做商业用途
10.1执行顺序
一个完整的FORTRAN程序,或程序单位,就给出了一个由可执行语句引导的语句执行序列,这个序列就是语句在程序里面出现的序列,称为正常运行序列。
个人收集整理勿做商业用途
但是某些可执行结构或可执行语句,能够控制实际的语句运行不止是按照语句书写的序列进行,这样的可执行结构或语句包括控制结构和分支语句。
个人收集整理勿做商业用途
控制语句执行序列有两种基本风格:
•使用可执行结构,使得程序能够选择性地运行程序序列里某个特定位置的语句块或
结构。
•使用能够分支到程序其他任意位置的语句的可执行语句。
一般说来,上面的第一种方式具有更好的可阅读性和可维护性,因此我们将详细讨论第一种方式的实现,而第二种方式则放在下章末尾简略说明一下。
个人收集整理勿做商业用途
10.2块与可执行结构
所谓控制结构由一个或多个语句块和结构构成,其中必定显式地或隐式地包含控制逻辑语句。
根据相应的逻辑控制条件,就可以选择性地运行某个特定的语句块与结构。
个人收集整理勿做商业用途
一个块就是一个由0个或多个语句与结构构成的序列,句法形式(R801)为:
[execution-part-construct]…
构成块的语句与结构的序列构成一个程序单位,是一个某种意义上的整体,即或者整个块被执行,或者整个块都不被执行,不能够出现块的某个部分被执行的情形。
不过也可能出现在整个块被执行的情况下,块内的某些语句没有被执行的情况,例如在块内的比较靠前的分支语句,常常能够制止它后面的语句得到执行,但是从语法意义上来看,整个块的功能得到了完整的实现,因此这种情形也被认为是块的完全执行。
个人收集整理勿做商业用途
所谓结构就是由一个或多个语句块或者结构,加上作用于这些块的控制语句构成。
•结构通常在块前具有一个初始语句,而在块后具有一个终止语句;
•当结构包含不止一个块时,结构必定包含了用来选择执行哪个块的条件语句,而一个块是否被执行,正是由结构的作为条件语句的控制逻辑语句当中的表达式决定的;个人收集整理勿做商业用途
•结构也有可能在块之间放置特定的语句,用来决定相应的块是否被执行;
•DO结构专门用来决定一个块可以被连续地执行的次数。
【例10-1】下面给出的可执行结构控制了一个块:
IF(K<=1)THEN!
IF结构的初始语句
X=K**2!
块的第一个语句
Y=SIN(X)!
块的第二个语句
ENDIF!
IF结构的终止语句
FORTRAN提供了三种能够控制块的可执行结构:
•IF结构
•CASE结构
•DO结构
块的一般规则如下:
•首先执行块内的第一个语句或结构,随后的执行顺序就是语句的排列顺序,除非中间包含控制结构或语句改变这个顺序。
个人收集整理勿做商业用途
•一个块作为一个整体,必须是完整地被包含在一个结构当中;一个块也可以是空块,即不包含任何语句与结构。
个人收集整理勿做商业用途
•在块内允许出现分支结构或控制结构,使得运行序列能够转移到该块内的特定语句或结构。
•在块内的任意位置,都可以强制运行的退出。
•从块的外部通过分支到达块的内部,哪怕是块内的第一个可执行语句,都是禁止的。
•块内可以引用过程。
•结构可以具有结构名称。
•结构名称在结构的初始语句和终止语句当中的出现,必须是成对的,也就是说或者同时出现在这两个位置,或者都不出现。
个人收集整理勿做商业用途
在上章我们讨论了WHERE结构与FORALL结构,它们似乎同样具有控制结构的功能,但实质上它们都是属于赋值语句。
个人收集整理勿做商业用途
WHERE结构可以包含多个块,但是除了块内的某些数组元素被过滤网过滤掉,从而不参与计算之外,每个块内的每个语句,都必须被执行。
个人收集整理勿做商业用途
FORALL结构只包含一个块,FORALL对这个块的执行控制,不是反复地运行这个块,而是其中的每个语句都必须对指标值集合里的所有元素执行一次,然后才转入下一个语句。
在FORALL结构里也可以引入过滤网,以排除掉不符合条件的计算。
个人收集整理勿做商业用途
10.3IF结构和IF语句
一个IF结构至多选择结构里的一个语句与结构的块来得到执行。
而一个IF语句至多控制一个语句的执行。
在下章后面会简略讨论到的算术IF语句与这里的IF语句没有关系,算术IF语句是一种分支语句,并且是过时的。
个人收集整理勿做商业用途
10.3.1IF结构
IF结构可以包含多个块与多个逻辑表达式,还可能包含ELSE语句与ELSEIF语句。
逻辑表达式总是放置在相应的块之前,因此IF结构的执行总是从逻辑表达式开始的,一旦逻辑表达式取真值,则相应的块获得执行,整个IF结构内至多只有一个块能够被选择执行,而如果没有ELSE语句的话,可能没有块满足执行的条件。
个人收集整理勿做商业用途一旦被选择执行的块运行完毕,或者不存在满足执行条件的块,则整个IF结构的运行被终止。
1.IF结构的形式
IF结构的句法形式(R802)为:
[if-construct-name:
]IF(scalar-logical-expression)THEN个人收集整理勿做商业用途
block
[ELSEIF(scalar-logical-expression)THEN[if-construct-name]个人收集整理勿做商业用途block]….
[ELSE[if-construct-name]
block]
ENDIF[if-construct-name]
IF结构的一般规则如下:
•至多只有一个结构里的块被执行,或者没有块被执行。
•ELSEIF语句不能跟随在ELSE语句后面。
•不能出现分支到ELSEIF语句或ELSE语句的情形。
•从IF结构里的任意块都可以分支到ENDIF语句,即随时可以退出IF结构。
•结构名称必须成对出现在IF-THEN语句和ENDIF语句当中。
•ELSEIF语句和ELSE语句里的结构名称是可选的,如果有的话,必须和IF-THEN语
句里的结构名称一致。
个人收集整理勿做商业用途
•在同一个作用域单位内,同一个结构名称不能用于不同的命名结构。
2.IF结构的运行
结构里的逻辑表达式按照序列位置执行,直到某个表达式为真值,然后紧跟该表达式后面的块得到执行,该块运行完毕之后,整个IF结构即退出运行。
个人收集整理勿做商业用途
在第一个真值表达式后面如果还存在真值表达式,则它们不影响对执行块的选择。
如果在该IF结构内(而不是它的子结构内)找不到真值表达式,则ELSE语句后面的块被执行;如果没有ELSE语句,则退出IF结构。
个人收集整理勿做商业用途
下面的图10-1给出了IF结构的运行示意图。
【例10-2】
IF(IX=Y*2.5
ELSEIF(I>8.3)THEN
X=0.0
Y=100
ELSE
X=100
Y=0.0
ENDIF
上例的执行顺序就是:
•首先执行I•-THEN语句。
•进入ELSEIF-THEN语句后,首先执行I>8.3,如果为真,则执行X=0.0,Y=100;个人收集整理勿做商业用途
•如果为假,则执行紧跟后面的ELSE语句。
•进入ELSE语句后,执行X=100,Y=0.0。
•然后执行ENDIF语句,退出该IF结构。
10.3.2IF语句
一个IF语句用在只需要控制一个语句的场合。
1.IF语句的形式
IF语句的句法形式(R807)为;
IF(scalar-logical-expression)action-statement
【例10-3】
IF(X=0)Y=X+1
2.IF语句的运行
首先执行逻辑表达式,如果为真值,则执行IF语句里的作用语句(action-statement);如
果为假,则退出该语句,执行程序里跟在IF语句后面的其他语句。
个人收集整理勿做商业用途
注意作用语句(action-statement)不能是一个IF语句,也不能是一个END语句。
如果逻辑表达式包含一个函数引用,那么逻辑表达式的运行可能产生修改作用语句的副作用,这是允许的。
作用语句能够改变变量,或输入输出系统条件,或控制语句的状态,作用语句的例子包括赋值,WRITE,GOTO语句等;说明性语句,FORMAT语句,和ENTRY语句等不属于作用语句,而结构也不能看成是作用语句。
个人收集整理勿做商业用途
10.4CASE结构
和IF结构类似的是,CASE结构也可以包含多个块,而最终能够获得执行的最多只能是一个。
和IF结构不同的是,CASE结构的选择是基于结构开头的SELECTCASE语句里的标量表达式的取值,这个取值被称为情况指标,它可以是离散型的各种标量值,例如整型,字
符型,逻辑型,而在IF结构里,用来进行判别而提供选择条件的是逻辑型取值,即只有.TURE.
和.FALSE.两个值。
个人收集整理勿做商业用途
得到情况指标之后,搜索所有的CASE语句里的情况选择符的值,如果有与情况指标
匹配的,则执行相应的CASE语句里的块,否则执行具有默认选择符的CASE,如果不存在
具有默认选择符的CASE,则退出。
个人收集整理勿做商业用途
使用CASE结构可以很自然地表达需要分情况考虑的问题,同时每种情况的定义必须是已知的。
【例10-4】设分段函数:
丄sin(x)x_0
y=
(cos(x)xc0
可以很自然地使用CASE结构描述如下:
SELECTCASE(x>=0)
CASE(.TRUE.)
Y=SIN(X)
CASE(.FALSE.)
Y=COS(X)
ENDSELECT
【例10-5】一年中十二个月的天数也可以用CASE结构表示如下:
MONTHDAY:
SELECTCASE(MONTH)
CASE
(2)
DAYS=28
CASE(4,6,9,11)
DAYS=30
CASE(1,3,5,7,8,10,12)
DAYS=31
ENDSELECTMONTHDAY
10.4.1CASE结构的形式
CASE结构的句法形式(R808)为:
[case-construct-name:
]SELECTCASE(case-expression)
[CASE(case-value-range-list)[case-construct-name]
block]…
[CASEDEFAULT[case-construct-name]
block]
ENDSELECT[case-construct-name]
其中的情况表达式(case-expression)为标量表达式,该表达式经过计算得到的取值为情况指标。
个人收集整理勿做商业用途
其中的情况值范围(case-value-range)即连同其括号称为情况选择符,表示它的取值所属
的离散区间,也可以就是一个单独的值,它的句法形式(R814)为:
个人收集整理勿做商业用途
case-valuecase-value:
:
case-value
case-value:
case-value
即如果是区间的话,该区间可以是半边开的。
其中的情况值(case-value)是一个标量初始化表达式,与情况表达式的类型等属性一样。
所谓初始化表达式即在编译时可以取值的表达式,本质上即常量表达式。
它们的取值都只能是整型,字符型和逻辑型。
个人收集整理勿做商业用途
可以看到在CASE结构里,包含了三种语句:
•SELECTCASE语句;
•CASE语句;
•ENDSELECT语句。
而在CASE语句当中,跟在关键词CASE后面的(case-value-range-list)或DEFAULT就
是情况选择符。
个人收集整理勿做商业用途
CASE结构的一般规则如下:
•如果CASE结构具有名称的话,那么结构名称必须成对出现在SELECTCASE语句和ENDSELECT语句当中。
个人收集整理勿做商业用途
•情况选择符后面如果出现结构名称的话,必须与SELECTCASE语句当中的结构名称一致。
•具有情况选择符DEFAULT的CASE语句是可选的,如果它出现在结构当中的话,
上述CASE结构的句法形式并没有要求它放置在结构的最后。
个人收集整理勿做商业用途
•在一个CASE结构里,情况表达式与所有的情况值都必须属于同一个类型,如果属
于字符型,它们可以具有不同的长度,但是种别参数必须一致。
个人收集整理勿做商业用途
•情况值范围里面出现冒号时,表示一个区间,而区间的构成隐含着相应的关系表达式。
•情况值不能是逻辑型。
•如果是字符型的话,则依据字符型的关系运算规则确定相应的取值范围。
【例10-6】
CASE(“ABOUT”:
“Z”)
里面的情况值范围为按照与处理器相关的默认字符类型的关系运算,在ABOUT与Z
之间的所有字符串。
结构当中的表达式的取值完成后,必须保证最多只能有一个情况选择符的值与情况指标
值匹配,也即不允许在不同的情况之间情况值出现重复的情形。
个人收集整理勿做商业用途
情况值DEFAULT与任何跟所有结构内的其他情况值都不匹配的情况指标值匹配。
【例10-7】
CALCU_AREA:
SELECTCASE(OBJECT)
CASE(RECTANGLE)CALCU_AREA
AREA=LENGTH*WIDTH
CASE(SQUARE)CALCU_AREA
AREA=SIDE*SIDE
CASE(CIRCLE)CALCU_AREA
AREA=PI*RADIUS**2
ENDSELECTCALCU_AREA
1042CASE结构的运行
首先计算SELECTCASE语句当中的作为标量表达式的情况指标,它的值最多与结构里的一个情况值匹配,与之匹配的情况值后面紧跟的块得到执行,然后退出结构。
程序进入紧跟该结构的ENDSELECT语句后面的可执行语句或结构。
个人收集整理勿做商业用途
如果没有与情况指标值匹配的情况值,而结构里包含了CASEDEFAULT语句,按照
DEFAULT的定义,情况值这时必定与之匹配,因此执行该语句后面的块,然后退出该结构。
个人收集整理勿做商业用途
如果结构当中不存在CASEDEFAULT语句,又没有与情况指标值匹配的情况值,那么
退出该结构,不执行结构里的任何块。
个人收集整理勿做商业用途
所谓情况指标值与结构里的一个情况值匹配,包含如下情形:
•如果情况值为单独的一个值,则运用等价与非等价关系运算,看是否与指标值等价;
•如果情况值是一个区间,则按照下表10-1的定义:
表10-1不同情况值的匹配
情况值范围
匹配的定义
case-value1:
case-value2
case-value1.LE.case-index.LE.case-value2
case-value:
case-value.LE.case-index
:
case-value
case-value.GE.case-index
注意不同CASE语句的情况值范围不能有重叠。
结构的执行最多只允许其中的一个块被执行。
只能从结构内部分支到该结构的ENDSELECT语句。
不允许分支到CASE语句,但可以分支到SELECTCASE语句。
下面的图10-2给出了CASE结构的运行流的示意图:
图10-2CASE结构的运行流示意图:
【例10-8】
INDEX=2
SELECTCASE(INDEX)
CASE
(1)
A=(1,2)
CASE
(2)
A=(2,3)
CASEDEFAULT
A=(0,0)
ENDSELECT
例10-9】下面的例子描述了一个交通规则
COLOR=“GREEN”
SELECTCASE(COLOR)
CASE(“RED”)
STOP
CASE(“YELLOW”)
CALLSTOP_IF_YOU_CAN_SAFELY
CASE(“GREEN”)
CALLGO_AHEAD
ENDSELECT