Download presentation
Presentation is loading. Please wait.
1
第四章 循环程序设计 循环程序 多重循环 程序设计实例 作业 4.10 4.32 4.20 4.1 4.14 4.18 4.25 练习
练习
2
§4.1 计算平均成绩—循环程序 例4.1 某评估单位要对学生的学习情况进行评估,需要计算每个学生的平均学习成绩。编程序,从终端逐次输入一个学生n门课程的成绩,计算并输出他的平均成绩。
3
循环程序有: 先判断条件的循环 这就是循环程序 后判断条件的循环 同样问题还可以描述成先判断条件的循环 本程序是后判断条件的循环
#include <stdio.h> #define n 40 void main(void){ float sum ; int k , m; k=1; sum=0; do { printf("pleace input a achievement :"); scanf("%d",&m ); sum = sum + m; k = k+1 ; } while ( k <= n ) ; printf("average achievement : %5.2f\n" , sum/n ); } sum=0; k=1; 读入一科成绩 → m sum =sum+m; k = k+1 ; 开始 k <= n 结束 F T 输出 sum / n 这就是循环程序 运行结果演示 同样问题还可以描述成先判断条件的循环 本程序是后判断条件的循环
4
sum=0; k=1; 读入一科成绩 → m sum =sum+m; k = k+1 ; 开始 k <= n 结束 F T 输出 sum / n
5
C 有三种不同的重复性语句, 它们是 需要弄清楚的 while 语句── 先判断条件的循环; do 语句── 后判断条件的循环;
for 语句── 先判断条件的循环。 需要弄清楚的 循环控制方式是什么? 控制条件是什么? 重复执行部分(称为"循环体")是什么?
6
§4.1.1 后判断条件的循环 其中: ● e是条件; ● S是语句,是要重复执行的操作。
§ 后判断条件的循环 其含义是: 1) 执行语句列S 2) 计算条件表达式e, 3) 若e的值为true,转向步骤1)再次执行语句S; 否则转向步骤4)结束循环。 4)循环结束,向后执行其后继操作。 其中: ● e是条件; ● S是语句,是要重复执行的操作。 例4.1程序是后判断条件的循环程序,后判断条件的循环在流程图中表示成类似如下左图形式,PAD表示形式如下述右图。 S e T do-while e S
7
sum=0; k=1; 读入一科成绩 → m sum =sum+m; k = k+1 ; 开始 k <= n 结束 F T 输出 sum / n do-while k<=n sum=0; k=1; 读入一科成绩 → m sum =sum+m; k = k+1 ; 输出 sum / n 开始 结束
8
后判断条件的循环用do语句描述 一般形式 do S while ( e );
9
例4.2 计算数列的ak=1/(k*(k+1)) 的前 n 项和
#include "stdio.h" void main ( ){ int n,k ; float sum ; printf ("please input n :"); scanf("%d",&n); sum = 0 ; k = 1 ; do { sum + = 1.0/(k*(k+1)); k++ ; } while ( k<=n ); printf("average achievement: %f\n",sum); } sum = 0 ; k = 1 ; do-while k<= n 结束 开始 输出 sum sum +=1/(k*(k+1)); k = k+1 运行结果演示
10
例4.3 编程序,输入一个年份,求该年以后的 n 个闰年
输入:年(yy) , 闰年数(n) do-while n > 0 yy = yy+4 开始 结束 求 yy 后第一个闰年 yy 是闰年 输出yy n= n-1
11
/*PROGRAM find leap year*/ #include "stdio.h" void main(){ int yy,n;
printf("please input begin year:"); scanf("%d",&yy); printf("please input the number of the leap year:"); scanf("%d",&n); yy=(yy/4+1)*4; do{ if( (yy%4==0)&&(yy%100!=0)||(yy%400==0) ){ printf("year %d\t",yy); n--; } yy=yy+4; }while(n>0); 运行结果演示 例子举一九○○年开始的三个闰年
12
例4.4 编程序,解方程 2X3+0.5X2-X+0.093=0 变换方程为:X = 2X X 若某个 X 代入右端后,计算结果正好是 X ,则这个 X 值就是方程的根
13
简单迭代法 等价变换 g (x) = 0 x = f (x) 采用迭代法方法求解x=f(x)方程的根 选定一个 x的初值 x0 ;
否则若 x1≠x0 则令 x0=x1 ,转向2 结束,停止计算 先讲数学上的迭代法的意义。
14
y=x 可以使用简单迭代的情况 f (x2) f (x) f (x1) f (x0) x0 x1 x2 x*
15
f (x) 不可以使用简单迭代的情况 y=x f (x0) f (x1) f (x2) x2 x1 x0 x*
16
简单迭代方法使用条件 对于方程x=f(x),当任意x(a, b) 存在0< L< 1,使 |f‘(x)|≤L<1 则方程x = f(x)在(a, b)上有唯一的根x* 且对任意初值x0 (a, b)时 迭代序列xk+1=f (xk) (k = 0, 1, …)收敛于x* 在实际工作中,决大部分计算都是近似计算,只要求 X1≈X0 即│X1 - X0│<ε使用条件
17
开始 X0 = 初值 X1 = f(X0) X0≈X1 结束 X0 = X1 T F X1 = 初值 do-while | X1-X0|>ε X0 = X1 X1 = f(X0) 开始 结束
18
#include "stdio.h" #include "math.h" #define eps 1e-6 void main(){ float x0,x1; x0=0.0; x1=0.0; do{ x0=x1; x1=2*x0*x0*x0 +0.5*x0*x ; }while(fabs(x1-x0)>eps); printf("x=%f\n",x0); } 运行结果演示
19
§4.1.2 先判断条件的循环 开始 开始 sum=0; sum=0; k=1; k=1; 读入一科成绩 → m F sum =sum+m;
§ 先判断条件的循环 sum=0; k=1; 读入一科成绩 → m sum =sum+m; k = k+1 ; 开始 k <= n 结束 F T 输出 sum / n 开始 sum=0; k=1; F k <= n T 输出 sum / n 读入一科成绩 → m sum =sum+m; 结束 k = k+1 ;
20
其中: ● e是条件; ● S是语句,是要重复执行的操作。 先判断条件的循环程序模式 其含义是: 1) 计算条件表达式e,
F while e S 其含义是: 1) 计算条件表达式e, 2) 若e的值为true,转向步骤3)继续循环; 否则转向步骤5)结束循环。 3) 执行语句S 4)转向步骤1) 5)循环结束,向后执行其后继操作。 其中: ● e是条件; ● S是语句,是要重复执行的操作。
21
先判断条件的循环用WHILE语句描述 一般形式 while ( e ) S
22
运行结果演示 #include <stdio.h> #define n 40 void main(void){
float sum ; int k , m; k=1; sum=0; while ( k<=n ) { printf("pleace input a achievement :"); scanf("%d",&m ); sum = sum + m; k = k+1 ; } printf("average achievement : %5.2f\n" , sum/n ); while k<=n sum=0; k=1; 读入一科成绩 → m sum =sum+m; k = k+1 ; 输出 sum / n 开始 结束 运行结果演示
23
例6.6 编程序,按公式求自然对数底 e 的近似值 由于不能进行无穷项的计算,所以只能进行近似计算,当余项 余项计算可利用前后项之间的递推关系
24
e=1 ; n=1; r=1 ; while r > eps e=e+r ; 开始 结束 r=r*1/n ; n=n+1;
25
#include "stdio.h" #define eps 1e-5 void main( ) { int n ; float e,r ; e=1.0; n=1; r=1.0; while ( r>eps ) { e=e+r; n=n+1; r=r/n; } printf (" e=%f\n",e) ; 运行结果演示 e=1.0; n=1; r=1.0; e=2.0; n=2; r=0.5; e=2.5; n=3; r=0.1667; e=2.6667; n=4; r=0.0417; ……..
26
例4.7 编程序,统计以100为结束符的整数输入流中 -1 、0 、+1 的出现次数并输出
例4.7 编程序,统计以100为结束符的整数输入流中 -1 、0 、+1 的出现次数并输出 while num != 100 i=0; j=0; k=0; 输出 i,j,k 开始 结束 输入一个数 → num i++ j++ k++ num -1 1
27
运行结果演示 #include <stdio.h> #define n 100 void main(void){
int i , j , k , num ; i=0; j=0; k=0; printf("pleace input a integer :"); scanf("%d",&num ); while ( num != n ) { switch (num) { case -1 : i++; break; case 0 : j++; break; case 1 : k++; } printf("number of -1 : %d\n" , i ); printf("number of 0 : %d\n" , j ); printf("number of 1 : %d\n" , k ); 运行结果演示
28
++和-- v0 – 1 一元 --v v0 后缀 v-- v0 + 1 ++v v++ 运算后表达式值 运算后v的值 类别 表达式
29
§4.1.3 for 语句 e=1.0; e=1.0; n=1; n=1; for ( r=1.0; r>eps; r=r/n ){
while ( r>eps ) { e=e+r; n=n+1; r=r/n; } e=1.0; n=1; for ( r=1.0; r>eps; r=r/n ){ e=e+r; n=n+1; }
30
for语句最经常被用于描述循环次数已知循环
sum = 0 ; k = 1 ; while( k<=n ) { sum = sum + 1.0/(k*(k+1)) ; k++ ; } sum = 0 ; for ( k=1 ; k<=n; k++ ) sum = sum + 1.0/(k*(k+1)) ;
31
一般形式 for ( e1; e2 ; e3) S e1——初值表达式 用于设置该循环开始的一些初值 e2——终值表达式 用于控制循环结束
32
执行与PAD图 e1 e2 S e3 F 结束 for ( e1 ; e2 ;e3 ) S
33
例4.8 编程序求向量内积。由终端输入两个n维向量X,Y. 计算其内积XY 。
for( i=1;i<=n ;i++) scanf("%f%f", &xi, &yi ) 开始 结束 输出 xy xy = xy + xi*yi
34
printf("pleace input n:\n"); scanf("%d",&n); xy = 0;
#include "stdio.h" void main ( ){ int n,i ; float xy,xi,yi ; printf("pleace input n:\n"); scanf("%d",&n); xy = 0; for (i=1;i<=n;i++ ) { printf("pleace input xi 、yi :\n"); scanf("%f%f", &xi, &yi ) ; xy = xy + xi * yi ; } printf("xy=%f\n", xy); 运行结果演示
35
例4.9 编程序,画函数 y=f(x)=e-x sin(2πX)在[0,2]区间上的图形
X
36
Y X
37
* +1 -1 40列 y x 40行 区间〔0,2〕分为40行,则图像显示40行,每行相当于x值0.05
* y 区间〔0,2〕分为40行,则图像显示40行,每行相当于x值0.05 Y值在〔-1,+1〕间,则把Y的0点在屏幕中央40列,第20列代表-1,60列代表+1,每列代表y值0.05 40行 x
38
x = 0; for(i=1 ;i<=40; i++) 开始 结束 计算 y = f(i*0.05) 确定 y 坐标,在相应位置印 *
39
#define dx 0.05 #define dy 0.05 #define pi #define y0 40 #define endx 40 void main( ) { int n , i ,j ; float x , y ; x = 0 ; for ( i=0; i<=endx; i++ ) { y = exp(-x) * sin( 2 * pi * x ) ; n = y0+ (int)( y/dy ) ; for (j=0;j<=n;j++) printf(" "); printf("*\n"); x = x + dx ; } 运行结果演示
40
比较两种循环 S e F while e S S e T 循环体执行的次数,还有循环体内必须有改变e值的操作 do-while e S
41
§4.2 多重循环 例4.10 打印99表 打印前 9 行 打印底行 开始 结束 1 1 *
42
打印底行 * 打印底行 结束 for (i=1;i<=9;i++) 印 i 印 *
43
打印前9行 打印前9行 结束 打印第 i 行 for (i=1;i<=9;i++) 1 1 2 2 4 3 3 6 9
1 1
44
打印第i行 行号 本行数值 打印第i行 结束 打印行标 i for(j=1;j<=i;j++) 打印 i*j
45
打印第i行 行号 本行数值 打印第i行 结束 打印行标 i for(j=1;j<=i;j++) 打印 i*j
46
例4.10 打印99表 打印行标 i for(j=1;j<=i;j++) 打印 i*j for (i=1;i<=9;i++)
开始 打印行标 i for(j=1;j<=i;j++) 打印 i*j for (i=1;i<=9;i++) 打印前 9 行 打印第 i 行 for (i=1;i<=9;i++) 印 i 印 * 打印底行 结束
47
#include "stdio.h" void main(){ int i,j; for(i=1;i<10;i++){
printf("%4d",i); for(j=1;j<=i;j++) printf("%4d",i*j); printf("\n"); } printf("%4c",'*'); for(i=1;i<10;i++) 运行结果演示 各种循环程序的循环体都可能是个结构语句。如果一个循环结构的循环体仍然是一个循环,便构成循环嵌套,称多重循环。 该程序中含有循环套循环的结构
48
for (j=i/2;j>=2;j--)
打印100以内素数 for (i=2;i<=100;i++) 开始 结束 打印 i i为素数 i为素数? 返回 flag flag = false for (j=i/2;j>=2;j--) flag = true i%j == 0 拿例子讲解整个过程比如6以内的素数
49
开始 flag = true for (i=2; i<=100; i++) flag = false for (j=i/2; j>=2; j--) i%j == 0 打印 i 结束 flag
50
#include "stdio.h" void main( ) { int i ,j ; bool flag;
for ( i = 2 ;i <= 100 ; i++ ) { flag=true; for ( j = i / 2 ; j > 2 ; j-- ) if ( i % j == 0 ) flag=false ; if ( flag ) printf("%5d\n" , i ) ; } 运行结果演示
51
多重循环程序编写要点 内外循环控制条件不要互相冲突 for ( i = 2 ;i <= 100 ; i++ ) {
flag=true; for ( i = i / 2 ; i >= 2 ; i-- ) if ( i % j == 0 ) flag=false ; if ( flag ) printf("%5d\n" , i ) ; }
52
§4.3 程序设计实例 打印数列 求两数最大公因数 阶乘求和 "百钱百鸡"问题 打印字符方阵
53
例4.12 打印数列 编程序,输出如下序列的前 50 项。 该序列的第一项为 0 第二项为 1 以后的 奇数项为其前两项之和
例4.12 打印数列 编程序,输出如下序列的前 50 项。 该序列的第一项为 0 第二项为 1 以后的 奇数项为其前两项之和 偶数项为其前两项之差。
54
项数 1 2 3 4 5 6 7 8 9 1 1 u v w 1 1 u v w 1 1 u v w 1 1 u v w 1 1 2 u v w
55
k<=50 开始 u=0 v=1 k=3 k=k+1 w=v-u k为偶数 w=v+u 输出w u=v v=w 结束 输出u ,v
56
#include "stdio.h" void main( ) { int u,v,w,k ; u=0 ; v=1 ; printf ( "%5d\n%5d\n",u,v); k=3 ; do { if ( k%2 == 0 ) w=v-u; else w=v+u; printf ( "%12d\n",w); u=v ; v=w ; k=k+1 ; }while ( k<=50 ) ; } 运行结果演示
57
k<=50 开始 u=0 v=1 k=3 k=k+1 w=v+flag*u flag=-flag 输出w u=v v=w 结束 输出u ,v flag=1
58
#include "stdio.h" void main( ) { int u,v,w,k ; int flag; u=0 ; v=1 ; printf ( "%5d\n%5d\n",u,v); k=3 ; flag = 1 ; do { w = v + flag*u; flag = -flag ; printf ( "%5d\n",w); u=v ; v=w ; k=k+1 ; }while ( k<=50 ) ; } 运行结果演示
59
例4.13 求两数最大公因数 编程序,输入两个正整数u 、v ,用欧几里德辗转相除法求它们的最大公因数并输出 欧几里德辗转相除法
例4.13 求两数最大公因数 编程序,输入两个正整数u 、v ,用欧几里德辗转相除法求它们的最大公因数并输出 欧几里德辗转相除法 u % v → R1 v % R1 → R2 R1 % R2 → R3 R2 % R3 → R4 … … … … Rn-1 % Rn → Rn+1=0 Rn 为正整数u 、v的最大公因数
60
14 % 18 → 14 u v r 18 % 14 → 4 u v r 14 % 4 → 2 u v r 4 % 2 → u v r 2
61
开始 结束 r=v r!=0 r=u%v u=v v=r 输出u 输入u、v #include "stdio.h" void main( ) { int u,v,r ; printf("pleace input u 、v:"); scanf("%d%d",&u,&v); r=v ; while ( r!=0 ) { r = u%v ; u = v ; v = r ; } printf ( "gcd(u,v) = %5d\n"u ); 运行结果演示
62
例4.14 阶乘求和 编程序,输入正整数N 计算r1!+r2!+...+rn! 并输出, N=r1r2...rn 例如 N=1234
例4.14 阶乘求和 编程序,输入正整数N 计算r1!+r2!+...+rn! 并输出, N=r1r2...rn 例如 N=1234 求1!+2!+3!+4!
63
开始 r=N%10 N=N/10 输入N S=0 N!=0 S=S+r! 输出S 结束
64
r!=1*2*3*……*r r! P=1 P=P*u u=1 u<=r u=u+1 P
65
开始 r=N%10 N=N/10 输入N S=0 P=1 N!=0 u=1 P=P*u u<=r 输出S u=u+1 S=S+P 结束
66
#include "stdio.h" void main( ) { int N,S,P,u,r ; printf("pleace input N:"); scanf("%d",&N); S=0 ; while ( N!=0 ) { r = N%10 ; N = N/10 ; P=1; u=1; while ( u<=r ) { P=P*u ; u=u+1 ; } S=S+P; printf ( “r1!+r2!+...+rn! = %5d\n”,S ); 所有计算连乘积的程序都使用一个积单元,有类似本题目的程序模式。其中: P是积单元; 开始进入循环之前积单元P必须置“1”; 在循环体内,每循环一次向积单元乘入一项; 最后循环结束,积单元中的值即为所求之积。 运行结果演示 本章已经编写过多个求和的程序,所有计算和的程序都使用一个和单元,有类似本题目的模式。其中: S是和单元; 开始进入循环之前和单元S必须清“0”; 在循环体内,每循环一次给和单元加上一项; 最后循环结束,和单元中的值即为所求之和。
67
例4.15 "百钱百鸡"问题 鸡翁一, 值钱五; 鸡母一,值钱三; 鸡雏三, 值钱一。百钱买百鸡; 问鸡翁、母、雏各几何。
例4.15 "百钱百鸡"问题 鸡翁一, 值钱五; 鸡母一,值钱三; 鸡雏三, 值钱一。百钱买百鸡; 问鸡翁、母、雏各几何。 设:设买x只公鸡,买y只母鸡,买z只鸡雏 5x + 3y + z/3 = /* 百钱 */ x + y + z = /* 百鸡 */
68
开始 结束 for ( x=1; x<=20; x++) 输出x,y,z x ,y ,z 满足方程 for ( y=1; y<=33; y++) for ( z=3; z<=99; z=z+3)
69
运行结果演示 #include "stdio.h" int x , y , z ; void main( ) { for ( x = 1 ; x <= 20 ; x++ ) for ( y = 1 ; y <= 33 ; y++ ) for ( z = 3 ; z <= 99 ; z=z+3 ) if ( x+y+z == 100 && 5*x+3*y+z/3 == 100 ) printf("result = %5d %5d %5d\n" , x , y ,z ) ; }
70
#include "stdio.h" int x , y , z ; void main( ) { for ( x = 1 ; x <= 20 ; x++ ) for ( y = 1 ; y <= 33 ; y++ ){ z = 100-x-y ; // 求鸡雏数z,百鸡 if ( 5*x+3*y+z/3 == 100 && z%3==0 ) // 百钱 printf("result = %5d %5d %5d\n" , x , y ,z ) ; } 运行结果演示
71
例4.16 打印字符方阵 x 打印一行 打印一行 打印前 6 行 for(x=‘A’;x<=‘F’;x++) 打印后5行
例4.16 打印字符方阵 x A B C D E F G H I A B C D E F G H I A B C D E F G H I A B B B C D E F G H I A B C D E F G H I A B C C C C C D E F G H I A B C D E F G H I A B C D D D D D D D E F G H I A B C D E F G H I A B C D E E E E E E E E E F G H I A B C D E F G H I A B C D E F F F F F F F F F F F G H I A B C D E F E F G H I A B C D E E E E E E E E E F G H I A B C D E D E F G H I A B C D D D D D D D E F G H I A B C D C D E F G H I A B C C C C C D E F G H I A B C B C D E F G H I A B B B C D E F G H I A B A B C D E F G H I A B C D E F G H I A for(x=‘A’;x<=‘F’;x++) 打印一行 打印前 6 行 打印一行 for(x=‘E’;x>=‘A’;x--) 打印后5行
72
结束 开始 打印前段 打印中段 打印后段 打印回车 A B C D E F G H I A B C D E F G H I A
B C D E F G H I A B B B C D E F G H I A B C D E F G H I A B C C C C C D E F G H I A B C D E F G H I A B C D D D D D D D E F G H I A B C D E F G H I A B C D E E E E E E E E E F G H I A B C D E F G H I A B C D E F F F F F F F F F F F G H I A B C D E F E F G H I A B C D E E E E E E E E E F G H I A B C D E D E F G H I A B C D D D D D D D E F G H I A B C D C D E F G H I A B C C C C C D E F G H I A B C B C D E F G H I A B B B C D E F G H I A B A B C D E F G H I A B C D E F G H I A 打印前段 打印中段 开始 结束 打印后段 打印回车
73
y x C D E F G H I A B D E F G H I A B C E F G H I A B C D for(y=x;y<=‘I’;y++) 打印 ’ □y’ for(y=‘A’;y<x;y++)
74
x A B B B C C C C C D D D D D D D 开始 打印:(5-(x-‘A’))*2个空格
结束 打印:(5-(x-‘A’))*2个空格 打印:2*(x-‘A’)+1个□x
75
y x C D E F G H I A B D E F G H I A B C E F G H I A B C D for(y=x+1;y<=‘I’;y++) 打印 ’ □y’ for(y=‘A’;y<=x;y++)
76
for ( y=x; y<=’I’;y++) 打印:□y for ( y=’A’; y<=x-1;y++) 开始 for ( x=’A’; x<=’F’; x++) 打印:(5-(x-‘A’))*2个空格 打印:2*(x-‘A’)+1个□x for(y=x+1;y<=‘I’;y++) 打印 ’ □y’ for(y=‘A’;y<=x;y++) 打印回车
77
for ( y=x; y<=’I’;y++) 打印:□y for ( y=’A’; y<=x-1;y++) for ( x=’E’; x>=’A’; x--) 打印:(5-(x-‘A’))*2个空格 打印:2*(x-‘A’)+1个□x for(y=x+1;y<=‘I’;y++) 打印 ’ □y’ for(y=‘A’;y<=x;y++) 结束 打印回车
78
#include "stdio.h" char x , y ; int i ; void main( ) { for ( x=’A’;x<=’F’;x++){ // 前六行 for ( y=x; y<=’I’;y++) printf ( " □ %c", y); for ( y=’A’; y<x; y++) printf ( " □ %c", y); for( i=1;i<=(5-(x-‘A’))*2); i++) printf ( " □ "); for( i=1;i<=2*(x-‘A’)+1;i++) printf ( " □ %c", x); for( i=1;i<=(5-(x-‘A’))*2); i++) printf ( " □ "); for ( y=x+1; y<=’I’;y++) printf ( " □ %c", y); for ( y=’A’; y<=x;y++) printf ( " □ %c", y); printf ( "\n"); }
79
for ( x=’E’;x>=’A’;x--){ // 后五行
for ( y=x; y<=’I’;y++) printf ( "□%c", y); for ( y=’A’; y<=x-1;y++)printf ( "□%c", y); for( i=1;i<=(5-(x-‘A’))*2); i++) printf ( "□"); for( i=1;i<=2*(x-‘A’)+1;i++) printf ( "□%c", x); for ( y=x+1; y<=’I’;y++) printf ( "□%c", y); for ( y=’A’; y<=x;y++) printf ( "□%c", y); printf ( "\n"); } 运行结果演示
80
本章小结 后判断条件循环 do while 语句 先判断条件循环 while语句 for语句 重点 使用编写循环结构程序解决实际问题
Similar presentations