第4章程序的控制结构_第1页
第4章程序的控制结构_第2页
第4章程序的控制结构_第3页
第4章程序的控制结构_第4页
第4章程序的控制结构_第5页
已阅读5页,还剩77页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章程序的控制结构C语言大学实用教程1内容提要算法的描述方法基本控制结构基本控制语句常用算法,如累加、累乘、统计、递推、迭代、穷举等程序的基本版式结构化程序设计的基本思想算法的概念

数据结构+算法=程序算法:为解决一个具体问题而采取的确定的有限的操作步骤,这里仅指计算机能执行的算法算法特性:有穷性确定性

有效性

没有输入或有多个输入

有一个或多个输出

算法的分类

数值运算算法:解决的是求数值解的问题,例如用辗转相除法求两个数的最大公约数等非数值运算算法:主要用于解决需要用分析推理、逻辑推理才能解决的问题,例如人工智能中的许多问题,查找、分类等问题算法的表示方法自然语言表示传统的流程图表示N-S结构化流程图表示

伪代码表示C程序结构C程序源程序文件1源程序文件2源程序文件3编译预处理命令全局变量声明函数1函数n…函数首部函数体局部变量声明执行语句构成程序的三种基本结构顺序结构选择结构循环结构已经证明,任何程序均可只用这三种结构综合描述只用这三种结构编制的程序,叫结构化程序程序必须符合结构化规则结构化程序设计的核心思想

采用顺序、选择和循环三种基本结构作为程序设计的基本单元只有一个入口;只有一个出口;无死语句,即不存在永远都执行不到的语句;无死循环,即不存在永远都执行不完的循环。采用“自顶向下、逐步求精”和模块化的方法进行结构化程序设计BANS图传统流程图顺序结构BABN如果

成绩<60

那么

通知补考否则

告知你考试成绩AY条件PABNY条件P分支结构(选择结构)条件PA当型循环直到型循环真假假条件PA假真循环结构当型循环A真假假条件P循环结构当P为真A当P为真A直到型循环条件PA假真循环结构直到P为假A直到P为假A复合语句{}括住的若干条语句构成一个复合语句语句块内可以定义变量变量仅在定义它的复合语句内有效变量必须在复合语句的开头定义复合语句可以用在任何可以使用语句的地方if-else选择结构的一种最常用形式if(表达式)

语句1;

else

语句2;

语句3表达式值非0时,执行语句1,然后语句3;

表达式值为0时,执行语句2,然后语句3else部分可以没有。if(表达式)

语句1;

语句3当表达式值为0时,直接执行语句3if-else嵌套使用时,注意else和谁配对的问题else-ifif的一种扩展形式if(表达式)

语句1;

elseif(表达式)

语句2;

elseif(表达式)

语句3;

…………

else

语句4;

语句5;else部分可以没有现场编程完成例4.5体型判断。按“体指数”对肥胖程度进行划分:体指数t=体重w/(身高h)2

(w单位为公斤,h单位为米)当t<18时,为低体重;当t介于18和25之间时,为正常体重;当t介于25和27之间时,为超重体重;当t>=27时,为肥胖。编程从键盘输入你的身高h和体重w,根据给定公式计算体指数t,然后判断你的体重属于何种类型。用3种方法编程:算法1:用不带else子句的if语句编程算法2:用在if子句中嵌入if语句的形式编程算法3:用在else子句中嵌入if语句的形式编程#include<stdio.h>main(){ floath,w,t; printf("Pleaseenterh,w:"); scanf("%f,%f",&h,&w); t=w/(h*h); if(t<18) { printf("t=%f\tLowerweight!\n",t); } if(t>=18&&t<25) { printf("t=%f\tStandardweight!\n",t); } if(t>=25&&t<27) { printf("t=%f\tHigherweight!\n",t); } if(t>=27) { printf("t=%f\tToofat!\n",t); }}#include<stdlib.h>#include<stdio.h>main(){ intmagic;/*计算机"想"的数*/ intguess;/*人猜的数*/ magic=rand();/*通过调用随机函数任意"想"一个数magic*/

printf("Pleaseguessamagicnumber:"); scanf("%d",&guess);/*输入人猜的数guess*/ if(guess>magic)/*如果guess大于magic,则提示"错误!太大!"*/ {printf("Wrong!Toohigh!\n"); } elseif(guess<magic)/*如果guess小于magic,则提示"错误!太小!"*/ {printf("Wrong!Toolow!\n"); } else/*如果guess等于magic,则提示"正确",并打印这个数*/ { printf("Right!\n"); printf("Thenumberis:%d\n",magic); }}switch多路选择switch(表达式){

case

常数1:

语句序列1;

case

常数2:

语句序列2;

…………

default:

语句序列3;

}default可以没有,但最好不省略不要忘记break现场编程完成计算器程序……例4.8编程设计一个简单的计算器程序,要求根据用户从键盘输入的表达式:操作数1运算符op操作数2然后,计算表达式的值,指定的运算符为加(+)、减(-)、乘(*)、除(/)#include<stdio.h>main(){ intdata1,data2;/*定义两个操作符*/ charop;/*定义运算符*/

printf("Pleaseentertheexpression:"); scanf("%d%c%d",&data1,&op,&data2);/*输入运算表达式*/ switch(op)/*根据输入的运算符确定要执行的运算*/ { case'+':/*处理加法*/ printf("%d+%d=%d\n",data1,data2,data1+data2); break; case'-':/*处理减法*/ printf("%d-%d=%d\n",data1,data2,data1-data2); break; case'*':/*处理乘法*/ printf("%d*%d=%d\n",data1,data2,data1*data2); break; case'/':/*处理除法*/ if(data2==0)/*为避免出现溢出错误,检验除数是否为0*/ printf("Divisionbyzero!\n"); else printf("%d/%d=%d\n",data1,data2,data1/data2); break; default: printf("Unknownoperator!\n"); }}#include<stdio.h>main(){ intscore,mark; printf("Pleaseenterscore:"); scanf("%d",&score); mark=score/10;/*采用整除方法,将mark取值压缩到有限的取值范围内*/switch(mark){case10:case9: printf("%d--A\n",score); break; case8: printf("%d--B\n",score); break; case7: printf("%d--C\n",score); break;case6: printf("%d--D\n",score); break;case5:case4:case3:case2:case1:case0: printf("%d--E\n",score); break; default: printf("Inputerror!\n");/*处理非法数据*/

} }循环——while,forwhile(表达式)

{

语句;}for(表达式1;表达式2;表达式3)

{

语句;}whilewhile(表达式)

{

语句;}只要表达式的值为非0,就重复执行语句,直到表达式值为0时止forfor(表达式1;表达式2;表达式3)

{

语句;}首先执行表达式1。如果表达式2的值为非0,就重复执行语句和表达式3,直到表达式2的值为0时止相当于:

表达式1;

while(表达式2){

语句;

表达式3;

}表达式1和表达式3可以没有或者是用逗号分隔的多个表达式的组合。但最好不要有太多的表达式组合注意在for和while语句之后一般没有分号有分号表示循环体就是分号之前的内容(空循环体)while(i<100);

i++;for(i=0;i<100;i++);

printf("%d",i);for通常有一个循环变量控制循环的次数,不要在循环体内改变这个变量do-whiledo

{

语句;

}while(表达式);首先执行语句,然后判断表达式的值。如果表达式为0,继续向下执行,否则,再次执行语句,再次判断表达式的值语句会被至少执行一次条件PA当型循环直到循环真假假条件PA假真假条件P条件PA假当循环条件第一次就为假时选择三种循环的一般原则如果循环次数已知,用for如果循环次数未知,用while如果循环体至少要执行一次,用do-while这只是“一般”原则,不是“原则”现场编程完成例4.6,例4.9例4.6:猜数游戏:先由计算机“想”一个数请人猜,如果人猜对了,则计算机给出提示:“Right!”,否则提示:“Wrong!”,并告诉人所猜的数是大还是小。例4.9:先由计算机“想”一个1到100之间的数请人猜,如果人猜对了,则结束游戏,否则计算机给出提示,告诉人所猜的数是太大还是太小,直到人猜对为止。计算机记录人猜的次数,以此来反映猜数者“猜”的水平。猜数游戏用到的库函数随机函数rand()#include<stdlib.h>RAND_MAX在stdlib.h中定义,不大于双字节整数的最大值32767产生[0,RAND_MAX]之间的随机数magic=rand();产生[0,b-1]之间的随机数magic=rand()%b;产生[a,a+b-1]之间的随机数magic=rand()%b+a;现场编程完成例4.6,发现问题猜数游戏用到的库函数随机函数srand为函数rand()设置随机数种子来实现对函数rand所产生的伪随机数的“随机化”通过键入随机数种子,产生[1,100]之间的随机数scanf("%u",&seed);srand(seed);magic=rand()%100+1;猜数游戏用到的库函数随机函数srand为函数rand()设置随机数种子来实现对函数rand所产生的伪随机数的“随机化”使用计算机读取其时钟值并把该值自动设置为随机数种子,产生[1,100]之间的随机数函数time()返回以秒计算的当前时间值,该值被转换为无符号整数并用作随机数发生器的种子#include<time.h>srand(time(NULL));magic=rand()%100+1;死循环永远不会退出的循环为死循环for(;;){}while(1){}do

{}while(1)一般情况下,要极力避免死循环绝大多数程序不需要死循环。如果出现,往往都是bug时间过长的循环会造成“假死”效果,也要考虑解决现场编程完成例4.11国王的许诺。相传国际象棋是古印度舍罕王的宰相达依尔发明的。舍罕王十分喜欢象棋,决定让宰相自己选择何种赏赐。位聪明的宰相指着8×8共64格的象棋盘说:陛下,请您赏给我一些麦子吧,就在棋盘的第一个格子中放1粒,第2格中放2粒,第3格放4粒,以后每一格都比前一格增加一倍,依此放完棋盘上的64个格子,我就感恩不尽了。舍罕王让人扛来一袋麦子,他要兑现他的许诺。

国王能兑现他的许诺吗?试编程计算舍罕王共要多少麦子赏赐他的宰相,这些麦子合多少立方米?(已知1立方米麦子约1.42e8粒)

总粒数为:sum=1+2+22+23+…+263

方法1#defineCONST1.42e8#include<stdio.h>#include<math.h>main(){intn;doubleterm,sum=0;/*累加求和变量赋初值*/for(n=1;n<=64;n++){term=pow(2,n-1);/*根据累加项的规律计算累加项*/sum=sum+term;/*作累加运算*/}printf("sum=%e\n",sum);/*打印总麦粒数*/printf("volum=%e\n",sum/CONST);/*打印折合的总麦粒体积数*/}方法2#defineCONST1.42e8/*定义符号常量CONST值为1.42e8*/#include<stdio.h>main(){

intn;

doubleterm=1,sum=1;/*累乘求积、累加求和变量赋初值*/

for(n=2;n<=64;n++){term=term*2;/*根据后项总是前项的2倍计算累加项*/sum=sum+term;/*作累加运算*/}

printf("sum=%e\n",sum);/*打印总麦粒数*/

printf("volum=%e\n",sum/CONST);/*打印折合的总麦粒体积数*/}

循环的嵌套使用嵌套的循环体时,应注意以下问题

在嵌套的各层循环体中,使用复合语句(即用一对大花括号将循环体语句括起来)保证逻辑上的正确性

内层和外层循环控制变量不应同名,以免造成混乱

嵌套的循环最好采用右缩进格式书写,以保证层次的清晰性

循环嵌套不能交叉,即在一个循环体内必须完整的包含着另一个循环

三种循环可互相嵌套,层数不限外层循环可包含两个以上内循环,但不能相互交叉嵌套循环的执行流程嵌套循环的跳转(1)while(){……while(){……}…...}(2)do{……do{……}while();…...}while();(3)while(){……do{……}while();…….}(4)for(;;){……do{……}while();……while(){……}…...}内循环外循环内循环禁止:从外层跳入内层跳入同层的另一循环向上跳转阅读以下程序,写出运行结果了解循环嵌套的工作流程#include<stdio.h>voidmain(){inti,j;for(i=1;i<=3;i++){for(j=1;j<=5;j=j+2)

printf("%3d%3d\n",i,j);

printf("%3d%3d\n",i,j);

}

printf("%3d%3d\n",i,j);}

111315

17

212325

27

313335

37

47例判断n是否素数读入nk=ni=2当ikn被i整除真假用break结束循环i=i+1ik+1真假输出:n”是素数”输出:n”不是素数”第一种设想第二种设想第三种设想第四种设想例4.19,20输入一个整数,判断它是否是素数

方法1#include<math.h>main(){

intm,i,k;

printf("Pleaseenteranumber:");

scanf("%d",&m); k=sqrt(m);

for(i=2;i<=k;i++) {

if(m%i==0) {

printf("No!\n");

gotoend; } }

printf("Yes!\n");end:

printf("Programisover!\n");}Pleaseenteranumber:

6

Programisover!No!方法1#include<math.h>main(){

intm,i,k;

printf("Pleaseenteranumber:");

scanf("%d",&m); k=sqrt(m);

for(i=2;i<=k;i++) {

if(m%i==0) {

printf("No!\n");

gotoend; } }

printf("Yes!\n");end:

printf("Programisover!\n");}Pleaseenteranumber:

5

Programisover!Yes!方法2#include<math.h>main(){

intm,i,k;

printf("Pleaseenteranumber:");

scanf("%d",&m); k=sqrt(m);

for(i=2;i<=k;i++){

if(m%i==0)

break; }

if(i>k)

printf("Yes!\n");

else

printf("No!\n");

printf("Programisover!\n");}Pleaseenteranumber:

6

Programisover!No!方法3#include<math.h>main(){

intm,i,k,flag=1;/*标志变量flag初值置为1*/

printf("Pleaseenteranumber:");

scanf("%d",&m); k=sqrt(m);

for(i=2;i<=k&&flag;i++) {

if(m%i==0)flag=0; }

if(flag)

printf("Yes!\n");

else

printf("No!\n");

printf("Programisover!\n");}这个程序是做什么的?#include<math.h>main(){

intm,i,k,flag=1;/*标志变量flag初值置为1*/

printf("Pleaseenteranumber:");

scanf("%d",&m); k=sqrt(m);

for(i=2;i<=m-1;i++) {

if(m%i==0)flag=0;

printf("%d\n",i);

}

if(flag)

printf("Nodivisor!Itisaprimenumber.\n");

printf("Programisover!\n");}现场编程完成例4.14编程输出如下形式的乘法九九表

#include<stdio.h>main(){

intm,n;

for(m=1;m<10;m++)

printf("%4d",m);/*打印表头*/

printf("\n");

for(m=1;m<10;m++)

printf("-");

printf("\n");

for(m=1;m<10;m++) {

for(n=1;n<10;n++) {

printf("%4d",m*n); }

printf("\n"); }}现场编程完成例4.15将上例输出格式改成如下的下三角格式打印

#include<stdio.h>main(){

intm,n;

for(m=1;m<10;m++)

printf("%4d",m);/*打印表头*/

printf("\n");

for(m=1;m<10;m++)

printf("-");

printf("\n");

for(m=1;m<10;m++) {

for(n=1;n<=m;n++) {

printf("%4d",m*n); }

printf("\n"); }}for(i=1;i<4*m;i++)

printf(“");

现场编程完成例4.16马克思手稿中有一道趣味数学题:有30个人,其中有男人、女人和小孩,在一家饭馆里吃饭共花了50先令,每个男人各花3先令,每个女人各花2先令,每个小孩各花1先令,问男人、女人和小孩各有几人?

解方程组穷举法方法1:采用三重循环穷举x,y,z的全部可能的组合

#include<stdio.h>main(){

intx,y,z;

printf("Man\tWomen\tChildern\n");

for(x=0;x<=30;x++)

for(y=0;y<=30;y++)

for(z=0;z<=30;z++)

if(x+y+z==30&&3*x+2*y+z==50)

printf("%3d\t%5d\t%8d\n",x,y,z);}

方法2:改进算法

#include<stdio.h>

main(){

intx,y,z;

printf("Man\tWomen\tChildern\n");

for(x=0;x<=16;x++)

for(y=0;y<=25;y++){z=30–x-y;

if(3*x+2*y+z==50)printf("%3d\t%5d\t%8d\n",x,y,z);}}

流程的转移控制break语句continue语句goto语句return语句标准库函数exit()

break和continue对for、while、do-while循环进行内部手术break,退出循环continue,中断本次循环体的执行,开始下一次break和continue少用为妙break和continue假假真真break表达式1表达式2循环语句的下一条语句循环语句的下一条语句假假真真

contiue表达式1表达式2continue

break语句功能:在循环语句和switch语句中,终止并跳出循环体或开关体说明:break只能终止并跳出最近一层的结构break不能用于循环语句和switch语句之外的任何其它语句之中

expr……break;……假(0)真(非0)whiledo……break;…...expr假(0)真(非0)whileexpr2……break;…...假(0)真(非0)forexpr1expr3switchexpr语句组1break;语句组2break;语句组nbreak;语句组break;…...const1const2constndefaultcase例break举例:输出圆面积,面积大于100时停止#definePI3.14159#include<stdio.h>voidmain(){intr;floatarea;for(r=1;r<=10;r++){area=PI*r*r;if(area>100) break;printf("r=%d,area=%.2f\n",r,area);}}例break举例:小写字母转换成大写字母,直至输入非字母字符#include<stdio.h>voidmain(){inti,j;charc;while(1){c=getchar(); if(c>='a'&&c<='z') putchar(c-'a'+'A'); else break;}}getch()getche()#include<conio.h>continue语句功能:结束本次循环,跳过循环体中尚未执行的语句,进行下一次是否执行循环体的判断仅用于循环语句中expr……continue;……假(0)真(非0)while真(非0)do……continue;…...expr假(0)whileexpr2……continue;…...假(0)真(非0)forexpr1expr3voidmain(){intn;for(n=100;n<=200;n++) {if(n%3==0)continue;printf(“%d”,n); }}Continue用法:

将100~200的不能被3整除的数输出例求输入的十个整数中正数的个数及其平均值#include<stdio.h>voidmain(){inti,num=0,a;floatsum=0;for(i=0;i<10;i++){scanf("%d",&a); if(a<=0)continue; num++; sum+=a;}printf("%dplusinteger'ssum:%6.0f\n",num,sum);printf("Meanvalue:%6.2f\n",sum/num);}标号举例error:goto举例gotoerror;一般形式goto语句标号;……

语句标号:……或语句标号:…………goto语句标号;goto与标号(label)exit()函数exit(0)作用是终止整个程序的执行,强制返回操作系统调用该函数需要嵌入头文件<stdlib.h>Dijkstra和

gotoE.W.Dijkstra,生于1930年,卒于2002年8月6日软件体系结构,结构化程序设计,……Dijkstra和

gotoDijkstra早在1968年就指出:“Gotoconsideredharmful”

,“Ibecameconvincedthatthegotostatementshouldbeabolishedfromall"higherlevel"programminglanguages.”“Thegotostatement…istoomuchaninvitationtomakeamessofone'sprogram.”糟糕的gotoSTART_LOOP:if(fStatusOk){

if(fDataAvaiable){i=10;

gotoMID_LOOP;}else{

gotoEND_LOOP;}}else{

for(i=0;i<100;i++){MID_LOOP://lotsofcodehere……}

gotoSTART_LOOP;}END_LOOP:糟糕的gotoSTART_LOOP:if(fStatusOk){

if(fDataAvaiable){i=10;

gotoMID_LOOP;}else{

gotoEND_LOOP;}}else{

for(i

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论