程序控制结构与结构化程序设计金川.ppt
第四章 程序控制结构及结构化程序设计(4),4.1 算法与程序设计算法(algorithm)是对特定问题求解步骤的一种描述算法的五个特性:有穷性:一个算法必须在执行有穷步之后结束。确定性:一个算法中每个步骤都必须意义明确,不能模棱两可,即不允许有二义性。有效性:算法的每一步都是能够实现的,即可操作的。输 入:算法有零个或多个输入。有输出:算法执行完毕,必须有一个或若干个输出结果。流程图:是一种能够比较形象地描述“算法”的工具,它对于编制 程序很有帮助。流程图又称为框图,它是由如下几种 不同的图形符号组合而成的。,起止框 处理框 输入输出框 流程线 条件判断框起止框:它代表一个算法的开始与结束。处理框:它可以表示算法中的一个或若干个步骤,这些步骤不涉 及输入与输出。输入输出框:它表示一个算法中需要进行输入或输出处理的步 骤。为了与一般的处理步骤区别开来,输入输出 框采用了平行四边形的形式。条件判断框:当一个算法中需要依据某一条件来决定后续操作 时,就采用此框。流程线:它表明每一步骤之间的先后顺序,标识一个算法的走向。,算法的描述自然语言描述法 向计算机中输入一个数X,若X0,则显示X的值;否则不显示。流程图表示 y n,C程序构成:文件函数语句序列。语句:C语言中描述计算过程的最基本单位。由分号;结束。结构化程序设计方法:程序语句序列由三种基本结构(顺序、分支、循环)构成,结构清晰、可读性强。4.2 程序的三种基本结构一、顺序结构 按书写的先后顺序执行语句。二、分支结构 按照当时的某个条件决定是否执行某些语句。三、循环结构 在一定条件下反复执行某些语句,直到这个条件不成立为止。,4.1 程序的三种基本结构一、顺序结构 按书写的先后顺序执行语句。二、分支结构 按照当时的某个条件决定是否执行某些语句。三、循环结构 在一定条件下反复执行某些语句,直到这个条件不成立为止。,4.3 语句一、表达式语句 C语言的表达式加上一个分号“;”结尾,就构成表达式语句,表达式语句主要完成运算功能。赋值表达式加上一个分号“;”结尾就构成了赋值语句,由于运算的结果往往需要保存起来,所以赋值语句也成为用得最多的表达式语句。1.简单赋值语句 一般形式为:=;x=x+1;ch=getchar();,2.多重赋值语句 一般形式为:=;i=j=k=1;3.复合赋值语句 一般形式为:;x+=2;二、复合语句复合语句:多个语句用花括号扩起来组成的语句。目的是将这多个语句看成是一条语句。复合语句的一般形式:说明部分,例:int i,j;i=s;j=i+;printf(“%d,%d”,i,j);注意:内部各条语句还是以分号结尾,结尾的 右花括号后不加分号。三、空语句 没有内容,只有一个分号“;”,便构成了一条空语句。空语句不执行任何操作,但在C语言中完全合法。空语句在逻辑上属于表达式语句,后面几节就要用到空语句。,4.4顺序结构的程序设计4.4.1 赋值语句赋值语句:赋值表达式后加一个分号。一、简单赋值语句形式:=;例如:a=2;b=3*5+7;,二、多重赋值语句形式:=.=;例如:i=j=k=n+1;a=b=c=5;三、复合赋值语句形式:;例如:i*=y+2;a%=10;,赋值语句的功能:将变量和表达式进行指定的运算后,将获得的值 赋予左边的变量,目的是得到一个计算结果。【例4.1】赋值语句使用举例(输入三角形三边的长度,求面积并将面积值输出)。海伦公式:假设有一个三角形,边长分别为a、b、c,三角形的面 积S 可由以下公式求得。算法分析:而公式里的p:,需要5个实型变量,调用求平方根函数,结果赋给一个变量,,实参使用表达式,求出边长和的一半,程序如下:#include#include main()float a,b,c,p,s;a=3.0;b=4.0;c=5.0;p=a+b+c;p/=2;s=sqrt(p*(p-a)*(p-b)*(p-c);printf(“s=%7.2f,s);运行结果如下:s=6.00,4.4.2 顺序结构程序设计举例【例4.2】编写一个程序,从键盘输入三位整数,将它们逆序输出,例如输入127,则输出721。算法分析:,程序如下:#include main()int a,i,j,k;printf(Enter a:n);scanf(%3d,运行情况如下:Enter a:127721,【例4.3】编写程序求出任一输入字符的ascii码。字符在内存存放的是它的ascii码(字符型和整型可以混合运算或者字符型可按整型输出),所以将它按整数输出即可。#include main()char c;printf(Enter the value of c:);scanf(%c,运行情况如下:Enter the value of c:aa:97,【例4.4】交换两个变量的值。设变量a、b均为整型变量,编写一个程序,输入a、b的值,并显示,然后交换a、b的值,再次显示。算法分析:,t,a,b,2,main()int a,b,t;printf(nEnter the value of a and bn);printf(a,b=);scanf(%d,%d,运行情况如下:Enter the value of a and b a,b=2,7,输出:a=2,b=7 changed a=7,b=2,4.5 分支结构(选择结构)三种条件转移语句:1、if语句2、if else语句3、switch语句4.5.1 if语句if语句的一般形式:if(表达式)语句;,表达式通常为条件表达式或逻辑表达式。if语句中的语句只能是一条语句,如果需要多条语句则使用复合语句。编写程序时使用缩进使结构清晰。,【例4.5】输入一个整数,若是3的倍数,则显示“ok”。#include main()int a;scanf(%d,【例4.6】输入一个字符,若是大写字母,则输出其ascii码。#include main()char ch;ch=getchar();if(ch=A,4.5.2 ifelse语句ifelse语句的一般形式:if(表达式)语句1;else语句2;或,if(表达式)语句1;语句n;else语句1;语句n;,【例4.7】输入两个整数,输出较大者。算法分析:main()int a,b;scanf(a=%d,b=%d,【,【例4.8】判断某一年是否是闰年,是则输出year xxxx is a leap year.否则输出year xxxx is not a leap year.if(y%4=0&y%100!=0)|(y%400=0)printf(year%d is a leap year.n,y);elseprintf(year%d is not a leap year.n,y);,建议:为使结构清楚不易错,语句使用花括号扩起(即使是一条语句)。,if(表达式1)语句1;else if(表达式2)语句2;else if(表达式3)语句3;else if(表达式n)语句n;else 语句n+1;,例如:if(score=90)grade=A;else if(score=80)grade=B;else if(score=70)grade=C;else if(score=60)grade=D;else grade=E;,4.5.3 条件分支的嵌套在分支的语句部分还可以出现分支语句,这样就形成了分支的嵌套(多分支结构),构成复杂的逻辑结构。if(表达式1)if(表达式2)语句1;else 语句2;else if(表达式3)语句3;else 语句4;,if(表达式1)语句1;else if(表达式2)语句2;else if(表达式3)语句3;else 语句4;,【例4.9】计算下列分段函数,x的值由键盘输入。Y=,-10(x-1.0),-1(-1.0 x0),1(0 x1.0),10(x 1.0),if(x0)if(x-1.0)y=-10;else y=-1;else if(x1.0)y=1;else y=10;,if(x-1.0)y=-10;else if(x0)y=-1;else if(x1.0)y=1;else y=10;,使用缩进和花括号避免程序的二义性,例如:if(c=0,或if(c=0,或if(c=0,4.5.4 switch语句 switch语句可直接处理多分支选择,不使用分支嵌套,简化程序结构。,表达式,语句组n,语句组2,语句组1,=值1,=值2,=值n,语句组n+1,=其他,if语句的一般形式:switch(表达式)case 常量表达式1:语句组1;break;case 常量表达式2:语句组2;break;.case 常量表达式n:语句组n;break;default:语句组n+1,常量表达式值必须互不相同,否则就会出现矛盾的现象。case 与 default 的顺序可以任意。执行完某case 后的语句后,将顺序执行后面case后的语句,直到遇 break 语句才退出整个switch结构的执行。如果没有default 且“表达式”值不等于任何case 后常量表达式的值,则直接退出switch结构而转到其后的语句执行。,【例4.10】输入一个无符号整数,然后按用户输入的代号,分别以十进制(代号D)、八进制(代号O)、十六进(代号X)制输出。main()unsigned int x;char c;scanf(%u,%c,【例4.11】一个简单的计算器程序main()int num1,num2;char oper;printf(enter a simple arithmetic expression:);scanf(%d%c%d,4.4.5 分支结构程序设计举例【例4.12】输入一个带符号的整型数,输出该数的位数。算法分析:,main()int x,y,m;printf(nEnter y=);scanf(%d,运行情况如下:Enter y=-2578-2578:4,【例4.13】求一元二次方程ax2+bx+c=0的解。算法分析:X=,(b2-4ac)=0),(a=0),(b2-4ac)0),(b2-4ac)0),两个复根,两个不等的实根,不是二次方程,-b/(2*a),=,d0,d=0,a=0,real=-b/(2*a),imag=sqrt(-d)/(2*a),x1=real+imag i,x2=real-imag i,is not,quadratic,-b/(2*a),X1=(-b+sqrt(d)/(2*a),d=b*b-4*a*c,yes,no,yes,no,yes,no,X2=(-b-sqrt(d)/(2*a),#include math.hmain()float a,b,c,d,x1,x2,real,imag;scanf(%f,%f,%f,else,real=-b/(2*a);imag=sqrt(-d)/(2*a);printf(has complex roots:n);printf(%7.2f+%7.2fin,real,imag);printf(%7.2f-%7.2fin,real,imag);,4.6 循环结构循环结构:重复执行某段程序,直到某个条件不成立的为止的一种程序结构。循环程序构成:初始化部分、工作部分、修改部分和判断部分。,n,y,4.6.1 while语句while语句的一般形式:while(表达式)语句;,【例4.14】从键盘上连续输入若干个字符(以回车换行符为结束标记),统计字符个数(不含回车换行符)初始化部分:int n=0,char c;判断部分:(c=getchar()!=n工作部分:n=n+1修改部分:无,#include stdio.hmain()int n=0;char c;while(c=getchar()!=n)n+;printf(number of charaters=%dn,n);,【例4.15】计算S=1+2+3+.+100之和。初始化部分:int i=1,s=0;判断部分:i=100工作部分:s=s+i;修改部分:i=i+1;注意:while后的语句复合语句格式缩进,程序如下:main()int i,s=0;i=1;while(i=100)s+=i;i+;printf(s=%dn,s);,运行情况如下:s=5050,4.6.2 dowhile语句dowhile语句的一般形式:do语句;While(表达式);注意:while(表达式)后的分号;,表达式,语句,n,y,【例4.16】从键盘上连续输入若干个字符(以回车换行符为结束标 记),统计字符个数(不含回车换行符)初始化部分:int n=-1,char c;工作部分:n=n+1;修改部分:无判断部分:(c=getchar()!=n,#include stdio.hmain()int n=-1;char c;do n+;while(c=getchar()!=n);printf(number of characters=%dn,n);,运行情况如下:abcd1234number of characters=8,【例4.17】用下列公式计算的值。/4=1-1/3+1/5-1/7+.1/n工作部分:pi=pi+t,t=s/n修改部分:n=n+2,s=s*(-1.0)初始化部分:pi=0.0,n=1.0,s=1.0判断部分:fabs(t)=1e-6,#include math.hmain()float pi=0.0,n=1.0,s=1.0,t;do t=s/n;/*求当前项t=s/n,s是符号,n是分母*/pi+=t;/*将当前项累加到pi中,pipit*/s*=-1.0;/*改变当前项的符号*/n+=2;/*产生下一个当前项的分母*/while(fabs(t)=1e-6);/*控制循环的结束条件*/printf(pi=%f n,4*pi);运行结果如下:pi=3.141598,4.6.3 for语句for 语句的一般形式:for(表达式1;表达式2;表达式3)循环体语句;注意:表达式1是初始化(只执行一次)。表达式2是循环条件判断。表达式3用于修改循环控制变量的值。,表达式1,表达式2,语句,表达式3,n,y,表达式也可以是与循环控制变量赋初值无关的其它表达式。表达式也可以是与循环控制无关的任意表达式。表达式、表达式可是一个简单表达式,也可是逗号表达式。表达式、表达式2、表达式3均可省略。,【例4.22】有一分数序列:2/1,3/2,5/3,8/5,求出这个数列的前20项之和。Yn/Xn:Yn=Yn-1+Xn-1,Xn=Yn-1 运行结果如下:sum=32.660259,main()int n,t,number=20;float a=2,b=1,s=0;for(n=1;n=number;n+)s=s+a/b;t=a;a=a+b;b=t;printf(sum=%9.6fn,s);,【例4.23】从键盘上输入若干个正整数,以零为输入结束标记,求其中的最大和最小数。main()int x,max,min;scanf(%d,运行结果为:2 1 5 3 7 0max=7 min=1,for(;x;),while(x),等价于,4.6.4 多重循环基本原则:内层循环完全要包含在外层循环的循环体内,允许内外层循环体交叉。【例4.24】输出以下图形。,#include main()int i,j,k;i=1;while(i=6)for(j=1;j=20-2*i;j+)printf();for(k=1;k=i;k+)printf(%4d,i);printf(n);i+;,4.6.5 break语句和continue语句break语句:强制中断当前层的循环,不再执行循环体中break语句后面的语句而退出循环。【例4.26】判定用户输入的一个整数是否是素数,是则输出yes,否则输出no。,#include main()int a,i=1;scanf(%d,continue语句:不执行continue语句后的语句而继续循环。【例4.27】输出200以内能被9整除的数。#include main()int n;for(n=9;n=200;n+)if(n%9!=0)continue;printf(“%dn”,n);,#include main()int n;for(n=9;n=200;n+)if(n%9=0)printf(“%dn”,n);,4.6.6 转移语句和语句标号goto语句格式:goto 标号goto语句功能:跳到标号所指的语句处去执行。【例4.28】计算1+2+3+.+100的值注意:goto语句不能跳到函数外,不得跳到循环体内。,#include main()int sum=0,i=1;loop:sum=sum+(i+);if(i101)goto loop;printf(“sum=%dn”,sum),【例4.29】累加用户输入的整数直到输入0为止。#include main()int s=0,x;while(1)scanf(“%d”,end:printf(“s=%dn”,s);注意:标号要合法(符合命名规则且不与关键字冲突),4.6.7 循环结构程序设计举例【例4.30】计算1!+2!+3!+n!算法分析:两层循环,内层计算某个数的阶乘,外层负责提供数,并且将内层的结果加到存放和的变量中去。,main()int j,k,n;long t,sum=0;printf(nEnter n=);运行情况如下:scanf(%d,【例4.30】计算1!+2!+3!+n!算法分析:main()int k,n;long t=1,sum=0;printf(nEnter n=);scanf(%d,n!=(n-1)!*n,sum=sum+n!,【例4.31】求斐波那契数列1,1,2,3,5,8,的前20 项。算法分析:Yn=Yn-1+Yn-2:需要三变量t=p1+p2,p1=p2,p2=t,main()int p1=1,p2=1,n=2,t;printf(%8d,p1);printf(%8d,p2);do t=p2+p1;/*求当前项*/p1=p2;p2=t;printf(%8d,p2);/*输出当前项*/n+;/*计数器加*/if(n%5=0)printf(n);/*每一行输出五个项*/while(n20);/*循环控制条件是输出项的个数*/,