1、共 36 页 第 1 页,第五章 循环结构程序设计,共 36 页 第 2 页,5.1 为什么使用循环,循环是有规律的重复操作。可以将复杂问题分解为简单的操作过程,程序只需对简单过程描述,这些过程的多次重复就可完成对问题的求解。,例:求1+2+3+100的和。,算法1:直接写出算式 sum=1+2+3+4+5+100,算法2:考虑到1+2+3+100可以改写为:(1+2)+3)+100),则有,共 36 页 第 3 页,S1:p1=0+1; S2: p2=p1+2; S100: p100=p99+100 ,结果在p100里。,算法3:用变量i存放加数,变量p存放上一步的和。那么每一步都可以写成:
2、p+i,然后把p+i的和存入p,即每步都是p=p+i。,S0: p=0,i=1 S1: p=p+i, i=i+1 S2: p=p+i, i=i+1 S3: p=p+i, i=i+1 S100: p=p+i, i=i+1,共 36 页 第 4 页,算法4:在上面的算法基础上采用循环功能实现。,S0: p=0,i=1(循环初值) S1: p=p+i, i=i+1(循环体) S2: 如果i小于或等于100,重复执行步骤S1及S2;否则,算法结束(循环控制)。 那么p中的值就是1+2+100的值。,循环变量的初始值循环进入条件循环体循环变量的增值,循环的基本要素,循环变量的初值,满足条件则执行循环体,
3、重复执行的语句,循环变量的改变,进一步测试条件,共 36 页 第 5 页,while循环,1. 格式:while(表达式) 循环体 2. 功能:先判断表达式的值,若为非零,重复执行循环体语句,再判断直到表达式的值为零,退出循环体。,条件,即:测试-执行-测试-执行-,5.2 while语句与do -while语句,while (条件)语句组,main ( ) int s,n ; s=0 ; n=1; while(n=100) s=s+n ;n+; printf(“%dn”, s); ,100,共 36 页 第 6 页,(1)当循环体中语句多于一条时,用 ,否则,循环只对第一个;起作用. (2)
4、循环体内部必须有实现对循环变量增值的语句,否则,易出现“死循环”. (3) 条件表达式要有括号,后面不加分号. (4) 注意条件的边界值.,例题:求 1+2+3+n=10000的最大的n。,main( ) int a,k; a=k=0;while(a=10000) +k; a+=k; printf(“1+2+3+%d=%dn”,k-1,a-k); ,3.说明:,例: 一个百万富翁遇见一个陌生人,达成换钱的协议:陌生 人说:“第一天我给你10万元,你只需给我一分钱;第二天 我依然给你10万元,你只需给我二分钱;以后你每天给我的钱数是前一天的二倍,直到满30天”,富翁很高兴,欣然同意了。请你编程计
5、算一下,30天后每人各得多少钱?,分析:设 fu: 富翁得到的钱的总数;mo:陌生人得到的钱的总数; t : 陌生人每天得到的钱数; 第一天:fu=100000.0, t=0.01, mo=0.01 循环:230天fu=fu+100000.0;t=2*t ; mo=mo + t ;,共 36 页 第 8 页,main( ) int i=1;float fu, mo, t ;fu=100000.0; mo=0.01; t=0.01;while (i30) i + +;fu=fu+100000.0;t = 2*t ; mo=mo+t ; printf(“The rich mans money=%f
6、n“,fu);printf(“The strangers money=%fm“,mo);,程序如下,共 36 页 第 9 页,do 语句while (条件);,1. 格式:do 循环体 while(表达式); 2. 功能:先执行循环体,再判断表达式的值,若为非零,重复执行循环体语句,再判断.直到表达式的值为零,退出循环体,do -while循环,条件,即:执行-测试-执行-测试-,共 36 页 第 10 页,main() int n=1,s=0,x;scanf(“%d“,条件表达式后有分号,共 36 页 第 11 页,main() int s=0,x;scanf(“%d“, ,main()in
7、t s=0,x;scanf(“%d“,输入:12 输出: s=12,循环至少 执行一次,循环没有 被执行,输入:12 输出: s=0,while与do while的区别,共 36 页 第 12 页,计算表达式1初值; 计算表达式2并判断,当表达式2为0 时跳出循环,当表达式2非0,执行循环体语句,计算表达式3增量; 自动转到第二步(计算表达式2).继续执行。,for语句,初值表达式1 条件表达式2 增量表达式3,for (表达式1;表达式2;表达式3) 语句组 ,5.3 for语句实现循环,1. 格式 :,2. 功能 :,main( ) int n, s; for(n=1 ; n=100 ;n
8、+)s=s+n; printf(“%dn”,s); ,变量的增量,循环体,变量的初值,循环条件,共 36 页 第 13 页,1.表达式1,表达式2和表达式3均可缺省,for (;n100;n+) 缺省e1, n 应在循环之前赋初值 for (n=0;n+) 缺省e2, 造成死循环,不可使用! for (n=0;n100;) 缺省e3, n增量应在循环体内进行 for (; ;) 缺省e1,e2,e3 死循环 for (;n100;) 缺省e1,e3,分号始终不能缺省!,3.说明,共 36 页 第 14 页,2.表达式1和表达式3可是与初值、增量无关的逗号表达式,for (s=0,n=1;n=1
9、00;s=s+n, printf(“ %d” ,s) n+; for (s=0;n100;s=s+n,n+) printf(“ %d” ,s);,求累加和,n的初值在 for之前完成,增量在for 之外完成,共 36 页 第 15 页,例 求正整数n的阶乘n!,其中n由用户输入。,程序如下: main( ) float fact=1.0;int i,n;scanf(“%d“,共 36 页 第 16 页,5.4 几种循环的比较,1、C中的三种循环语句while( ) ,do-while( ), for( ) 都可由表达式控制重复执行一个循环体,都可以用来解决同一个问题,一般情况下,可以相互代替。
10、,2、三种循环各有特点:,1) 当循环次数及条件在程序运行中才能确定时,选用while( )或do-while( )语句 两者区别:while( ) 顶部测试,可能一次也不执行do-while( )底部测试,至少执行一次,共 36 页 第 17 页,(2) 如果初值,条件明显,循环次数已给出,选用for( )语句,功能最强。,(3) 出现“死循环”的几种情况for( ; ; )for( .; 非零常数表达式;)while(非零常数表达式)do while(非零常数表达式),main() int I=0,j=5; while(j10) j=I*2; printf(“%d”,j); 结果为: ?,
11、共 36 页 第 18 页,5.5 循环嵌套,一、循环嵌套的概念,1 2 3 4 5 6 7 8 9 - 1 2 4 3 6 9 4 8 12 16 5 10 15 20 25 6 12 18 24 30 36 7 14 21 28 35 42 49 8 16 24 32 40 48 56 64 9 18 27 36 45 54 63 72 81,在循环体中,又包含有循环结构。,行循环中包含了列循环。,双重循环,将一元钱换成硬币,共有多少种换法?,共 36 页 第 19 页,二、嵌套结构规则 一个循环体必须完完整整地嵌套在另一个循环体内,不能出现交叉。,外循环,内循环,交叉循环,外循环 入口,
12、内循环出口,内循环出口,外循环出口,三、循环嵌套的运行过程,外层循环取一个值,内层循环取遍所有的值,共 36 页 第 20 页,例:,每只公鸡5个钱,每只母鸡3个钱,每3只小鸡1个钱,用100个钱,买100只鸡,问公鸡、母鸡和小鸡各买几只?,分 析,定义变量x,y,z ,表示公鸡、母鸡和小鸡的只数,int x,y,z;for(x=1;x=20;x+)for(y=1;y=33;y+)for(z=1;z=300;z+) .,程序运算多少次?,百钱百鸡问题的解决,共 36 页 第 21 页,程序如下,main() int x,y,z; for(x=1;x20;x+)for(y=1;y=33;y+)
13、z=100-x-y;if(5*x+3*y+z/3=100) printf(“%d,%d,%dn”,x,y,z); ,共六组解: x y z 3 20 77 4 18 78 7 13 80 8 11 81 11 6 83 12 4 84,所求的z不能被3整除如何解决?,共 36 页 第 22 页,main( ) int a,b,c,k=0; for(a=0;a=100;a+)for(b=0;b=50;b+)for(c=0;c=20;c+) if (a+2*b+5*c=100)k+; printf(“%dn”,k); ,将一元钱换成一分,二分和五分的硬币,共有多少种换法?,定义变量a,b,c 定义
14、变量 k,循环体,计数器,共 36 页 第 23 页,要求:从键盘输入m值,输出m行每行m个*号。例:输入m=4,输出的图形如下:,思路: 1. 输入m; 2. 重复打印m行,每行打印m个*;,* * * * * * * * * * * * * * * *,1. 输入m; 2. for ( k=1; k=m; k+)打印一行中的 m 个 * ;,打印如下图形:,共 36 页 第 24 页,细化: 1. 输入m; 2. for ( k=1; k=m; k+) 打印 m 个 * ;换新行; ,1. 输入m; 2. for ( k=1; k=m; k+) for ( j=1; j=m; j+)pri
15、ntf (“*”);printf(“n”) ;,main ( ) int k, m, j;scanf ( “%d”, ,共 36 页 第 25 页,5.6 break和continue语句,break语句格式 break;,break语句的功能1.在switch语句中结束case子句,使控制转到 switch语句之外。2.在循环结构中,break语句使流程转向该循环体的外层继续运行。向外退出一层循环,break语句与continue语句,循环的退出,共 36 页 第 26 页,continue语句格式:continue;,continue语句的功能: continue语句仅能在循环语句中使用。
16、 它的作用不是结束循环,而是开始一次新的循环。结束一次循环 对于for语句,将控制转到执行增量和条件测试部分。 对于while和do-while语句,将控制转到条件测试部分。,循环的退出,共 36 页 第 27 页,break的使用,main( ) int i,j,a=0; for(i=0;i2;i+) for(j=0;j4;j+) if(j%2) break; a+; a+; # printf(“a=%dn”,a); ,a=4 a=5 a=6 a=7,1. i=0,j=0,if为0,a从0到1 j=1,if为1 退出 j循环 执行语句 # a从1到2,2. i=1,j=0,if为0,a从2到
17、3 j=1,if为1 退出 j循环 执行语句# a从3到4,练习1,共 36 页 第 28 页,main( ) int i,j,x=0; for(i=0;i2;i+) x+; for(j=0;j=3;j+) if(j%2) continue; x+; x+; # printf(“x=%dn”,x); ,x=4 x=8 x=6 x=12,1. i=0, x从0到1,j=0,if 为0 ,x从1到2 j=1,if 为1 j=2,if为0,x从2到3 j=3,if为1,执行 语句# x为4,2. i=1,x从4到5,内部循环,j=0,if 为0, x从5到6j=1,if 为1 j=2,if为0 ,x
18、从6到7j=3,if为1,x为8,continue的使用,练习2,共 36 页 第 29 页,5.7 选择结构程序设计举例,例1 打印出200到300之间的所有素数。,判断整数m为素数的方法:,共 36 页 第 30 页,#include “math.h“main( ) int m,i,k,n=0;for (m=201;m=k+1) printf(“%d,“,m);n+;if (n%10=0) printf(“n“); ,程序如下,共 36 页 第 31 页,一个古典数学问题: 有一对兔子,从出生后第3个月起每月都生一对兔子。小兔子长到第三个月后每月又生一对兔子。假设所有兔子都不死,问每个月的
19、兔子总数为多少只及四十个月后所有兔子的总数?,设以不满1个月的为小兔子,满1个月不满2个月的为中兔子,3个月以上的为老兔子,列出各个月的兔子情况:,例2 Fibonacci数列问题,共 36 页 第 32 页,求Fibonacci数列的前40个数?,数列特点:第1,2两个数为1,1。从第三个数开始,该数是其前面 两个数之和。即:,F1=1 (n=1) F2=1 (n=2) Fn=Fn-1+Fn-2 (n=3),共 36 页 第 33 页,解题方法:,设计求每月兔子总数的通用程序。设计一个计数器i表示当前月数,变量f1,f2分别表示前两月兔子总数并分别输出,当计数器i值变为20时,能得出前四十个
20、月所有兔子数(总数)。,程序与流程图,共 36 页 第 34 页,main( ) long f1,f2;int i;f1=1; f2=1;for(i=1;i=20;i+) f1=f1+f2;f2=f2+f1; printf(“%12ld,%12ld”,f1,f2); ,共 36 页 第 35 页,例3 求两个数的最大公约数。,辗转相除法 已知两个数M和N,假定MN,则求M%N,若余数r 为0,则N即为是所求,若余数r不为0,用N除 r,再求 其余数直到余数为0,则除数就是最大公约数。,求76 与 64的最大公约数,r=76%64 , r 的值为12 r不为0,r=64%12 , r 的值为4 r不为0,r=12%4 , r 的值为 0,76与64的最大公约数为4,共 36 页 第 36 页,程序如下,main( ) int x,y,t,r; scanf(“%d,%d”, ,输入64,76,交换x,y,条件是:余数不为0,除数做被除数,余数做除数,