520 likes | 706 Views
第 4 章 循环结构程序设计. 在学生信息管理系统的设计中有许多需要重复处理的问题。要处理上述问题,最简明的方式是采用循环结构。. 本章内容. 4.1 循环结构的引入 4.2 while 语句 4.3 do-while 语句 4.4 for 语句 4.5 break 语句和 continue 语句 4.6 循环语句的嵌套 4.7 案例分析与实现. 【 学习目标 】 掌握三种循环控制语句: while 语句、 do-while 语句和 for 语句 区分三种循环控制语句的应用场合 理解并熟练掌握 break 、 continue 语句
E N D
第4章 循环结构程序设计 在学生信息管理系统的设计中有许多需要重复处理的问题。要处理上述问题,最简明的方式是采用循环结构。
本章内容 4.1 循环结构的引入 4.2 while语句 4.3 do-while语句 4.4 for语句 4.5 break语句和continue语句 4.6 循环语句的嵌套 4.7 案例分析与实现
【学习目标】 • 掌握三种循环控制语句:while语句、do-while语句和for语句 • 区分三种循环控制语句的应用场合 • 理解并熟练掌握break、continue语句 • 能够熟练应用for、while 和do-while语句进行程序设计
4.1 循环结构的引入 例如,要输入100个学生的分数,int score[100]; 如果不采用循环结构,程序代码: printf("请第1个学生的分数:"); scanf("%d",&score[0]); printf("请第2个学生的分数:"); scanf("%d",&score[1]); ... printf("请第100个学生的分数:"); scanf("%d",&score[100]); 如果采用循环结构,程序代码: int i=0; while(i<100) { printf("请第%d个学生的分数:",i+1); scanf("%d",&score[i]); i++; }
4.2 while语句 while语句又叫“当”语句,其一般格式为: while(条件表达式) 循环体
【例4-1】编写程序求1+2+3+…+100的和。 #include <stdio.h> void main() { int sum=0,i=1; while(i<=100) { sum=sum+i; i=i+1; } printf("sum=%d\n",sum); } 问题: 如果是求从1到100的所有奇数之和,那么上述程序应如何修改?
【例4-2】小红今年12岁,她父亲比她大30岁,编程计算:多少年后她父亲的年龄是她的年龄的2倍,此时她的年龄是多少?【例4-2】小红今年12岁,她父亲比她大30岁,编程计算:多少年后她父亲的年龄是她的年龄的2倍,此时她的年龄是多少? • 编程思路: • 循环条件是什么? • 重复执行的操作是什么? #include <stdio.h> void main (void) { int x=12,y=42,m; while(2*x!=y) { x++; y++; } m=x-12; printf("经过的年数:%d,小红的年龄:%d,小红父亲的年龄:%d \n",m,x,y); }
【例4-3】 编程输出1~200之间所有用3除余2、且用5除余3的数。 编程思路:可以采用穷举法来编程实现。 #include <stdio.h> void main() { int i=1; while(i<=200) { if((i%3==2) && (i%5==3)) printf("%d ",i); i++; } }
【例4-4】鸡兔同笼问题。已知笼中鸡和兔共100只,共有274只脚,求鸡和兔各有多少只?【例4-4】鸡兔同笼问题。已知笼中鸡和兔共100只,共有274只脚,求鸡和兔各有多少只? #include <stdio.h> void main(void) { int a=1,b; //a和b分别表示鸡和兔的数量 while(a<100) { b=100-a; if(a*2+b*4==274) printf("鸡有:%d只,兔有:%d只\n",a,b); a++; } }
#include <math.h> void main(void) { double sum=0,pi,c; //c为当前项 int n=1; //n为循环控制变量 while (n<=100) { c=pow(-1,n+1)/(2*n-1); sum=sum+c; n++; } pi=4*sum; printf("pi=%lf\n",pi); } • 问题: • 1)如果不调用数学函数pow(),能否采用其它方式来控制每一项的符号位? • int s=1; • c=s*1.0/(2*n-1); • s=-s;
2如果题目不指定计算的项数,而是根据精度要求计算到某一项为止,如计算到最后一项的绝对值小于10-6 为止,程序应如何修改? #include <stdio.h> #include <math.h> void main(void) { double sum=0,pi,c=1; //c为当前项 int n=1,s=1; while (fabs(c)>=1e-6) { c=s*1.0/(2*n-1); //当前项 sum=sum+c; s=-s; n++; } pi=4*sum; printf("pi=%lf\n",pi); }
4.3 do-while语句 while语句又叫直到型循环语句,其一般格式为: do 循环体 while(条件表达式);
【例4-6】编写程序求1+2+3+…+100的和。 #include <stdio.h> void main() { int sum=0,i=1; do { sum=sum+i; i=i+1; } while(i<=100); printf("sum=%d\n",sum); } 问题: while语句和do while语句两者有何区别?
【例4-7】在使用软件时,经常用到口令,编写一个口令输入程序,让用户不停地输入口令,直至输对为止。假设口令为100。要求分别采用while和do while两种循环语句来实现。 #include <stdio.h> void main() { int pwd; do { printf("请输入口令:"); scanf("%d",&pwd); }while(pwd!=100); printf("口令正确!"); } #include <stdio.h> void main() { int pwd; printf("请输入口令:"); scanf("%d",&pwd); while(pwd!=100) { printf("请输入口令:"); scanf("%d",&pwd); } printf("口令正确!"); } 对于先执行,再判断的应用场合,采用do-while语句实现更方便。
4.4 for语句 其一般格式为: for(循环变量赋初值;条件表达式;循环变量增值) 循环体
【例4-8】编写程序求1+2+3+…+100的和。 #include <stdio.h> void main() { int sum=0,i; for(i=1;i<=100;i++) sum=sum+i; printf("sum=%d\n",sum); } 问题: 1)如果求从1到100之间的所有奇数之和,上面的程序应如何修改? 2)什么情况下最适合采用for语句? 什么情况下最适合采用while语句或do while语句?
【例4-9】我国现有13亿人,按年0.2%的增长速度,10年后将有多少人? #include <stdio.h> void main() { double m=13; int i; for(i=1;i<=10;i++) m=m*(1+0.002); printf("10年后的人口数为:%f\n",m); }
【例4-10】 输出所有水仙花数。所谓水仙花数是指一个3位数,其各位数字的立方和等于该数本身。例:153=13+53+33 #include <stdio.h> void main() { int m,bai,shi,ge; // bai、shi、ge分别对应百位、十位和个位 for(m=100;m<=999;m++) { bai=m/100; shi=(m%100)/10; ge=m%10; if(m==bai*bai*bai+shi*shi*shi+ge*ge*ge) printf("%d ",m); } }
【例4-11】有一数列2、3、5、8、…,从第3项开始,每一项为其前两项之和,输出这个数列的前20项。 编程思路:这是一个典型的递推问题。 #include <stdio.h> void main() { int i,a1=2,a2=3,a3; printf("%d %d ",a1,a2); for (i=3;i<=20;i++) { a3=a1+a2; printf("%d ",a3); a1=a2; a2=a3; } }
4.5 break语句和continue语句 有些应用需要提前结束正在执行的循环操作。 4.5.1 break语句
【例4-12】在例1-9中,我们介绍了一个简单的菜单程序,如何当该程序的功能进行扩展?当用户输入的数字不正确时给出错误提示,直至输入正确为止。【例4-12】在例1-9中,我们介绍了一个简单的菜单程序,如何当该程序的功能进行扩展?当用户输入的数字不正确时给出错误提示,直至输入正确为止。 #include "stdio.h" void main() { int choice; printf(" 欢迎使用学生信息管理系统\n"); printf("-------------------------------------------------\n"); printf("1.添加学生信息 2.显示学生信息\n"); printf("3.修改学生信息 4.删除学生信息\n"); printf("5.查找学生信息 6.统计不及格人数、最高分和平均分\n"); printf("7.按总分排序 8.保存至文件(文本方式)\n"); printf("9.从文件读入(文本方式) 10.保存至文件(二进制方式)\n"); printf("11.从文件读入(二进制方式) 12 .退出程序\n"); printf("-------------------------------------------------\n"); printf("请选择功能模块,输入数字1-12: "); scanf("%d",&choice); printf("您选择了第%d号子菜单\n", choice); }
#include "stdio.h" void main() { int choice; printf(" 欢迎使用学生信息管理系统\n"); printf("-----------------------------------------------\n"); printf("1.添加学生信息 2.显示学生信息\n"); printf("3.修改学生信息 4.删除学生信息\n"); printf("5.查找学生信息 6.统计不及格人数、最高分和平均分\n"); printf("7.按总分排序 8.保存至文件(文本方式)\n"); printf("9.从文件读入(文本方式) 10.保存至文件(二进制方式)\n"); printf("11.从文件读入(二进制方式) 12 .退出程序\n"); printf("-----------------------------------------------\n"); printf("请选择功能模块,输入数字1-12: "); while(1) { scanf("%d",&choice); if(choice>=1 && choice<=12) break; else printf("输入数字不正确,请重输1-12: "); } printf("您选择了第%d号子菜单\n", choice); }
问题: 数学上已经证明:只要m不被2~ 之间的数整除,它就是素数。根据这一原理,上述程序应如何改进? 【例4-13】从键盘输入一个正整数,判断该数是否为素数。 素数定义:除了1和自身外不能被其它自然数整除的数。 #include<stdio.h> void main() { int i,m; scanf("%d",&m); for(i=2;i<=m-1;i++) if(m%i==0) break; if(i<=m-1) printf("%d不是素数\n",m); else printf("%d是素数\n",m); }
4.5.2 continue语句 • 不终止整个循环操作,而只是提前结束本次循环,接着执行下次循环。
【例4-14】输出100以内不能被3整除的自然数。 #include<stdio.h> void main() { int i; for(i=1;i<=100;i++) { if(i%3==0) continue; printf("%d ",i); } }
4.6循环语句的嵌套 如果一个循环语句的循环体中又包含有另一个完整的循环语句就叫做嵌套循环。
【例4-15】输出100到200之间的所有素数。 #include<stdio.h> #include<math.h> void main() { int i,m,k; for(m=100;m<=200;m++) { k=sqrt(m); for(i=2;i<=k;i++) if(m%i==0) break; if(i>k) printf("%d ",m); } }
【例4-16】数学史上有一个著名的百钱买百鸡问题。公鸡一只5元,鸡母一只3元,小鸡3只1元,用100元钱买100只鸡,问公鸡、母鸡和小鸡各买多少?【例4-16】数学史上有一个著名的百钱买百鸡问题。公鸡一只5元,鸡母一只3元,小鸡3只1元,用100元钱买100只鸡,问公鸡、母鸡和小鸡各买多少? #include <stdio.h> void main() { int a,b,c; //a、b、c分别表示公鸡、母鸡和小鸡的数量 for(a=0;a<=19; a++) for(b=0;b<=33;b++) for(c=0;c<=100;c++) if(5*a+3*b+c/3==100 && a+b+c==100) printf("公鸡:%d,母鸡:%d,小鸡:%d\n", a,b,c); }
【例4-17】采用对个位、十位、百位进行穷举的方法输出所有水仙花数。【例4-17】采用对个位、十位、百位进行穷举的方法输出所有水仙花数。 #include <stdio.h> void main(void) { int i,j,k; for(i=1;i<10;i++) for(j=0;j<10;j++) for(k=0;k<10;k++) if( (i*100+j*10+k)==((i*i*i)+(j*j*j)+(k*k*k))) printf("%d%d%d ",i,j,k); }
【例4-18】从键盘输入一个数n,求1!+2!+…+n!。【例4-18】从键盘输入一个数n,求1!+2!+…+n!。 #include <stdio.h> void main() { int i,j,n; long p,sum=0; //p保存阶乘,sum保存累加和 scanf("%d",&n); //输入n for(i=1;i<=n;i++) //各阶乘累加 { p=1; for(j=1;j<=i;j++) //求i! p=p*j; sum=sum+p; } printf("计算结果为:%d\n",sum); //在屏幕上显示结果 }
4.7案例分析与实现4.7.1 学生结构体数组的定义和引用 1. 结构体数组的定义 • 定义结构体数组的格式如下: struct 结构体名 数组名[下标]; • 学生结构体数组可以定义为: struct stu_type stu[100];
2. 结构体数组的引用 • 引用结构体数组成员的格式如下: 结构体数组名[下标].成员名 例如,第1个学生的各科成绩进行赋值,并计算总分: stu[0].c=60; stu[0].math=70; stu[0].en=80; stu[0].sum=stu[0].c+stu[0].math+stu[0].en;
【例4-19】从键盘输入学生人数,然后向学生信息管理系统中输入这些学生的信息,最后显示输入的数据。【例4-19】从键盘输入学生人数,然后向学生信息管理系统中输入这些学生的信息,最后显示输入的数据。
#include <stdio.h> struct stu_type{ …}; struct stu_type stu[100]; //学生数组 void main() { int i=0, stu_num; printf("请输入学生人数:"); scanf("%d",&stu_num); for(i=0;i<stu_num;i++) { printf("请输入第%d个学生的信息\n",i+1); printf("请输入学号:"); scanf("%s",stu[i].num); ... stu[i].sum=stu[i].c+stu[i].math+stu[i].en; stu[i].ave=(float)stu[i].sum/3; } printf("学生学号\t姓名\t年龄\tC语言\t数学\t英语\t总分\t平均分\n"); for(i=0;i<stu_num;i++) printf("%-16s%s\t%d\t%d\t%d\t%d\t%d\t%5.1f\n",stu[i].num,stu[i].name, stu[i].age,stu[i].c,stu[i].math,stu[i].en,stu[i].sum,stu[i].ave); }
4.7.2 案例分析与实现 【例4-20】 在例4-19中,我们是先从键盘输入学生人数,然后再输入这些学生的信息。这样存在一个问题,如果事先不知道学生人数,则需要先手工统计学生人数后再输入,比较麻烦。请编写在学生人数未知情况下的数据输入程序。 编程思路: 由于学生人数未知,所以循环不能由学生人数来控制,而应改为判断某一标志值,如0。当输入的学号为0时表示输入结束,否则,继续输入。
void add() //数据添加自定义函数 { int i=stu_num; printf("说明:依次输入学生信息,当输入的学号为0时表示输入结束\n"); while(1) { printf("请输入第%d个学生的信息\n",i+1); printf("请输入学号:"); scanf("%s",stu[i].num); if(strcmp(stu[i].num,"0")==0) break; printf("请输入姓名:"); scanf("%s",stu[i].name); printf("请输入年龄:"); scanf("%d",&stu[i].age); printf("请输入C语言成绩:"); scanf("%d",&stu[i].c); printf("请输入数学成绩:"); scanf("%d",&stu[i].math); printf("请输入英语成绩:"); scanf("%d",&stu[i].en); stu[i].sum=stu[i].c+stu[i].math+stu[i].en; stu[i].ave=(float)stu[i].sum/3; i++; } stu_num=i; printf("总共已输入 %d 个学生的信息\n",stu_num); }
void find() { char str[15]; int i,flag=0; //flag是标志位,用于判断学生是否找到,1为已找到 printf("请输入要查找的学生学号:"); scanf("%s",str); for(i=0;i<stu_num;i++) if(strcmp(str,stu[i].num)==0) { printf("学生学号\t姓名\t年龄\tC语言\t数学\t英语\t总分\t平均分\n"); printf("%-16s%s\t%d\t%d\t%d\t%d\t%d\t%5.1f\n",stu[i].num, stu[i].name,stu[i].age,stu[i].c,stu[i].math,stu[i].en,stu[i].sum,stu[i].ave); flag=1; } if(flag==0) printf("没有找到符合条件的学生\n"); }
void compute() //数据统计自定义函数 { int i,n=0,max=0,sum=0; //分别对应不及格人数、最高分和总分 for(i=0;i<stu_num;i++) { if(stu[i].c<60) n++; if(max<stu[i].c) max=stu[i].c; sum=sum+stu[i].c; } printf(" C语言统计结果如下:\n"); printf("不及格人数\t最高分\t平均分\n"); printf(" %d \t %d \t %5.2f\n",n,max,(float)sum/stu_num); }
void modify() { char str[15]; int i,m,flag=0; //flag是标志位,1为找到 printf("请输入要修改的学生学号:"); scanf("%s",str); for(i=0;i<stu_num;i++) if(strcmp(str,stu[i].num)==0) { flag=1; printf("学生学号\t姓名\t年龄\tC语言\t数学\t英语\t总分\t平均分\n"); printf("%-16s%s\t%d\t%d\t%d\t%d\t%d\t%5.1f\n",stu[i].num, stu[i].name,stu[i].age,stu[i].c,stu[i].math,stu[i].en,stu[i].sum,stu[i].ave); printf("确认修改该学生的信息吗?(y/n):"); m=getche(); if(m=='y' || m=='Y') { printf("\n请重新输入该学生的信息\n"); printf("\n请输入学号:"); scanf("%s",stu[i].num); printf("请输入姓名:"); scanf("%s",stu[i].name); printf("请输入年龄:"); scanf("%d",&stu[i].age); printf("请输入C语言成绩:"); scanf("%d",&stu[i].c); printf("请输入数学成绩:"); scanf("%d",&stu[i].math); printf("请输入英语成绩:"); scanf("%d",&stu[i].en); stu[i].sum=stu[i].c+stu[i].math+stu[i].en; stu[i].ave=(float)stu[i].sum/3; } } if(flag==0) printf("没有找到符合条件的学生\n"); }
例题 • 猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾又多吃了一个,第二天早上又将剩下的桃子吃掉一半又多吃了一个,以后每天早上都吃了前一天剩下的一半加一个,到第10天早上时,就只剩下一个桃子了,求第一天共摘了多少桃子? 编程思路: 采用逆向思维的方式,从后往前倒推。设某一天的桃子数为x,则之前一天的桃子数为(x+1)*2。按照这一公式从第10天开始倒推,第10天的桃子数x=1。
#include<stdio.h> void main() { int i,x=1; //x=1是第10天的桃子个数 for(i=9;i>0;i--) x=(x+1)*2; //计算每天的桃子个数 printf("第一天共摘了%d只桃子\n",x); }
例题 • 有一分数序列 、 、 、 、…,从第2项开始,每一项的分子为前一项的分子与分母之和,每一项的分母为前一项的分子,编程求这个数列的前n 项之和。 编程思路: 该程序需要用到递推算法,根据序列的第1项推出第2项,再根据第2项推出第3项,…。
#include <stdio.h> void main() { int a=2,b=1,t,i,n; double sum=0.0; printf("请输入n:"); scanf("%d",&n); for (i=1;i<=n;i++) { sum=sum+1.0*a/b; t=a; a=a+b; //下一项分子的值 b=t; //下一项分母的值 } printf("sum=%f\n",sum); }
本章小结 主要内容总结如下: (1) 循环语句包括两部分:循环控制条件和循环体。 (2) 循环语句有三种:for语句、while语句和do-while语句。它们的应用场合如下:循环次数事先明确的,一般使用for语句;循环次数不明确的,一般使用while语句或do-while语句。 (3) break语句用来提前终止循环,跳出循环体;continue语句用来提前结束本次循环,进入下一次循环。 (4) 三种循环语句可以互相嵌套,构成多重循环。
作业 • 用while或do while编程输出1~200之间所有能被12整除的整数。 • 我国现有13亿人,按年0.2%的增长速度,10年后将有多少人?
练习题 1. 编程从键盘输入k,求12+22+32+…+k2。 2. 编程输出1~200之间所有能被3整除、且个位数为6的整数。 3. 编程从键盘输入k的值及k个整数,统计其中正数、零和负数的个数。 4. 编程求
练习题 1. 编写程序,求e=1+1/1!+1/2!+1/3!+…+1/n!,直到第10项为止。 2. 编写程序,求e=1+1/1!+1/2!+1/3!+…+1/n!,直到最后一项小于10-5为止。 3. 输入两个正整数m和n,求其最小公倍数。 4. 编程输出方程x2+y2=1989的所有正整数解。