500 likes | 751 Views
第六章 循环控制. §6.1 概述. 前面已介绍了顺序结构 , 选择结构,本章介绍循环结构 。. 实际问题 : 一组重复执行的语句。. sum=1+2+3+…+100;. 如 :. 则用循环结构解决。. C 语言用四种形式循环. 1. if 语句与 goto 语句. 2. while 语句. 3. do …while 语句. 4. for 语句. §6.2 goto 语句及与 if 语句构成循环. 1. goto 语句. 形式 : goto 标号;. 功能 : 无条件转向标号处。. 标号 :用标识符命名。. 2. 与 if 构成循环.
E N D
第六章 循环控制 §6.1 概述 前面已介绍了顺序结构,选择结构,本章介绍循环结构。 实际问题:一组重复执行的语句。 sum=1+2+3+…+100; 如:
则用循环结构解决。 C语言用四种形式循环 1.if语句与goto语句 2.while 语句 3.do …while 语句 4.for语句
§6.2 goto语句及与if语句构成循环 1. goto语句 形式: goto 标号; 功能: 无条件转向标号处。 标号:用标识符命名。 2. 与if构成循环. 例6.1: 求
main ( ) { int i, sum=0; i=1; loop:if (i<=100) { sum=sum+i; i++; goto loop;} printf("%d", sum); } 运行结果如下: 5050
§6.3 while语句 为了使程序的结构化功能强,应尽量少用goto语句。 专门的当型循环语句––while语句 1. 形式: while (表达式)语句 2. 执行过程: 先判断表达式的值。若0.则执行其后面的语句,否则while执行完毕。
表达式 =0 0 语句 下一语句 3.流程图: 将上述例子用while语句写出 例6.2 while (i<=100) { sum+ =i;//sum=sum+i i++; }
注: while后面的语句一般为复合语句, 即:加{ } 语句中应有使表达式=0的语句。 否则会出现无限循环–––"死"循环。
语句 0 表达式 =0 §6.4 do …while语句 一种专门的“ 直到型” 循环语句。 1. 形式: do语句while(表达式);注,其后有分号 2. 执行过程: 先执行语句,再判表达式的值,若0,再执行语句,否则结束循环 3. 流程:
main ( ) { int i, sum=0; i=1; do { sum=sum+i; i++; } while (i<=100); printf("%d",sum); } 例6.3 while语句与do…while语句的区别: 当第一次执行时, 若表达式=0时,则while语句与do …while有所不同, do …while 执行一次后面的语句,而while不执行。 因此,do …while语句又叫做非0次循环语句。例P109 6.4
§6.5 for语句 一种形式更为灵活的循环语句。 1. 形式 for(表达式1; 表达式2; 表达式3)语句 2.执行过程 首先计算表达式1,接着执行表达式2,若表达式2的值0,则执行语句,接着计算表达式3,再判断表达式2的值.依此重复下去,直到表达式2的值=0(假)。
计算表达式1 =0(假) 求表达式2值 0(真) 语句 计算表达式3 结束for语句 3.流程:
用for语句写出上述例子 for ( i=1; i<=100; i++) sum+=i; for语句完全可以用while代替,但for直观、简单、方便 for用while代替的流程 表达式1; while(表达式2) { 语句 表达式3; }
4. for语句的几种特例 可以省略表达式1, 但须保留分号;这时在for之前就得赋值给循环变量; 例: 任意输入两个整数a, b,求 main ( ) { int i, j, a, b, sum; printf ("please input two number!\n"); scanf ("a=%d, b=%d", &a, &b); i=a; j=b; if (a>b) {i=b; j=a;} for (; i<=j; i++) sum=sum+i; printf (" \n sum=%d", sum); }
表达式2一般不可省略,否则为无限循环 例: for (i=1; ; i++) sum=sum+i; 相当于条件永真、永不为0,若用while表示 相当于:while (1) { sum=sum+i; i++; }
表达式3亦可省略,但在循环体中须有语句修改循环变量;以使表达式2在某一时刻为0而正常结束循环。表达式3亦可省略,但在循环体中须有语句修改循环变量;以使表达式2在某一时刻为0而正常结束循环。 例: for (sum=0,i=1;i<=100;) { sum=sum+i; i++; }
若同时省略表达式1,表达式3,则相当于while(表达式2)语句。若同时省略表达式1,表达式3,则相当于while(表达式2)语句。 例: for (; i<=100;) {sum+=i; i++;} 相当于while (i<=100) { sum+=i; i++; }
三个表达式均省略 即for(;;)语句则相当于while(1)语句. 表达式1、表达式3可以是逗号表达式,以使循环变量值在修改时可以对其它变量赋值。 如for (sum=0,i=1;i<=100;i++,i++) 相当于:sum=0; for (i=1;i<=100;i=i+2)
表达式2可以是关系表达式,也可以是数值表达式或字符表达式。只要值0.即执行循环体.表达式2可以是关系表达式,也可以是数值表达式或字符表达式。只要值0.即执行循环体. 例:for (i=0; (c=getchar( ))!='\n'; i+=c);
§6.6循环的嵌套 与其它语言一样,当循环体中又包含了另一个完整的循环语句时–––嵌套。 C有三种循环语句,均可以相互嵌套: while ( ) {… while ( ) {… } } for (; ;) { … while ( ) { } do { } while ( ); … } 均为正确的嵌套。
while ( ) { … while ( ) { }… } for (; ; ) { for (; ; ) {… } } 会理解为正确的形式;但要注意语句的包含关系。
§6.7几种循环的比较 • 对于同一问题, 四种循环可相互替代。但不提倡用goto. • for循环功能强于while, do…while.但若不是明显地给出循环变量初终值(或修改条件),则应用while 或do …while.以增强程序的结构化和可读性。 • 要防止无限循环——死循环。 • 循环过程中,为了结束本次循环或跳出整个循环。分别要用到continue和break语句。
§6.8break语句和contiune语句 6.8.1 break语句 问题: 计算圆的面积r2, 半径取1, 2, 3, 4…,当面积>100时结束。 #define PI 3.14159 main() {… for(r=1; r<=10; r++) {area=PIrr; if (area>100) break;} printf ("%f", area); }
从结构化程序要求出发,用break,退出循环,进入for语句的下一条语句。从结构化程序要求出发,用break,退出循环,进入for语句的下一条语句。 注: break只能用于循环语句和switch语句。
6.8.2 continuce语句 问题: 编写程序,打印100~200中不能被3整除的数。 main( ) { int n; for (n=100; n<=200; n++) if (n%3!=0) printf("%d", n); }
换一种方式: main( ) { int n; for (n=100; n<=200; n++) {if (n%3==0) continue; printf ("%d", n); } } continue语句起了结束本次循环的作用。
t=1,pi=0,n=1,s=1 当|t|>=10-6 pi=pi+t n=n+2 s=-s t=s/n pi=pi*4 输出pi §6.9程序举例 例6.6:用/4=1-1/3+1/5-1/7+…公式求的近似值,直到最后一项的绝对值小于10-6为止。 变量说明: s作分子,控制符号变化 n作分母,奇数序列 t=s/n,第i项值 pi先存放/4,再存放值
程序如下: #include <math.h> main() { int s;//做分子,取符号 float n,t,pi;//n做分母,t=s/n t=1;pi=0;n=1.0;s=1; while((fabs(t))>1e-6) { pi=pi+t; n=n+2; s=-s; t=s/n; } pi=pi*4; printf("pi=%10.6f\n",pi); }
例6.7:求Fibonacci数例: 1, 1, 2, 3, 5, 8, …前40个数。 规律:F1=1, F2=1 Fn=Fn – 1 + Fn – 2 (n>2) 程序要点: f1=f1+f2; f2=f2+f1; 交替的结果正好为一序列 每输出4个数时换行。
f1=1, f2=1 for i=1 to 20 输出f1, f2 f1=f1+f2 f2=f2+f1 程序如下: main ( ) { long int f1, f2; int i; f1=1; f2=1; for (i=1; i<=20; i++) { printf(%12ld %12ld ", f1, f2); if (i%2= =0) printf("\n "); f1=f1+f2; f2=f2+f1; } }
运行结果为: 1 5 34 233 1597 10946 75025 514229 3524578 24157817 1 8 55 377 2584 17711 1211393 832040 5702887 39088169 2 13 89 610 4181 28657 196418 1346269 9227465 63245986 3 21 144 987 6765 46368 317811 2178309 14930352 102334155
例6.9.求100~200的素数. 判一个数m是否为素数的方法: 的整数去除它时均不能除尽, 当用2, 3, … 则为素数。 每打印10个数,换一次行。
程序如下: #include <math.h> main() { int m, k, i, n=0; for (m=101; m<=200; m=m+2)//只判断奇数 { if ( n%10==0) printf("\n"); k=sqrt(m); for (i=2; i<=k;i++) if (m%i==0) break; if (i>=k+1) {printf("%d ",m); n=n+1;} } }
运行结果如下: 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199
例6.10:译密码。 规律:将输入的字母变成其后的第4个字母。 如,输入China! 译为Glmre! 程序要点:字符的ASCII码值+4; 若为WXYZ或wxyz之一,需转换为ABCD或abcd之一 if((c>=‘a’&&c<=‘z’)||(c>=‘A’&&c<=‘Z’)) {c=c+4; if(c>’Z’&&c<=’Z’+4||c>’z’) c=c-26; }
程序如下: #include<stdio.h> main ( ) { char c; while((c=getchar())!=‘\n’) {if((c>=‘a’&&c<=‘z’)||(c>=‘A’&&c<=‘Z’)) {c=c+4; if(c>’Z’&&c<=’Z’+4||c>’z’) c=c-26; } printf(“%c”,c); } }
循环控制应用 一、统计与计数问题 方法:计数变量c的初值为0,每输入一个数据,进行必要判断后,若输入的数据满足统计条件,则计数变量c自加1,这样当对所有输入进行判断后,计数变量c的值就是统计的结果。
例:输入若干非0实数,直到输入0时停止,要求输入的实数最多不超过20个,统计其中正数的个数,负数的个数。例:输入若干非0实数,直到输入0时停止,要求输入的实数最多不超过20个,统计其中正数的个数,负数的个数。 分析: 设三个计数变量: n-统计输入的数据总个数(为什么有必要?)posn-统计正数的数目negn-统计负数的数目
#include<stdio.h> #include<math.h> void main() { int n,posn,negn;double a; n=0; posn=0; printf("Input real numbers:\n"); scanf("%lf",&a); while(fabs(a)>=1e-6&&n<20) { if(a>1e-6) posn++; n++; scanf("%lf",&a); } negn=n-posn; printf("posn=%d,negn=%d\n",posn,negn); }
二、数列求和/求积:累加/累乘/递推法 1.基本累加/累乘问题 累加法:求和变量初值一般为0,每循环一次,求和变量自加一个数据,这样循环结束后,求和变量的值即为这些数据的和。 累乘法:累乘变量初值一般为1,每循环一次,累乘变量自乘一个数据,这样当循环结束的时候,累乘变量的值即为这些数据连乘的积。
例:输入n个100分制成绩(用整型),计算并输出平均成绩,要求输出精确到两位小数。例:输入n个100分制成绩(用整型),计算并输出平均成绩,要求输出精确到两位小数。 #include <stdio.h>#define n 10void main() { double av=0; int score,i; printf(“Input %d int numbers:”,n); for(i=1;i<=n;i++) { scanf(“%d”,&score);av+=score; } av/=n; printf(“av=%.2f\n”,av);}
#include “stdio.h”void main(){ double p=1.0;int m,n,k; printf(“Input n,m:”); scanf(“%d%d”,&n,&m); if(n<0||m<0||m>n) { printf(“Input data aren’t correct.\n”); return; } if(n-m<m) m=n-m; /*这句有何作用?*/ for(k=1;k<=m;k++) p*=(double)(n-m+k)/k; /*此处为什么要强制类型转换?*/ printf(“c(%d,%d)=%.lf\n”, n,m,p);}
三、字符图形 例:*号图形 (打印行数n由键盘输入)
分析(2)号图形:从第1行打印到第n行,打印第i行时(i从1~n),首先打印n-i 个空格;接着打印 i个*号;换行; 分析:(6)号图形:打印第i行(i 从1~n)时,首先打印i-1个空格;接着打印2(n-i)+1个*号;换行;
#include “stdio.h”void main() { int n,i,j; printf(“Input n=“); scanf(“%d”,&n); for(i=1;i<=n;i++) { for(j=1;j<=n-i;j++) putchar(‘‘); for(j=1;j<=i;j++) putchar(‘*’); printf(“\n”); } } /*打印(2)号图形*/
例:“鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一,百钱买百鸡,问翁母雏各几何?”(引自张邱建算经,公元五世纪)例:“鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一,百钱买百鸡,问翁母雏各几何?”(引自张邱建算经,公元五世纪) 分析:设x,y,z分别表示鸡翁,鸡母,鸡雏的数目,则有 四、搜索(穷举求解) 上述方程属于不定方程,解并不唯一,因此,只能用搜索法对x,y,z的所有组合情况,测试满足条件的解。
#include “stdio.h”void main(){ int x,y,z; printf(“ Cock Hen chicken\n”); for(x=0;x<=20;x++) for(y=0;y<=33;y++) { z=3*(100-5*x-3*y); if(z>=0&&x+y+z==100) printf(“%8d%8d%8d\n”,x,y,z); }}
例.输入两个自然数a,b,求它们的最大公约数与最小公倍数。例.输入两个自然数a,b,求它们的最大公约数与最小公倍数。 分析:设a,b的最大公约数为gcd(a,b),可用下式计算gcd(a,b),而最小公倍数=a*b/gcd(a,b)。 五、数论有关问题 例如:gcd(24,32) =gcd(32,24) =gcd(24,8) =gcd(8,0)=8
#include “stdio.h”void main() /*两数求最大公约数与最小公倍数*/{ int a,b,t,m; printf(“Input a,b:”); scanf(“%d%d”,&a,&b); if(a<1||b<1) {printf(“Input isn’t correct.\n”); return; } m=a*b; while(b!=0) { t=a%b;a=b;b=t; } printf(“zdgys=%d,zxgbs=%d\n”,a,m/a);}
课外学习 • 看书(reading) p106——121 • 思考题(exercise) 6.3、6.5 • 作业题(problem) 6.7、6.11 • 上机题一(project) 6.2、6.4、6.8 • 上机题二(project) 6.1、6.6、6.14