第5章循环结构程序设计 循环结构可以处理程序中需要被重复执行的操作。首先,通过一个例子说明在程序设计中使用循环结构的必要性。假设有如下程序: 从键盘上输入10个整数,求它们的最大数。不难看出,如果只采用顺序结构和选择结构编写这个程序,将会出现冗长的代码,不仅执行效率低而且可读性差,使用循环结构则可以极大地提升程序的编写效率。 实现循环结构的语句称为循环语句,也叫重复语句。循环语句包括如下4类。 (1) while语句。 (2) do…while语句。 (3) for语句。 (4) 用goto语句和if语句构成循环。 本章重点: (1) while语句、do…while语句、for语句的用法。 (2) 多重循环语句的用法及注意事项。 (3) break与continue语句的区别。 (4) 循环结构程序设计的方法。 本章难点: (1) do…while语句中条件表达式的书写。 (2) 多重循环语句的执行流程。 (3) 循环结构算法的思维训练。 5.1while语句 while语句也叫“当型循环语句”,其一般形式如下:图5.1while语句流程图while(表达式) { 循环体语句 }while语句流程图如图5.1所示。 当while语句执行时,首先计算“表达式”的值,若该值为假(即为0),则终止执行while语句;否则,就执行“循环体语句”,执行完毕后,再次计算“表达式”的值,并根据该值的真假,决定是否继续执行循环体语句,如此重复下去,直到“表达式” 的值为假退出该循环结构。 第 5 章循环结构程序设计C语言程序设计【说明】 (1) while语句括号中的“表达式” 可以是任意类型表达式,必须用圆括号“()”括起来。 (2) “循环体语句”部分可以是单个语句,也可以是多个语句。如果是多个语句,必须用一对花括号“{ }”将它们括起来构成复合语句。 (3) while语句的特点是:先执行表达式,后执行循环体。 图5.2例5.1流程图 【例5.1】从键盘上输入10个整数,求它们的最大数。 【分析】对于需要使用循环结构的程序,读者需要弄清楚两个基本问题。 (1) 需要被重复执行的操作是什么,换句话说,循环体是什么。 (2) 循环体的执行需要满足的判别条件是什么。 基于以上两个问题,对这道题目的要求做出以下分析。 (1) 要重复执行以下操作: 输入一个数,把它与表示最大数的变量进行比较,如果它大于最大数,则将它的值赋值给最大数变量。 (2) 要确保上述的循环体能够执行10次。那么,怎样确保这一点呢? 注意: 表示最大值的变量的初始值应该如何处理?可以在循环结构之前先输入一个数,并将该数赋值给表示最大值的变量。为了能够确保输入的数据刚好是10个,循环体的执行次数将会相应地变为9次。为了便于更加清晰地理解该程序的执行过程,读者可以参照本程序的流程图,如图5.2所示。 【程序】#include int main() { int x,max,i; scanf("%d",&x); max=x; i=1; while(i<10) { scanf("%d",&x); if(max int main() { int m,n,i,min,t; printf("请输入整数m和n:\\n"); scanf("%d%d",&m,&n); if(m<=0||n<=0) printf("输入错误!"); else { min=m int main( ) { int sum=0,i; scanf("%d",&i); while(i<5) sum+=i++; printf("sum=%d",sum); return 0; }(2) do…while语句代码段。#include int main( ) { int sum=0,i; scanf("%d",&i); do { sum+=i++; }while(i<5); printf("sum=%d",sum); return 0; }运行时,若两个程序都是输入1,则运行结果均为sum=10;如果都是输入5,则第一个程序得到结果sum=0,而第二个程序得到结果sum=5。 【例5.4】输入一个正整数n,求n!。 【分析】用变量jc表示阶乘计算的最终结果,并令其初值为1,然后把从2到n的所有整数逐个乘到jc中去。 (1) 输入一个正整数n。 (2) 置jc的初值为1,循环变量a的初值为1。 (3) 把a乘到jc中去,即执行jc=a。 (4) a的值自增。 (5) 当a≤n时,转到(3),否则转到(6)。 (6) 输出jc的值。 【程序】#include int main( ) { int n,a; long jc; printf("请输入一个正整数n:"); scanf("%d",&n); a=1; jc=1; do { jc=a; a++; }while(a<=n); printf("%d!=%ld\\n",n,jc); return 0; }【运行】请输入一个正整数n:5 5!=1205.3for语句 for语句是一种使用频率较高的循环语句,其一般形式为: 图5.4for语句流程图 for(表达式1;表达式2;表达式3) 循环体语句for语句流程图如图5.4所示。 执行过程如下: (1) 计算“表达式1”。 (2) 计算并判断“表达式2”,若该值为真(非0),则执行循环体语句;若为假(等于0),则转到第(5)步。 (3) 计算“表达式3”。 (4) 转到第(2)步继续执行。 (5) 结束循环。 【说明】 (1) for语句的圆括号内必须包含并且只能包含两个分号“;”。 (2) for语句的3个表达式(即“表达式1”“表达式2”“表达式3”)可以是任意类型表达式。“循环体语句”可以是一条语句,也可以是多条语句,如果是多条语句,必须用一对花括号“{ }”把它们括起来成为复合语句。 (3) “表达式1”可以省略。比如: for(;j<10;j++) x=x-j;相当于while(j<10) { x=x-j; j++; }(4) “表达式2”也可以省略。由于“表达式2”起到判断并控制循环是否继续执行的作用,因此当它省略时,则不判断循环控制条件,也就是认为“表达式2”始终为真,循环将无终止地执行下去。例如: for(j=1; ;j++) x=x-j;相当于j=1; while(1) { x=x-j; j++; }(5) “表达式3”也可以省略。例如: for(j=1;j<10;) x=x-j;相当于j=1; while(j<10) x=x-j;【例5.5】输入一个正整数,判断其是否为素数。 【分析】素数除了能表示为它自己和1的乘积以外,不能表示为任何其他两个正整数的乘积。对于一个整数m,判断算法如下: (1) 设置一个标志变量flag,令其初值为1。 (2) 将变量i的值置为2。 (3) 若i>m,则转到(6);若i≤m,则用m除以i,如果不能整除,则转到(4),否则转到(5)。 (4) 将i的值自增,再转到(3)。 (5) 将flag的值置为0,再转到(4)。 (6) 如果flag等于1,则m是素数,否则就不是素数。 【程序】#include #include int main( ) { int m,i,flag=1; printf("请输入一个正整数m:"); scanf("%d",&m); for(i=2;i<=sqrt(m);i++) if(m%i==0) flag=0; if(flag) printf("%d是素数\\n",m); else printf("%d不是素数\\n",m); return 0; }【运行】请输入一个正整数m:7 7是素数【说明】 (1) 在本例的程序中,使用库函数sqrt()计算m的平方根,所以在程序的开头要声明它的头文件math.h。 (2) 请读者参照5.7节中“break语句”的作用思考一下,此程序能否进行简化? 【例5.6】有一个分数序列2/1,3/2,5/3,8/5,13/8,21/13,…,求出这个数列的前10项之和。 【分析】首先分析这个数列的规律: 从第2个数开始,该数项的分母是前一个数项的分子,该数项的分子是前一个数项的分子与分母之和。算法如下。 (1) 用s表示各个数项之和,令其初值等于0;用a表示数项的分子,初值赋为2;用b表示数项的分母,初值赋为1。 (2) 用i表示加到s中的数项的个数,初值为1。 (3) 若i>10,则转到(8);否则转到(4)。 (4) 将a/b加到s中。 (5) 将前一个数项的分子与分母之和赋值给后一个数项的分子。 (6) 将前一个数项的分子赋值给后一个数项的分母。 (7) 将i的值自增,再转到(3)。 (8) 输出结果。 【程序】#include int main( ) { int i; float a=2.0,b=1.0,s=0; for(i=1;i<=10;i++) { s+=a/b; a=a+b; b=a-b; } printf("该数列前10项之和为:%f\\n",s); return 0; }【运行】该数列前10项之和为16.4799065.4用goto语句和if语句构成循环5.4.1goto语句goto语句也叫转向语句,用于将程序的执行流程转移到由goto语句指定的位置(某个标号语句处)。它的一般形式为: goto语句标号;其中,语句标号由标识符表示。 使用if语句和goto语句可以构成循环结构。但是,这样的循环形式不仅容易造成程序结构的混乱,而且容易降低程序的可读性,因此,在结构化程序设计中应当尽量避免使用goto语句。 5.4.2带标号语句 带标号语句的一般形式为: 标号:语句;带标号语句的作用是便于其他语句将程序的执行流程转移到标号所标记的位置。 【例5.7】用if语句和goto语句构成循环,求解∑10i=1i。 本题比较简单,在此直接给出参考程序: #include int main( ) { int a=1,s=0; loop: if(a<=10) { s+=a; a++; goto loop; } printf("1到10的和等于%d\\n",s); return 0; }5.5循环的嵌套 如果循环语句的循环体内包含另一个完整的循环结构,则称为循环的嵌套。如果一个循环体内只嵌套一层循环,这种结构就称作二重循环。对于二重循环而言,处于内部的循环叫作内循环,处于外部的循环叫作外循环。前几节介绍的几种循环语句均可以互相嵌套。对于嵌套的循环结构,应当特别注意内外循环的执行过程。下面举例说明嵌套循环的程序设计方法。 【例5.8】编程实现下面图形的输出。      【分析】对于要输出的这个图形,应当考虑输出行数、每行星号的个数、每行星号的位置3个因素。经过分析发现,第i(-2≤i≤2)行星号的个数等于5-2abs(i)。对于每行星号的位置,取决于它的前导空格个数,第i行的前导空格数等于abs(i)。需要说明的是,abs(i)表示i的绝对值。算法如下。 (1) 将i的初值设置为-2。 (2) 当i>2时,转向(7),否则转向(3)。 (3) 输出abs(i)个空格。 (4) 输出5-2abs(i)个星号。 (5) 输出换行符。 (6) i的值自增,并转向第(2)步。 (7) 程序结束。 【程序】#include #include int main( ) { int i,j; for(i=-2;i<=2;i++) { for(j=1;j<=abs(i);j++) printf(" "); for(j=1;j<=5-2abs(i);j++) putchar(''); printf("\\n"); } return 0; }【运行】