C程序设计 第5章 循环结构 主讲教师: 鲁 萍 西安建筑科技大学 理学院
第5章 循环结构程序设计 为什么要用循环结构 ? 实现循环结构的语句 改变循环执行的状态 循环结构综合举例 while do…while for 改变循环执行的状态 break 语句 continue语句 循环结构综合举例 小 结 习 题 游 戏
应 用 循 环 1. 例: 求1+2+3+4+…+100 的累加和 重复:相加 2. 一个球从100米高度自由落下,每次落地后反跳回原高度的3/4,再落下,再反弹。求它在第10次落地时,共经过多少米? 重复:计算每次反弹的高度,并累加路径 … 100 1 2 3 4 … 10 循 环 重复做一件事情
循 环 结 构 A0501 例1: 求1+2+3+4+…+100的累加和 void main() { int sum=0, i=1; sum=sum+i; i=i+1; printf(“sum=%d\n”,sum); } sum=0 sum = sum + 1 sum = sum + 2 sum = sum + 3 sum = sum + 4 sum = sum + 5 …… sum = sum + 100 循环结构的关键 while( i<=100 ) 循环条件 { } 循环体 (修改循环变量)
循环语句:while 1. while (表达式) 循环体语句 当 表达式为真时重复执行语句;为假时循环结束。 void main() { int sum=0, i=1; while( i<=100 ) { sum = sum + i ; i = i + 1; } printf(“sum=%d\n”,sum); 表达式 假 真 假 真 循环体语句
循环语句:do while 2. do 重复执行循环体语句, 循环体语句 直到表达式为假。 while (表达式); 例1B: 求1+2+3+…+100的累加和 void main() { int i=1,sum=0; do{ sum = sum + i; i = i+1; 直到(i<=100)不成立 printf(“sum=%d\n”,sum); } sum=0 sum = sum + 1 sum = sum + 2 sum = sum + 3 sum = sum + 4 sum = sum + 5 …… sum = sum + 100 循环体语句 循环体 (修改循环变量) 假 表达式 循环条件 真 }while(i<=100); 真 假
循环语句:while 和 do while sum=0, i=1; sum=0, i=1; while( i<=100 ) { sum = sum + i ; i = i + 1; } do{ sum = sum + i; i = i+1; }while(i<=100); 执行 1 次, sum=200 执行100次,sum=5050 执行100次,sum=5050 执行 0 次, sum=0 真 表达式 假 循环体语句 真 表达式 假 循环体语句 “当”型循环 “直到”型循环 2. 说明: 1)表达式:循环判断条件 2)循环次数取决于表达式 3)循环体包含多条语句时用{ }括起 4)先判断表达式,后执行循环体 执行 1 次或多次 执行 0 次或多次
循环语句:while 和 do while sum=0, i=1; sum=0, i=1; while( i<=100 ) { sum = sum + i ; i = i + 1; } do{ sum = sum + i; i = i+1; }while(i<=100); 真 表达式 假 循环体语句 真 表达式 假 循环体语句 “当”型循环 “直到”型循环 2. 说明: 1)表达式:循环判断条件 2)循环次数取决于表达式 3)循环体包含多条语句时用{ }括起 4)先判断表达式,后执行循环体 执行 1 次或多次 执行 0 次或多次
循环语句: for语句 3. for (表达式1; 表达式2; 表达式3 ) 循环体语句 变量初始化 循环条件 循环变量修改 循环体 假 for (i=1; i<=100; i=i+1) { sum=sum+i; } …… 表达式1: 赋初值 假 真 条件表达式2 真 循环体语句 表达式3:循环变量递增
for和while比较 例6-1C:求1~100的累加 求100-200之间偶数的累加和 sum=0; for(i= 1 ;i<=100 ; i++ ) sum=sum+i; sum=0; i=1; while (i<=100) { sum=sum+i; i++; } 假 表达式1 100 200 i+=2 真 表达式2 循环体 表达式3 for语句能够取代while语句,且可读性好 尤其适用于:循环次数确定的循环
课堂练习 分别用for和while语句完成 1. 求100-200之间偶数的累加和 2. 求 10! 100! i=100; sum=0; { sum=sum+i; i+=2; } for(i=100,sum=0; i<=200; i+=2) sum=sum+i; 100! i=1; n=1; while (i<=10) { n*=i; i++; } double n; int n; for(i=1,n=1; i<=10; i++) n=n*i;
循环结构举例 A0502 一个球从100米高度落下,每次落地后反跳回原高度的3/4,再落下,再反弹。求它在第10次落地时,共经过多少米? 循环结构的关键 循环体:重复做的事情 循环条件:做多少次 … 100 米 对每一个落点: 计算高度并 累加路径长度 1. h=100 sum = sum + h 2. h=h*3/4 sum = sum + 2*h 3. h=h*3/4 sum = sum + 2*h 4. h=h*3/4 sum = sum + 2*h …… 10. h=h*3/4 sum = sum + 2*h 1 2 3 4 …. 10
循环结构举例 A0502一个球从100米高度落下,每次落地后反跳回原高度的3/4,再落下,再反弹。求它在第10次落地时,共经过多少米? sum=0 1. h=100 sum = sum + h 2. h=h*3/4 sum = sum + 2*h 3. h=h*3/4 sum = sum + 2*h 4. h=h*3/4 sum = sum + 2*h …… 10. h=h*3/4 sum = sum + 2*h sum=0; h=100; sum=sum+h for(i=2;i<=10;i++) { h=h*3/4; sum=sum+2*h; }
循环结构举例 A0502一个球从100米高度落下,每次落地后反跳回原高度的3/4,再落下,再反弹。求它在第10次落地时,共经过多少米? for(i=2;i<=10;i++) { h=h*3/4; sum=sum+2*h; } i=2; while(i<=10) { h=h*3/4; sum=sum+2*h; i++; } i=2; do { h=h*3/4; sum=sum+2*h; i++; } while(i<=10)
循环结构例题 A0503 例:输入一行字符,统计输入字符的个数 (以回车键 '\n'作为输入结束标记) 输入:hello↙ num:5 循环结构的关键 循环体:重复做的事情 循环条件:做多少次 6 循环体 输入字符 ch,num=num+1 …… 直到 输入回车键('\n') num=0; do { ch=getchar(); num=num+1; } while(ch!='\n') num=num-1; 循环次数不确定! 循环条件:ch!='\n'
循环结构例题 num=0 A0503例:输入一行字符,统计输入字符的个数 (以回车键作为输入结束标记) ch!='\n' 再次输入字符ch num=0 num=num+1 结束 开始 输入字符ch 输出num 真 假 循环结构例题 A0503例:输入一行字符,统计输入字符的个数 (以回车键作为输入结束标记) #include <stdio.h> void main() { char ch; int num=0; ch=getchar(); while(ch!='\n') { num++; } printf("num=%d\n",num); do { ch= getchar(); num++; }while(ch!='\n'); while((ch=getchar())!='\n') num++;
循环结构例题 num=0 B0501例:输入一行字符,分别统计其中英文字母,空格,数字和其他字符的个数 (以回车键作为输入结束标记) ch!='\n' 再次输入字符ch num=0 num=num+1 结束 开始 输入字符ch 输出num 真 假 循环结构例题 B0501例:输入一行字符,分别统计其中英文字母,空格,数字和其他字符的个数 (以回车键作为输入结束标记) 分析:字符变量c:接收键盘输入字符 整形变量:zimu_num,kong_num,shuzi_num,other_num 如果ch是英文字母:zimu_num++ 如果ch是空格:kongge_num++ 如果ch是数字:shuzi_num++ 如果ch是其他字符:other_num++ 循环标记:c!=‘\n’ 布置为作业题
循环结构例题 B0503例:输入一行字符,分别统计其中英文字母,空格,数字和其他字符的个数 (以回车键作为输入结束标记) #include <stdio.h> void main() { char ch; int num=0; ch=getchar(); while(ch!='\n') { num++; } printf("num=%d\n",num); int zimu_num=0, kong_num=0; int shuzi_num=0, other_num=0; if((ch>=‘a’ && ch<=‘z’)|| (ch>= ’A’ && ch<=‘Z’) ) zimu_num++; else if( ch==‘ ‘) kong_num++; else if( ch>=‘0’ && ch<=‘9’) shuzi_num++; else other_num++; while { if ( ) { ... } ... }
循环应用分析 for / while { if ( ) { ... } ... } 1.录入50个学生的成绩,计算平均成绩,并显示。 2.录入50个学生的成绩,统计100~90,89~80,79~70,69~60,59~0各分数段学生的人数,并显示统计结果 循环统计(for) ,嵌套 switch 或 if..else if..else 3.对某单位100个人进行年龄统计,35岁以下是“青年”,35~55是中年,55以上是“老年”,并显示统计结果 循环for,嵌套if…else for / while { if ( ) { ... } ... }
任 务 A0504 在全系1000学生中进行募捐,当总数达到10万元时结束。统计此时捐款的人数 ,以及 平均每人 捐款的数目。
break语句 至此位置 假 1.格式: break; 条件 2.功能:强行结束整个循环,转向执行循环语句的下一条语句。 用于循环语句和switch语句中 条件 真 语句A 3. 执行过程 while(条件) { 语句A; break; 语句 B; } break 语句B if (表达式) break; 至此位置 结束循环
continue语句 1.格式: continue ; 2.功能:结束该循环中的本次循环,继续下一轮循环。 只能用于循环语句中 假 条件 真 语句A 3. 执行 for(表达式1;表达式2;表达式3) { 语句A; continue; 语句 B; } 3. 执行 while(条件) { 语句A; continue; 语句 B; } 至此位置 continue if (表达式) continue; 语句B 结束循环
break & continue 应用 #include <stdio.h> void main() { int x,k; 小 结 break & continue 应用 A0505例: 求300以内能被17整除的最大的数。 #include <stdio.h> void main() { int x,k; for(x=300;x>=1;x--) if(x%17==0) printf("x=%d\n",x); } 找到满足条件的最大数,结束循环 break;
循环程序综合举例 A0506 例:近似求PI。 PI/4=1-1/3+1/5-1/7+….,直到某一项绝对值小于10-6为止。 void main() { int s; double n,t,pi; // s:分子,n:分母,t:分式,pi:累加和 t=1; pi=0; n=1.0; s=1; while(fabs(t)>1e-8) { pi=pi+t; n=n+2; s=-s; t=s/n; } pi=pi*4; printf("PI=%15.10f\n",pi);
斐波那契数列 问题:已知一对幼兔一个月长成成年兔子,一对成年兔子在一月内生出一对幼兔。如果有一对幼兔,问一年后共有多少对兔子? 如果设F(n)为该数列的第n项 F(0) = 0, F(1)=F(2)=1, F(n)=F(n-1)+F(n-2) (n≥3) 显然这是一个线性递推数列 1、1、2、3、5、8、13、21、34、55、
循环程序设计举例 A0507 例: Fibonacci数列。 void main() { long int f1,f2; int i; for(i=0;i<=20;i++) { printf("%12ld %12ld ",f1,f2); if(i%2==0) printf("\n"); f1=f1+f2; f2=f2+f1; } 如果设F(n)为该数列的第n项 F(0) = 0, F(1)=F(2)=1, F(n)=F(n-1)+F(n-2) (n≥3)
循环结构例题 A0508例:键盘输入一个正整数, 判断是否为素数。 数x在[2,sqrt(x)]范围内没有因子 n=2 循环结构例题 A0508例:键盘输入一个正整数, 判断是否为素数。 数x在[2,sqrt(x)]范围内没有因子 n<= sqrt(x) n=n+1 假 假 真 x%n==0 真 分析: 对每一个n∈ [2,sqrt(x)] 如果x%n==0 则 不是素数 循环结构,循环结束条件: (1) n> sqrt(x) 没有n满足x%n==0 ,是素数 (2)找到n,满足x%n==0 ,则x不是素数,退出循环( break) 此时 n<=sqrt(x) C1:例6.8 c3: 例4.16部分 x是素数 n> sqrt(x) 真 假
循环结构例题 A0508例:键盘输入一个正整数,判断是否为素数 #include <math.h> void main() 键盘输入x n=2 n<= sqrt(x) 假 真 x%n==0 n=n+1 x是素数 n> sqrt(x) 循环结构例题 A0508例:键盘输入一个正整数,判断是否为素数 #include <math.h> void main() { int x,n; scanf("%d",&x); for(n=2;n<=sqrt(x);n++) if(x%n==0) break; if(n>sqrt(x)) printf(" %d is a prime " ,x); else printf(" %d is not a prime " ,x); } 在判断范围内无因子,程序正常终止 有因子不再判断 C1:例6.8 c3: 例4.16部分 有因子,程序 非正常终止
循环嵌套 A0509例:输出100以内的素数 分析: for( x=2~100) { for( n=2~ sqrt(x)) #include < math.h> void main() { int n,x; for(x=2;x<=100;x++) { for(n=2;n<=sqrt(x);n++) if(x%n==0) break; if(n>sqrt(x)) printf(“% d " ,x); } 分析: for( x=2~100) { for( n=2~ sqrt(x)) if x%n==0? 判素数 } 外循环 内循环 上机演示 Lisushu1 d 和 Lisushu2 4d c1: 例6.9 C3:例4.16 4d break和continue只影响其所在的循环,与外层循环无关
for( ...) { ... while(...) { ... } ... 内循环 外循环 嵌套循环 外循环初始条件 假 外循环条件 真 { ... while(...) { ... } ... 内循环 外循环 嵌套循环 真 内循环初始条件 假 内循环条件 真 内循环体 外循环体 循环结束
循环程序设计举例 A0510例:译密码。按照如下方式将英文字符加密 6566 87 88 89 90 A B C D E F G H I …W X Y Z a b c d e… x y z E F G H I J K L M… A B C D e f g h i… a b c 91 分析: (1)对每个英文字符c用其后第4个字符替代 c=c+4 注意:右边界 WXYZ +4 不在是英文字符,特殊处理c=c-26 (2)非英文字符不变 C1:例6.10
循环程序设计举例 A0510例:译密码。按照如下方式将英文字符加密 #include<stdio.h> void 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; /* 是否出界*/ } putchar(c); /* 输出加密后字符*/ printf("\n");
循环小结 重复做一件事情 循环结构 循环体:重复做的事情 循环条件:做多少次 1.“当”型循环 while (表达式) 循环体语句 2. “直到”型 循环 do 循环体语句 while (表达式); 变量初始化 循环条件 循环变量修改 3. for (表达式1; 表达式2; 表达式3) 循环体语句
习题 B0501 :输入一行字符,分别统计其中英文字母,空格,数字和其他字符的个数(回车键作为输入结束标记)
游戏扩展 A05011 计时程序 计算执行10000000空循环需要的时间。 A05012 循环随机算式:每次游戏后询问游戏者是否继续游戏,键入y或Y 则继续游戏,否则退出。 C0501猜数游戏:系统产生一个随机数,请游戏者从键盘上输入数据猜想设值的数是什么,告诉用户是猜大了还是小了。5次以内猜对,用户获胜。否则,提示失败信息,并告诉游戏者该数值。(可扩充程序功能,如循环猜数游戏,对游戏进行计时等) C0502 打字练习游戏 随机出现若干个英文字母,游戏者按照顺序键入。 练习结束后给出正确以及错误个数的提示信息,计算正确率,并给出所用时间。
游戏扩展 A0511 计时程序。 执行10000000空循环需要的时间 void main( ) { long i = 10000000L; clock_t start, finish; double duration; start = clock(); while( i-- ) ; finish = clock(); duration = (double)(finish - start) / CLOCKS_PER_SEC; printf("%ld empty loops is %f seconds\n", i,duration ); } #include<stdio.h> #include<stdlib.h> #include<time.h> 获取的时间是一个长整形 将毫秒转化成秒 1000
循环结构例题 A0512例: 循环随机算式(扩展A0502):每次随机算式游戏后询问游戏者是否继续游戏,键入y或Y 则继续游戏,否则退出。 #define N 100 void main() { int a,b,c,score=0,ans; char next; srand(time(0)); //设置种子 do{ a=rand()%N; b=rand()%N; c=a+b; printf("%d+%d=",a,b); scanf("%d",&ans); if(ans==c) printf("right!\n"); else { printf("wrong!\n"); printf("%d+%d=%d",a,b,c);} printf("play the game again? Y/N: "); fflush(stdin); //清空输入缓冲区 next=getchar(); }while((next=='Y')||(next=='y')); } #include<stdio.h> #include<stdlib.h> #include<time.h>
循环程序分析 猜数游戏:任意设置一个整数,请用户从键盘上输入数据猜想设值的数是什么,告诉用户是猜大了还是小了。5次以内猜对,用户获胜。否则,告诉用户设置的数据是什么。 循环猜数 分析: (1)已知循环次数n <=5 for() (2) 每次循环中 接收一个整数, scanf 并判断和已知数的大小关系 if 如果猜中退出循环 break (3)如果5次后没有猜中 n==6 则输出已知数
循环应用分析 C0502 打字练习游戏 随机出现英文字母,游戏者键入相同字母。 练习结束后给出正确以及错误个数的提示信息,计算正确率,并给出所用时间。 知识点: (1) 随机字母: ASCII码,给定范围的随机数 (2) 接收一个字符 (3) 统计正确个数: 分支判断,正确则计数增1 (4) 下一次接收字母前要清除输入缓存 A0604 (5) 循环结构:for,while 均可 (6) 系统计时 A0603