第3章 While循环程序设计
本章重点 § 循环的概念 § while 及 do-while 循环的执行过程 § while 循环的应用 § for 循环的执行过程 § 循环的嵌套 Company Logo
本章难点 §循环条件判断 § while、do~while、for循环的执行过程 § for语句的变形 §循环嵌套的应用 Company Logo
三种基本的循环语句:while语句、do-while语句和for语句。 3.1 循环的概念 三种基本的循环语句:while语句、do-while语句和for语句。 1)while循环语句和for循环语句在初始时,首先测试循环条件,如果满足则执行循环体,如不满足则退出循环语句;do-while循环语句则是先执行循环体,后测试循环条 件,所以循环体不管怎样都必然会被执行至少一次。 2)此三种循环语句都是根据循环条件来决定是否继续执 行,所以在循环体内部或循环条件中必须存在改变循环条件的动作;否则,可能会出现死循环等异常情况。 3)C语言的for语句并不同于一般的狭义计数循环语句,其循环条件包含的内容可以不是单一的计数,而可以有其他的形式和动作,如getch( )一类的取值动作。 Company Logo
3.2 while的循环 while循环通常叫做前判断循环,意思是指首先判断循环的条件是否满足,如条件满足则执行循环体,条件不满足则退出循环体,此种循环有可能循环体一次也不执行。 While循环的格式如下: while(条件表达式) { 循环体 } Company Logo
其中: 1)循环体:程序中反复执行的一段程序被称为循环体,一般以{ }括起来。 2)循环条件:执行循环的条件,一般为关系表达式或逻辑表达式。 While循环流程图如图3.1所示。 其中: 1)循环体:程序中反复执行的一段程序被称为循环体,一般以{ }括起来。 2)循环条件:执行循环的条件,一般为关系表达式或逻辑表达式。 3)while循环的执行过程如下: ① 判断循环条件(表达式)。 ② 如果条件为假(即为0),while循环结束,然后执行循环体后面的语句。 ③ 如果条件为真(即非0),则执行循环体中的语句。 ④ 返回到第1步,判断循环条件。 图3.1 while循环流程图 Company Logo
【例3.1】计算1+2+3+…+99+100的和 分析:计算1~100的和,是重复做100次加法,首先定义变量sum及用于循环变量i,每循环一次,做一次sum=sum+i运算,且循环变量i自增长1,当i增加到101时循环结束。程序流程图如图3.2所示。 i是这个循环结构的循环变量,以它来控制循环的继续或者退出。 图3.2 流程图 Company Logo
#include<stdio.h> int main( ) { int i,sum=0; i=1; while(i<=100) sum=sum+i; i++; } printf("sum=%d\n",sum); return 0; 注意:如果while中的循环体由两条以上的语句构成,用'{'与'}'构成一个程序块,while中的条件表达式后不能有';'号。 编译程序3-1.c,并执行程序3-1.exe,程序执行后在屏幕上输出:sum=5050 Company Logo
1. 若例3.1循环体大括号省略,程序运行时会出现什么情况?为什么? 2. 如果在while(i<=100)后加“;”号,请思考程序运行的结果是什么? Company Logo
上机操作与练习1 1.求0+2+4+…+98+100的和。 2.求100+101+102+…+200的和。 Company Logo
【例3.2】 输出1~100之间的所有奇数。 分析:我们可以设置i从1开始,每循环1次,输出i,之后将i的值增2,循环的条件是i<=100,输出的i即为1~100之间的奇数。流程图如图3.3所示。 图3.3 输出1~100的所有奇数流程图 Company Logo
#include<stdio.h> int main( ) { int i=1; while(i<=100) printf("%4d " , i); i+=2; } printf("\n"); return 0; 编译程序3-2.c,并执行程序3-2.exe,观察程序输出的结果 Company Logo
若要输出1~100之间的所有偶数,程序该作何更改? Company Logo
编写程序求n~m之间所有奇数和,n、m从键盘输入。 上机操作与练习2 编写程序求n~m之间所有奇数和,n、m从键盘输入。 【例3.3】 求5!的值(5!=1×2×3×4×5) 分析:设乘积t的初始值为1,乘数项i的初试值也为1,每循环1次,i与t相乘,得到一个新的t,然后i的值增1,再与t相乘,如此反复直到i>5。退出循环后,输出t即为所求值。流程图如图3.4所示。 图3.4 求5!的流程图 Company Logo
#include<stdio.h> int main( ) { int i=1 , t=1 ; while (i<=5) } printf("5! =%d\n", t); return 0; 编译程序3-3.c,并执行程序3-3.exe,程序执行后在屏幕上输出: 5!=120 如何求2×4×6×…×10的乘积。 Company Logo
上机操作与练习3 编写程序求 ,n、m从键盘输入 。 【例3.4】 若s=1+1/2+1/3+1/4+……+1/n, 求和s大于3为止时的s与n的值。 分析:设置变量n,每循环1次n的值增1,s变量用来存放各数的和,当s的值大于3时,循环结束。因此,在while条件里设置s<=3。流程图如图3.5所示。 Company Logo
图3.5 流程图 Company Logo
注意: 编辑源程序代码3-4.c: #include<stdio.h> int main( ) { int n=1 ; double s=0; while (s<=3) s+=1.0/n; n++ ; } printf("s=%lf n=%d\n", s,n-1); return 0; 注意: 1. 程序中1.0/n不能写成1/n,请 读者自己思考。 2. s+=1.0/n;等同于s=s+1.0/n; Company Logo
模仿例3.4,求s=1-1/2+1/3-1/4+……的值,直到误差<0.00001。 上机操作与练习4 模仿例3.4,求s=1-1/2+1/3-1/4+……的值,直到误差<0.00001。 【例3.5】 求Fibonacci数列的前20项,Fibonacci数列 是前 两项之和,即an=an-1+an-2 ,其中a1=a2=1。 分析:将a、b、c分别表示连续的三项,第一次计算之后,将原来的b赋值给a,再将c赋值给b,再求出c=a+b,保证运算公式c=a+b每次循环都成立。每次求出的c加上第1、2项即为Fibonacci数列。 第一次计算:a(1) b(1) c(2) c=a+b 第二次计算: a(1) b(2) c(3) c=a+b 第三次计算: a(2) b(3) c(5) c=a+b Company Logo
编辑源程序代码3-5.c: #include<stdio.h> int main() { int a, b, c, i; a=1;b=1;i=3; printf("%d,%d,",a,b); /*先输出数列的1、2两项*/ while (i<=20) { c=a+b; a=b; b=c; printf("%d,",c); i++; } return 0; Company Logo
【例3.6】 求s=1!+2!+3!+4!+5!的值。 分析:关于求阶乘,此问题只是将每次阶乘的结果求和。阶乘的项依次以1、2、3、4、5变化。流程图如图3.6所示。 图3.6 流程图 Company Logo
编辑源程序代码3-6.c: #include<stdio.h> int main( ) { int i=1 , t=1 ,s=0,j=1 ; while (i<=5) t=t*i; s=s+t; i++; } printf("s=%d\n", s); return 0; Company Logo
3.3 do-while 循环 do-while循环是后判断循环,不论循环的条件是否满足,循环体至少应执行一次,do-while循环的语句格式如下: do { 循环体 }while(表达式); 语句执行流程图如图3.6所示。 图3.6 语句执行流程图 do-while语句是先执行后判断,因此它至少要执行一次循环体。不同于while语句,先判断后执行,如果条件不满足,循环体可以一次都不执行。 Company Logo
【例3.7】输入任意一个正整数,按低位开始输出它各个 位置上的数字。例如:531输出135。 分析:先求出531除以10的余数,得到1;将531除以10得到53;再求53除以10的余数,得到3,将53除以10,得到5。这样将1、3、5全部分解出来。 执行步骤:设被除数为m,余数为n,进行下列运算: 1)n=m%10; 2)m=m/10; 3)循环的条件为m!=0。 流程图如图3.7所示。 Company Logo
编辑源程序代码3-7.c: 图3.7 流程图 #include<stdio.h> int main( ) { long m , n; printf("请输入一个正整数:"); scanf ("%ld",&m); do n=m%10 ; m=m/10 ; printf("%ld", n); } while(m); return 0; } 图3.7 流程图 Company Logo
模仿例3.7,求各个位数之和。例如:输入531输出9(1+3+5)。 上机操作与练习6 模仿例3.7,求各个位数之和。例如:输入531输出9(1+3+5)。 2.输入任意一个正整数,求出此数的相反数,最后输出此数。例如输入 531,输出为135,要求一次输出。 Company Logo
3.4 for 循环 C语言中的for循环语句应用比较灵活,虽然主要用于定数循环,但也 可以不定数循环,它完全可以替代while循环。 for语句格式如下: for(初始化表达式;条件表达式;增量表达式) { 循环体 } 其中: 1)初始化表达式:通常用来给循环变量赋初值,一般是赋值表达式。也允许在for语句外给循环变量赋初值,此时可以省略该表达式。 2)条件表达式:通常是循环条件,一般为关系表达式或逻辑表达式。 3)增量表达式:通常可用来修改循环变量的值,一般是赋值语句。控制变量每循环一次后按什么方式变化。 Company Logo
for语句的执行过程如下: 1)计算初始化表达式的值。 2)计算条件表达式的值,若值为真(非0)则执行循环体中的语句,转第3)步;若值为假(0)则转第4)步。 3)计算增量表达式的值,转第2)步重复执行。 4)结束循环。 程序流程图如图3.8所示。 图3.8 程序流程图 Company Logo
【例3.8】求1+2+3+…+100的和,用for语句实现 。 分析:在计算求和时,采用循环的方法,把1加到s,再把2加到s,一直加到100,然后循环结束。程序设计中首先把存放结果的变量s置零,循环变量i初值为1,把i加到s中,每循环一次,i增1,其流程图如图3.9所示。 Company Logo
图3.9 流程图 Company Logo
#include<stdio.h> int main() { int i,sum=0; for(i=1;i<=100;i++) sum+=i; printf("1+2+…+100=%d\n",sum); return 0; } Company Logo
注意:for语句中的各表达式都可以是逗号表达式,也可都省略,但分号作为间隔符不能少。上述for语句可以写成以下形式: 形式1: int i=1,sum=0; for( ;i<=100;i++) sum+=i; 形式2: for( ;i<=100; ) { i++; } 形式3: for( ; ; ) if(i>100) break; 形式4: for(int i,sum=0 ;i<=100 ;sum+=i,i++ ) ; Company Logo
求1+2+…+100的和,分别用以上几种形 式在机器上调试通过。 2.求2+4+6+…+200的和。 提示:把增量表达式改为:i+=2。 Company Logo
【例3.9】输入一个1~10间的自然数,用for语句求这个 数的阶乘。例如,输入5,输出为5!=120 。 分析:5的阶乘为1*2*3*4*5,设乘积s的初始值置为1,循环变量i初值也为1,运算:s=s*i,i的值从1每次循环增1,直到5。其流程图如图3.10所示。 图3.10 流程图 Company Logo
#include<stdio.h> int main() { int i,n,s=1; scanf("%d",&n); for(i=1;i<=n;i++) s*=i; printf("%d!=%d\n",n,s); return 0; } Company Logo
输入一个5~10之间的整数n,求1!+2!+3!+…+n!。例如,输入5,输出为1!+2!+3!+…+5!=153。 分析:设阶乘的积存放在s中,s的初始值置为1,循环变量i的初值也为1,各步阶乘的和存放在sum中,sum的初值为0,循环的第1步可求得1的阶乘,把1的阶乘加入sum,循环的第2步可求得2的阶乘,把2的阶乘也加入sum, i的值从1每次循环增1,直到n。 Company Logo
【例3.10】 从键盘输入的正整数,按逆序输出在屏幕上。 例如,输入3456,输出为6543。 分析:从键盘输入的正整数对10取余数,先输出最低位,然后使这个正整数除10,再将余数输出,再除10,直到这个数为0。其流程图如图3.11所示。 图3.11 流程图 Company Logo
#include<stdio.h> int main( ) { int num; int digit; printf("input a number\t"); scanf("%d",&num); for( ; num!=0; num=num/10) digit=num%10; printf("%d",digit); } printf("\n"); return 0; Company Logo
【例3.11】用循环体是空语句的for循环,计算输入的一 行字符的字符个数 。 分析:程序中的循环条件为getchar( )!='\n',判断从键盘输入的字符是不是回车。增量表达式用于字符计数,而不是用来修改循环变量,所有的工作都在表达式中已完成,循环体是空语句了,注意此时空语句的分号不可少。流程图如图3.12所示。 图3.12 流程图 Company Logo
#include<stdio.h> int main() { int n=0; printf("请输入一串字符:\n"); for(;getchar()!='\n';n++); printf("%d\n",n); return 0; } 注意:函数getchar( )是从键盘读入一个字符。 Company Logo
3.5 break语句和continue语句 Break 语句可应用于循环体中或switch语句中。在循环中,当程序执行到break语句后,立即退出循环;在多分支语句中,程序遇到break语句时,停止以下分支的执行。 Continue 语句只能位于循环体内,执行continue语句后,continue语句到循环体末尾之间的语句会被跳过,但会接着执行下一次循环。break语句和continue语句往往与if一起使用。 Company Logo
【例3.12】 若s=1+1/2+1/3+1/4+…+1/n,求和s大于3为止 时的s与n的值,用break语句跳出循环。 分析:设置一个无限循环,当和s的值大于3时,用break语句跳 出循环。流程图如图3.13所示。 编辑源程序代码3-12.c: #include<stdio.h> int main( ) { int n= 1; double s=0; while (1) /*非0(永真),无条件循环*/ s+=1.0/n ; if (s>3) /*当s>3时,执行break跳出循环*/ break; n++ ; } printf("s=%f n=%d\n", s,n); return 0; Company Logo
图3.13 流程图 Company Logo
求s=1/1!+1/2!+1/3!+1/4!+…,要求误差<0.00001。 上机操作与练习7 求s=1/1!+1/2!+1/3!+1/4!+…,要求误差<0.00001。 【例3.13】 判断某整数m是否是素数,m从键盘输入。 分析:采用这样的算法:让m被2~ 除,如果m能被2~ 之中任何一个整数整除,则提前结束循环,此时i必然小于或等于 ;如果m不能被2~ 之间的任何一个整数整除,则在 完成最后一次循环后,i再加上1,因此i= +1,然后才终止循环。 在循环之后判别i的值是否大于或等于 +1,若是,则表明未曾被2~ 之间的任意整数整除过,因此输出是素数。程序流程图如图3.14所示。 Company Logo
编辑源程序代码3-13.c: #include<stdio.h> #include<math.h> int main( ) { int i, m, k; i=2; scanf("%d",&m); k=(int)sqrt(m); while (i<=k) if (m%i==0) break; i++; } if (i>=k+1) printf("%d是素数\n",m); else printf("%d不是素数\n",m); return 0; Company Logo
上例为什么只要判断m是否被2~之间的某一整数整除,而不需要判断2~m-1,请读者自行思考。 图3.14 判断是否是素数的流程图 Company Logo
上机操作与练习8 求整数100~1000之间所有的素数。 Company Logo
3.6 循 环 嵌 套 当然循环可以嵌套,且三种循环语句可以相互嵌套。如for语句可与while、do~while语句相互嵌套,构成多重循环。 循环和循环一般是并列或嵌套的,绝不能交叉。在循环中可用转移语句把流程转到循环体外,但绝不能从外面转入循环体内。 【例3.14】用户输入一个正整数,判断它是否是素数 之后,若用户还想判断其他数字是否为素 数时,需要重新运行程序,非常麻烦。我 们可以编写一个新的程序,可以让用户多 次重复输入。 Company Logo
分析:设计一个无限循环,当输入1时继续测试数字,输入0时则退出循环。 流程图如图3.15所示。 图3.15 流程图 Company Logo
#include<stdio.h> #include<math.h> int main( ) { int i, m, k, c; do { i=2; scanf("%d",&m); k=sqrt(m); while (i<=k) if (m%i= =0) break; i++; } if (i>=k+1) printf("%d是素数\n",m); else printf("%d不是素数\n",m); printf("输入1继续,输入其他数字退出:"); scanf("%d",&c); if (c==1) continue; else break; }while(1); /*永真循环*/ 编辑源程序代码3-14.c: Company Logo
上机操作与练习9 用双重循环的方式输出下列图形: * * * * * * * * * * * * * * * * * * Company Logo
【例3.15】 输出一张乘法九九表。 分析:用两个嵌套for循环,外for循环执行9次,每一次包含一个内for循环,用来打印1 【例3.15】 输出一张乘法九九表。 分析:用两个嵌套for循环,外for循环执行9次,每一次包含一个内for循环,用来打印1 行。这样两个for循环打印9行。流程图如图3.16所示。 编辑源程序代码3-15.c: #include<stdio.h> int main() { int i,j; for (i=1;i<10;i++) printf("%4d",i); printf("\n--------------------------------------------------\n"); for (i=1;i<10;i++){ for (j=1;j<=i;j++) printf("%2d*%d=%-3d",i,j,i*j); printf("\n"); } return 0; Company Logo
图3.16 流程图 Company Logo
编译程序3-15.c,并执行程序3-15.exe,程序执行后在屏幕上输出: 1 2 3 4 5 6 7 8 9 ---------------------------------------------------- 1*1=1 2*1=2 2*2=4 3*1=3 3*2=6 3*3=9 4*1=4 4*2=8 4*3=12 4*4=16 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 Company Logo
【例3.16】 编写程序,打印如下所示的输出。 * * * * * * * * * * * * * * * 【例3.16】 编写程序,打印如下所示的输出。 * * * * * * * * * * * * * * * 分析:外循环5次,循环语句为for(i=0;i<5;i++);然后循环空格,循环语句为 for(j=0;j<i;j++);内层循环5次,循环语句为for(k=0;k<5-i;k++),流程图 如图3.17所示。 Company Logo
for(i=0;i<5;i++){ for(j=0;j<i;j++) printf(" "); 关键语句如下: for(i=0;i<5;i++){ for(j=0;j<i;j++) printf(" "); for(k=0;k<5-i;k++) printf("*"); printf("\n"); } 图3.17 流程图 Company Logo
#include<stdio.h> int main( ) { int i,j,k; for(i=0;i<5;i++){ for(j=0;j<i;j++) printf(" "); for(k=0;k<5-i;k++) printf(" *"); printf("\n"); } return 0; 编译程序3-16.c,并执行程序3-16.exe,程序执行 后在屏幕上输出: * * * * * * * * * * * * * * * Company Logo