1、 第七章 循环结构程序设计 循环结构是三种基本控制结构之一。使用循环结构是优化程序结构的一种有效方法。本章将详细介绍循环结构及其程序设计方法有关内容。7.1 循环结构概述7.1.1 循环及循环结构在求解复杂问题时,常常遇到大量重复或相似的处理过程(计算过程、操作过程)。对于这些处理过程,我们不难按顺序结构设计和编写程序。例如:从键盘输入 5 个数,求 5 个数之和,并打印输出计算结果。求解这个问题,我们甚至会不假思索地采用顺序结构设计出求解算法,编写出相应程序。求解算法如下:(1)初始化:赋初值 0.0 至 sum。(2)输入一个数 x,并累加到 sum 中。(3)输入一个数 x,并累加到 s
2、um 中。(4)输入一个数 x,并累加到 sum 中。(5)输入一个数 x,并累加到 sum 中。(6)输入一个数 x,并累加到 sum 中。(7)输出结果 sum。(8)结束。根据上述算法,编写程序如下:sum=0.0READ *, xsum=sum+xREAD *, xsum=sum+xREAD *, xsum=sum+xREAD *, xsum=sum+xREAD *, xsum=sum+xPRINT *, sum=,sumEND第七章 循环结构程序设计-170-在上述算法中,第 2 至第 6 步的处理过程完全相同。在程序中,下面 2 条语句依次重复出现 5 次:READ *, xsum
3、=sum+x这是一个典型的重复处理问题。对于这类问题,如果问题规模比较小(如处理 5 个数),则设计的算法和编写的程序不会感到有何不足之处,相反还给人以简洁、清晰、直观的感觉。问题是当求解规模增大时(如处理 100 个数据),则算法中的处理过程“输入一个数 x,并累加到 sum 中”将增加到 100 个,算法设计人员要机械地重复写 100 个这样的处理过程,同样程序中的重复语句也增加至 100 组,程序员要机械地重复写 200 条这样的语句。从中可以看出,采用顺序结构不但大大增加了算法和程序长度,增加了存储开销,而且也大大降低了设计算法和编写程序的效率,浪费了程序设计人员宝贵的时间和精力。求解
4、这类问题的有效办法是采用循环结构,FORTRAN 90 提供了循环语句用于实现循环结构。对于上述问题,采用循环结构设计算法如下:(1)初始化:赋初值 0.0 至 sum,即 0.0sum。(2)1I。(3)如果 I5,则执行步骤(4),否则执行步骤(7)。(4)输入一个数 x,并累加到 sum 中。(5)I+1I。(6)转步骤(3)。(7)输出结果 sum。(8)结束。对于上述问题,采用循环语句编写程序如下:对于顺序结构,其算法步数和程序行数与问题规模成正比,当问题规模从 5 个数增加到100 个数时,算法步数从 8 步增加至 103 步,程序行数从 13 行增加至 203 行。而对于循环结构
5、,当问题规模从 5 个数增加到 100 个数时,算法步数也是 8 步,程序行数从 13 行降低至 7行,算法步数和程序行数与问题的规模大小几乎无关。在算法或程序中,重复地执行某个处理过程或语句块(程序段、语句组)的情形称为循环,被重复执行的处理过程或语句块称为循环体,具有循环特征的程序结构称为循环结构,将重复执行的处理过程或语句块设计成循环结构或编写成循环语句的过程称为循环设计,具有循环结构和循环语句的程序称为循环程序。循环体sum=0.0DO I=1,5READ *, xsum=sum+xENDDOPRINT *,sum=, sumEND循环体71 循环结构概述171例 7.1 求 S=1+
6、2+3+N 的值(N 由键盘输入,N2)。编写程序。解:求解这一问题,将执行 N-1 次加法运算,如果将等式写成 S=0+1+2+N,则执行 N 次加法运算,不同的是参与运算的操作数不同而已。显然该问题易采用循环结构实现之。用整型变量 S 保存和值,用 N 保存求和最大值,用 I 作计数器。编写程序如下:例 7.2 读入某班级考试成绩(人数不定),计算其平均成绩,并输出。编写程序。解:由于学生人数不定,所以输入的学生成绩个数不确定,以输入-1 作为结束标志(因为成绩不可能为负数),从而动态确定学生人数 n。平均成绩计算公式是:av=(x 1+x2+xn)/n对于计算平均成绩问题,核心问题是一个
7、求和问题,类似例 7.1问题。程序易采用循环结构和循环语句来实现。编写程序如下: 从上述例题中可看出,循环结构或循环语句由两部分组成:一部分是循环体,指需要重复执行的处理过程(语句序列、语句块);另一部分是循环控制机制,指根据条件判断循环体是否继续执行。INTEGER S,N,IREAD(*,*)NS=0DO I=1,NS=S+IEDNDOWRITE(*,*) S=,SEND循环体INTEGER sum,n,xREAL avsum=0;n=0READ *,xDO WHILE (x-1) GOTO 10av=sum/nWRITE(*,*) 平均成绩为:,avEND循环体假真n+1nsum+xsu
8、m输入成绩 x0sum0n开始结束x-1输入成绩 xsum/nav输出:av假真n+1nsum+xsum输入成绩 x0sum0n开始结束X=-1输入成绩 xsum/nav输出:avINTEGER sum,n,xREAL avsum=0;n=0READ *,xDOn=n+1sum=sum+xREAD *,xIF (x=-1) EXITENDDOav=sum/nWRITE(*,*) 平均成绩为:,avEND循环体第七章 循环结构程序设计-174-7.2 用 DO循环语句实现“计数型”循环7.2.1 DO循环语句DO 循环语句用于实现“计数型”循环结构,语句中直接指定循环的次数和范围。DO 循环语句
9、的一般格式是:: DO =,ENDDO 一个 DO 循环语句称为一个 DO 循环。DO 循环语句由三部分组成:DO 语句、循环体(语句序列)和 ENDDO 语句。DO 语句是 DO 循环的开始语句,指定用于控制循环执行的有关参数(初值、终值和步长),决定是否执行循环体。循环体是 DO 循环的主体,给出用于处理数据的有关语句,决定 DO 循环语句的执行结果。ENDDO 语句是 DO 循环的终端语句,表明 DO 循环语句到此结束(注意:不是循环语句执行结束),控制返回到 DO 语句执行。下面给出一些合法的 DO 循环语句:M=1;N=10;L=1DO I=1,10,2 !输出 1、3、5、7、9P
10、RINT *,IENDDODO I=10,1,-2 !输出 10、8、6、4、2PRINT*,IENDDODO I=M+1,N+2,L+3 !输出 2、6、10PRINT *,IENDDODO I=1,5 !输出 1、2、3、4、5PRINT *,IENDDODO A=0.1,0.5,0.1 !输出 0.1、0.2、0.3、0.4、0.5PRINT *,A循环体说明:v 为循环变量,一般为整型变量,用来控制循环次数。e1、e2 和 e3 为表达式,其类型与循环变量类型相同。e1 代表循环变量 v 的初值,e2 代表循环变量 v 的终值,e3 代表循环变量 v 的步长,e3 可缺省,e3 缺省指
11、 e3 为 1。在 Digital Visual FORTRAN 5.0 中,v、e1、e2 和 e3 的类型可以是实型,FORTRAN 90 不提倡使用实型。71 循环结构概述175ENDDO下面给出使用 DO 循环名字的 DO 循环语句:Odd:DO I=1,10,2 !输出 1、3、5、7、9PRINT *,IENDDO Odd上述 DO 循环语句的循环次数分别为:MAX(10-1)/2 + 1 ,0)=MAX(5,0)=5。MAX(1-10)/(-2) + 1 ,0)=MAX(5,0)=5。MAX(N+2-(M+1)/(L+3) + 1 ,0)=MAX(3,0)=3。MAX(5-1)/
12、1 + 1 ,0)=MAX(5,0)=5。MAX(0.5-0.1)/0.1 + 1 ,0)=MAX(5,0)=5。下面 DO 循环语句的循环次数为 0:Odd:DO I=1,10,-2PRINT*,IENDDO Odd下面 DO 循环语句的循环次数为 0:Even:DO I=10,1,2PRINT*,IENDDO Even下面程序中从 DO 循环语句内向外转移的操作合法:Odd: DO I=1,100,2IF (I10) GOTO 999PRINT*,IENDDO Odd999 PRINT*,finish loop.为 DO 循环的名称,可选择使用。为了提高 DO 循环语句的可读性,可通过为
13、DO循环语句命名,后必须跟冒号“:” 。DO 循环语句一旦命名,DO 循环语句中的 ENDDO 语句后必须跟相同的,否则产生语法错误。循环次数计算公式是:MAX(e2-e1)/e3 + 1 ,0)。e1、e2、e3 取值应在循环变量 v 的取值范围之内。如循环变量类型为:INTEGER(1),取值范围为-128127,则 e1、e2、e3 取值应在此范围之内,否则将产生意想不到的错误。e3 不能为 0,否则在运行时产生除 0 错误。如果 e30,则一般要求 e1e2,否则循环次数为 0,即循环体一次也不执行。如果 e30,则执行循环体直到 ENDDO 语句。(5)执行 ENDDO 语句,给循环
14、控制变量 v 增加一个步长 e3,即 v+e3v。循环次数减 1,即 r-1r,转(4)继续执行。DO 循环语句的执行过程如图 7-6 所示。计算表达式 e1,e2,e3e1 v计算循环次数 r:MAX(INT(e2-e1)/e3 +1),0)rr 0执行循环体v+e3 vr-1 rDO 循环语句下面一条语句真假图 7-6 DO 循环语句执行过程循环结束后,循环变量 v 的值有意义,其值为最后一次增加步长后得到的值。72 用 DO 循环语句实现“计数型”循环177从 DO 循环语句的执行过程可以看出,在循环体执行前计算循环次数,循环体的执行过程不影响循环次数(转移语句除外)。循环体中虽然不允许
15、修改循环变量 v 的值,但允许修改表达式 e1、e2 和 e3 中所含变量的值,其修改不影响循环次数。下面程序中 DO 循环语句的循环次数为 3:M=1;N=5;L=1DO I=M,N+5,L+1 !输出 1、3、5、7、9PRINT*,I,M,N,LM=M+1;N=N*I;L=2*L+IENDDO程序运行后,输出结果为:1 1 5 13 2 5 35 3 15 97 4 75 239 5 525 53例 7.3 打印 5 个随机数。解:这是一个重复问题,可用循环 5 次的 DO 循环语句实现。REAL RDO I=1,5CALL RANDOM_NUMBER(R)PRINT “(1X,F8.3
16、)“,REND DOEND程序运行后,输出结果为:0.0000004 0.0 254804 0.3525162 0.6669145 0.9630556例 7.4 计算 4!,并输出。解:4!=1234。对于 n!,计算公式是:n!=123(n-1)n。该问题显然是一个重复计算问题,需做 n-1 次乘法。可用 DO 循环语句实现。PARAMETER(n=4)INTEGER :factor=1DO i=2,4factor=factor*iPRINT*,i,! =,factorEND DOEND程序运行后。输出结果为:2! = 23! = 6第七章 循环结构程序设计-178-4! = 247.3 用
17、 DO WHILE循环语句实现循环7.3.1 DO WHILE循环语句DO WHILE 循环语句用于实现“当型”循环结构,语句中可给出控制循环执行的条件。DO WHILE 循环语句是一条结构化语句。DO WHILE 循环语句一般情况下用于实现循环次数不确定的循环,也可用它实现循环次数已知的循环,所以该语句有很好的通用性。DO WHILE 循环语句的一般格式是:: DO WHILE ()ENDDO 一个 DO WHILE 循环语句称为一个 DO WHILE 循环。DO WHILE 循环语句由三部分组成:一个 DO WHILE 语句、一个循环体(语句序列)和一个 ENDDO 语句。DO WHILE
18、 语句是 DO WHILE 循环的开始语句,指出用于控制循环执行的循环条件(逻辑表达式),决定是否执行循环体。循环体是 DO WHILE 循环的主体,给出用于处理数据的有关语句,决定 DO WHILE 循环语句的执行结果。ENDDO 语句是 DO WHILE 循环的终端语句,表明 DO WHILE 循环语句到此结束(注意:不是循环语句执行结束),控制返回到 DO WHILE 语句执行。下面给出两个使用合法 DO WHILE 循环语句的程序:第二个程序中使用了更严格和复杂的逻辑表达式作为循环控制条件。循环体说明:可以是关系表达式,也可以是复杂的逻辑表达式,但不能是算术表达式和字符表达式。PROGRAM cycle1sum=0READ *,xDO WHILE (x-1)sum=sum+xREAD *,xENDDOPRINT *,sum=,sumENDPROGRAM cycle2sum=0READ *,xDO WHILE (0=x .AND. x=100)sum=sum+xREAD *,xENDDOPRINT *,sum=,sumEND使用 DO WHILE 循环语句时要特别注意死循环的产生,要保证循环体中至少有一条对循环控制条件有影响的语句,否则将产生死循环,引起严重后果。