530 likes | 653 Views
Chap. 4 Selective Structure Programming. 第 4 章 选择结构 程序设计. 第 4 章 选择结构程序设计. 选择 ( 分支 ) 结构:体现程序运行过程中的逻辑判断能力。 程序在执行过程中根据某个条件的成立与否,来决定 下一步做什么 , 不做什么。 4.0 引言 4.1 算法及其描述 4.2 关系运算及其表达式 4.3 逻辑运算及其表达式 4.4 if 语句 4.5 switch 语句 4.6 选择结构程序设计举例 良好的源程序书写风格──注释. 4.0 引言.
E N D
Chap. 4 Selective Structure Programming 第4章 选择结构程序设计
第4章选择结构程序设计 选择(分支)结构:体现程序运行过程中的逻辑判断能力。 程序在执行过程中根据某个条件的成立与否,来决定 下一步做什么,不做什么。 4.0 引言 4.1 算法及其描述 4.2 关系运算及其表达式 4.3 逻辑运算及其表达式 4.4 if 语句 4.5 switch 语句 4.6 选择结构程序设计举例 良好的源程序书写风格──注释
4.0引言 【例4.1】计算火车行李托运费.输入行李重量,计算并输出托运费。 收费标准: (1)不超过50公斤,每公斤0.35元; (2)超过50公斤,其中50公斤同(1),超过部分每公斤0.50元。 1、变量设置:行李重量 weight,托运费 pay,均为实型。 2、程序清单: #include <stdio.h> int main ( ) { float weight,pay; printf(weight= ); scanf(%f, &weight); if (weight<=50) pay=weight*0.35 ; else pay=50*0.35+(weight-50)*0.5; printf( pay=%-7.2f\n , pay); return 0; } 解题基本步骤: 0、问题分析 1、变量设置 2、算法设计 3、程序清单
4.1 算法及其描述 算法:为解决一个特定问题而采取的确定的有限的步骤。 算法的特性:1. 有穷性 2. 确定性 3. ≥0个输入 4. >0个输出 5. 有效性 算法描述:自然语言、流程图、伪语言 [例4.1]算法描述——自然语言 1、输入weight的值 2、根据weight的值计算pay 3、输出pay的值 第2步求精: 若weight<=50 则 pay=weight*0.35 否则 pay=50*0.35+(weight-50)*0.5
4.1.1 流程图 流程图(框图) 1、描述算法直观、严谨、结构清晰、条理分明。 2、流程图可以用来构思解题思路、描述解题步骤、作为编 写程序和检查调试程序的依据及软件设计的技术资料。 3、流程图可粗可细。 粗:从宏观上反映解题思路; 细:使每一个步骤对应一条或几条语句,以便由它 直接编写程序。
开始 条件 结束 输入/输出 操作 起始框 终止框 输入/输出框 操作框 判别框 连接点 流程线 一、传统流程图 用规定的各种图形符号和表示走向的带箭头线段来描述算法步骤的图形。 流程图符号及其含义: 真 假
开始 输入weight 真 假 weight≤50 pay=weight*0.35 pay=50*0.35+(weight-50)*0.5 输出pay 结束 【例4.1】算法描述——传统流程图
二、 N-S结构化流程图 以I.Nassi和B.Shneiderman[美]在73年提出的方法为基础形成。 主要特点:取消了流程线,适合结构化程序设计,能较好地反映 算法的逻辑执行过程。 N-S流程图的基本形状如下所示: S1块 条件P 当P成立 成立 不成立 S块 S2块 S1块 S2块 S块 直到P成立 (1)顺序结构 (2)选择结构 (3)a“当型”循环 (3)b"直到型"循环
读入weight 输出pay 真weight ≤50假 pay=weight*0.35 pay=50*0.35+(weight-50)*0.5 [例4.1]算法描述——N-S流程图
[例4.1] 2、程序清单: #include <stdio.h> int main ( ) { double weight,pay; printf("weight="); scanf("%lf",&weight); if (weight<=50) pay=weight*0.35 ; else pay=50*0.35+(weight-50)*0.5; printf("pay=%-7.2f\n", pay); return 0; }
算术运算符 < ,<=, >, >= ==, != 赋值运算符 4.2关系运算及其表达式 “关系运算”即“比较运算”。 4.2.1 关系运算符及其优先次序 1.关系运算符(6种) < , <= , >, >= , ==(等于), !=(不等于) 2.优先级
4.2.2 关系表达式 1.关系表达式的概念 〈表达式〉〈关系运算符〉〈表达式〉 即用关系运算符将两个表达式连接起来的式子。 例如:下面的关系表达式都是合法的: a>b a+b<c-d (a=3)<=(b=5) 'a'>='b’ (a>b)= =(b>c) 2.关系表达式的值 ——逻辑值(“真”、“假”)。 C语言中: 用整数“1”表示“真”,用整数“0”表示“假”。
例如:假设num1=3,num2=4,num3=5,则: (1)num1>num2的值为0。 (2)(num1>num2)!=num3的值为1。 (3)num1<num2<num3的值为1。 思考:改变num1或num2的值,会影响整个表达式的值吗? (4)(num1<num2)+num3的值=6,。 注意:C语言的逻辑值用整数 1 和 0 表示。所以,关系表达 式的值,还可以参与其它种类的运算,例如算术运算。
4.3 逻辑运算及其表达式 单一条件如“x>=0”,用关系表达式表示。 复杂条件如“x>=0”并且“x<10”,用逻辑表达式表示。 4.3.1 逻辑运算及其优先次序 1.逻辑运算符及其运算规则 (1)逻辑运算符: && 逻辑与 (相当于“并且”) || 逻辑或 (相当于“或者”) ! 逻辑非 (相当于“不是”) x>=0 && x<10 √ 0<=x<10 ×
例如:下面的表达式都是逻辑表达式 (x>=0) && (x<10) ,(x<1) || (x>5) ,! (x= =0), (year%4==0)&&(year%100!=0)||(year%400==0) (2)运算规则 1)a&&b:当且仅当a和 b的值都为真时,结果为真,否则为假。 2)a||b :当且仅当a和 b的值都为假时,结果为假,否则为真。 3) !a :当a的值为真时,结果为假;当a的值为假时,结果为真。 例如: 假定x=5, 则(x>=0) && (x<10) 的值为真,即1。 (x<-1) || (x>5) 的值为假,即0。
2.逻辑运算符的运算优先级 (1) ! → && → || (2) !→ 算术运算符 → 关系运算符 → &&→ || → 赋值运算符 4.3.2 逻辑表达式 1.逻辑表达式的概念 用逻辑运算符将1个或多个关系表达式连接起来的式子。 逻辑表达式用来表示多个条件的组合。 例如:(year%4==0)&&(year%100!=0)||(year%400==0) 是一个判断年份year是否是闰年的逻辑表达式。 2 .逻辑表达式的值 逻辑值,同关系表达式。
数值与逻辑量的对应: (1)逻辑值 数值 1表示真、用0表示假。 (2)数值 逻辑值 0为假、非0为真。 例如:num=12, 则: !num的值为 0; num>=1 && num<=31的值为 1; num || num>31的值为 1。 3.说明 (1)逻辑表达式求值时,如提前得到结果,则剩下的运算不 再进行。 (2)C语言逻辑运算符两侧的操作数,可以是整数,也可以是 其它任何类型的数据,如实型、字符型或指针型等。
n1>n2 真 假 max n1 max n2 n3>max 真 假 max n3 输入n1,n2,n3 将n1与n2中的大数存于max中 将n3与max中的大数存于max中 输出max 4.4 if语句和条件运算符 4.4.1 if 语句 【例4.2】求三个数中的最大者。 (1)问题分析及变量设置: 从键盘读入三个数分别存入变量n1,n2,n3中,求出最大数存入变量max中,float型。 (2)算法设计: 1)N-S流程图 一级算法: 二级求精: 用if 语句实现 需求精
开始 输入n1,n2,n3 真 假 n1≥n2 max=n1 max=n2 真 假 n3≥max max=n3 输出 max 结束 2)传统流程图
开始 输入n1,n2,n3 n1≥n2 max=n1 max=n2 真 假 n3≥max max=n3 输出 pay 结束 2)传统流程图 (3)程序清单1 #include <stdio.h> int main() { float n1,n2,n3,max; printf("n1,n2,n3="); scanf("%f%f%f",&n1,&n2,&n3); if (n1>=n2) max=n1; else max=n2; if (n3>=max) max=n3; printf("max=%.2f\n",max); return 0; } 真 假
(3)程序清单2 #include <stdio.h> int main() { float n1,n2,n3,max; printf("Please intput three numbers:" ); scanf("%f,%f,%f",&n1,&n2,&n3); if (n1>n2) max=n1; else max=n2; if (n3>max) max=n3; printf("The largest number is %.2f\n",max); return 0; } 运行结果:Please input three numbers:11,22,18↙ The largest number is:22.00 如 何 选 择 调 试 数 据 ?
算法的多样性 将本例中程序段: if (n1>n2) max=n1; else max=n2; if ( n3>max) max=n3; 改为: max=n1; if(n2>max) max=n2; if(n3>max) max=n3; 这种方法对从3个以上的数中找最大数的处理,非常有效。
真 假 表达式 表达式 语句1 语句1 语句2 说明: (1)if 语句中的<表达式>必须用( )括起来。 (2)else子句,必须与 if 配对使用,不能 单独使用。 (3)当if 和 else下面的语句,由多条语句 构成时,要使 用复合语句形式(即加 花括号)。 1.If 语句的一般格式 if (<表达式>) <语句1> [ else <语句2> ] 2.If 语句的执行过程 双分支 单分支 真 假
真 假 表达式 语句1 语句2 表达式 真 假 语句1 语句2 表达式 真 假 语句1 真 假 表达式 语句1
输入n1,n2 n1 > n2 Y N 交换n1与n2 输出n1, n2 将大者放入n1中, 小者放入n2中 【例4.3】输入三个数,按从小到大的顺序排序后输出。 (1)先设计程序将两个数按从小到大的顺序排序输出。 main() { float n1,n2; printf(“n1,n2=”); scanf(“%f,%f”,&n1,&n2); if (n1>n2) n1 n2; printf(“result:%.2f,%.2f\n”,n1,n2); } 声明 t 复合语句 {t=n1;n1=n2;n2= t ;}
#include <stdio.h> int main() {int n1,n2,n3,t; printf("Please input three numbers:"); scanf("%d,%d,%d",&n1,&n2,&n3); if (n1>n2) { t=n1;n1=n2;n2=t; } if (n2>n3) { t=n2;n2=n3;n3=t; } if (n1>n2) { t=n1;n1=n2;n2=t; } printf("Three numbers after sorted: %d,%d,%d\n",n1,n2,n3); return 0; } 运行结果: Please input three numbers:11,22,18↙ Three numbers after sorted: 11,18,22 参考P.88
4.4.2 if 语句的嵌套 表达式1 真 假 指在if 语句中,又包含有 if 语句的情况。 例: 真 假 真 假 表达式2 表达式3 语句1 语句3 语句2 语句4
表达式1 真 假 表达式2表达式3 真 假真 假 语句1 语句2语句3 语句4 If (表达式1) if (表达式2) 语句1 [else 语句2 ] else if (表达式3) 语句3 [else 语句4 ]
-1 x<0 y= 0 x=0 1 x>0 X < 0 真 假 x = 0 y = -1 真 假 y = 0 y = 1 【例4.4】符号函数 输入 x #include <stdio.h> int main() { int x,y; printf("x="); scanf("%d",&x); if (x<0) y=-1; else if (x==0) y=0; else y=1; printf("y=%d\n",y); return 0; } 输出 y 方法2,参p.101
n3>n2 真 假 n3>n1 n2>n1 真 假真 假 max=n3 max=n2 求三个数中最大数 小明同学设计的算法和程序正确吗? 输入n1,n2,n3 #include <stdio.h> int main() { float n1,n2,n3,max; printf("n1,n2,n3="); scanf("%f,%f,%f",&n1,&n2,&n3); max=n1; if (n3>n2) if (n3>n1) max=n3; else if (n2>n1) max=n2; printf("max=%.2f\n",max); return 0; } max=n1 { } 输出max
else子句与 if 的匹配原则: else 与在它上面、距它最近、且尚未匹配的 if 配对。 为明确匹配关系,避免匹配错误,建议: 将内嵌的 if 语句,用花括号括起来。
分析:0 <= x < 10 0或1 1 上机问题: 1、条件“x>=0”并且“x<10”, 如何用逻辑表达式表示? 0 <= x < 10 × x>=0 && x<10 √ 2、float l,h; printf(“l,h=\n”); scanf(“l=%d,h=%d\n”,l,h); printf(“l,h=”); scanf(“%f%f”,&l,&h); √
N y N y N y N y P1 N P1 P2 y N P2 P3 y S1 N P4 S2 P3 y S1 S3 N P4 S2 S4 S5 y S3 S4 S5 if 语句嵌套特例(多分支) p.89 if (P1) S1 else if(P2)S2 else if(P3)S3 else if(P4)S4 else S5 if (P1) S1 else if(P2)S2 else if(P3)S3 else if(P4)S4 else S5
输入 year (4位) 输入 year (4位) leap=0 leap=0 Year被4整除 真 假 year不被100整除year被400整除 真 假真 假 leap=1 leap=1 Year被4整除 真 假 year不被100整除 真 假 leap=1 year被400整除 真 假 leap=1 leap 真 假 输出“闰年” 输出“非闰年” leap 真 假 输出“闰年” 输出“非闰年” 标志变量 #include <stdio.h> int main() { int year,leap=0; printf("year="); scanf("%d",&year); if (year%4==0) if (year%100!= 0) leap=1; else if (year%400==0) leap=1; if (leap) printf("Yes.\n"); else printf("No.\n"); return 0; } [例4.5]从键盘上输入年份year(4位),判断是否闰年。 闰年的条件是: 能被4整除、但不能被100整除,或者能被400整除。 P.105
判断某年是否闰年 main() { int year,leap=0; /* leap为标志变量*/ printf("Please input the year:"); scanf("%d",&year); if (year % 4==0) { if (year % 100 != 0) leap=1; else if (year%400==0) leap=1; } if (leap) printf("%d is a leap year.\n",year); else printf("%d is not a leap year.\n",year); } if (year%4==0 && year%100!=0) leap=1; else if (year%400==0) leap=1; if ( (year%4==0 && year%100!=0) || (year%400==0) ) printf("%d is a leap year.\n",year); else printf("%d is not a leap year.\n",year);
表达式1 真 假 取表达式2的值 取表达式3 的值 4.4.3 条件运算符 1.一般格式 : < 表达式1>?<表达式2>:<表达式3> 三目运算! eg. (a>b)?a:b 2.运算规则 p.97 3.优先级与结合性 算术运算符 → 关系运算符 → 条件运算符 → 赋值运算符 右结合性 4 .常用方式 max=(a>b)?a:b等价于 if (a>b) max=a; else max=b;
ch=getchar(); 【例 4.6】从键盘上输入一个字符,如果它是大写字母,则 把它转换成小写字母输出;否则,直接输出。 #include <stdio.h> int main() { char ch; printf("Input a character: "); scanf("%c",&ch); ch=(ch>='A' && ch<='Z') ? (ch+32) : ch; printf("ch=%c\n",ch); return 0; } if (ch>='A' && ch<='Z') ch= (ch+32); else ch=ch; P.99
4.5 switch 语句 专用于实现多分支结构(多路选择结构),它的使用比if语句的嵌套简单、直观,但要注意适用情况。 1.语句格式 switch(<表达式>) { case <常量1>:<语句1> case <常量2>:<语句2 ...... case <常量n>:<语句n> [default: <语句n+1> ] }
2.说明 (1)switch后面的<表达式>,可以是int、char或枚举类型。 (2)每个case后面<常量表达式>的值,必须各不相同。 (3)case后面的<常量表达式>仅起语句标号作用,并不进行 条件判断。 故 应合理使用break语句! (4)各case及default子句的先后次序,不影响程序执行结果。 (5)多个case子句,可共用同一组语句。
输入year,month的值 switch(month) 1,3,5,7,8,10,12 4,6,9,11 2 是闰年 31days 30days T F 29days 28days 输出days的值 【例4.7】输入年、月,输出该月有几天。 if (month==1==3==5==7==8==10==12)days=31? if (month==1||month==3||month==5||…||month==12) days=31; else if (month==4||month==6||month==9||month==11) days=30; else if(闰年)days=29; else days=28;
main( ) { int year,month,days; scanf(“%d%d”,&year,&month); switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: days=31; break; case 4: case 6: case 9: case 11: days=30; break; case 2 : if (year %4==0 && year%100 !=0) ||(year%400==0) days=29; else days=28; } printf(“year=%d,month=%d,days=%d”,year,month,days); }
【例4.8】输入成绩score,按下列原则输出其等级:【例4.8】输入成绩score,按下列原则输出其等级: score≥90: A等; 80≤score<90: B等; 70≤score<80: C等; 60≤score<70: D等; score<60: E等。 分析: grade=score/10 A等: grade=9或10; B等: grade=8; C等: grade=7; D等: grade=6; E等: grade=0~5;
程序清单1 main() { int score, grade; printf(“Input a score(0~100): ”); scanf(“%d”, &score); grade = score/10; /*将成绩整除10,转化成switch语句中的case标号*/ switch (grade) { case 10: case 9: printf(“Grade=A\n”); break; case 8: printf(”Grade=B\n"); break; case 7: printf(”Grade=C\n"); break; case 6: printf(”Grade=D\n"); break; case 5: case 4: case 3: case 2: case 1: case 0: printf(“Grade=E\n”); break; default: printf(“The score is out of range!\n”); } } 运行结果: Input a score(0~100): 85↙ Grade=B
程序清单2 main() { int score, grade; char Grade; printf(“Input a score(0~100): ”); scanf(“%d”, &score); grade = score/10; /*将成绩整除10,转化成switch语句中的case标号*/ switch (grade) { case 10: case 9: Grade=‘A’; break; case 8: Grade=‘B’; break; case 7: Grade=‘C’; break; case 6: Grade=‘D’; break; case 5: case 4: case 3: case 2: case 1: case 0: Grade=‘E ’; break; default: Grade=‘ ’; } if (Grade !=‘ ’ ) printf(“Grade=%c\n”,Grade); else printf(“The score is out of range!\n”); } 运行结果: Input a score(0~100): 85↙ Grade=B
a=0 真 假 disc=0 真 假 disc>0 真 假 x1=(-b+sqrt(disc))/(2*a) x2=(-b-sqrt(disc))/(2*a) 输出两个实根x1,x2 p=-b/(2*a) q=sqrt(-disc))/(2*a) 输出两个共轭复根x1,x2 4.6 选择结构程序设计举例 输入方程的系数a,b,c disc=b*b-4*a*c 【例4.9】求一元二次方程ax2+bx+c=0的解。要求程序具有通用性。 输出 出错 信息 输出 两个 相等 实根 #include <stdio.h> #include <math.h> int main() { double a,b,c,disc,x1,x2,p,q; scanf("%lf%lf%lf",&a,&b,&c); P.105
程序清单 disc=b*b-4*a*c; if(a==0) printf("Error!\n"); //输出出错信息else if(disc==0) printf("x1=x2=%-7.2f\n", -b/(2*a)); //输出两个相等的实根else { if (disc>0) { x1=(-b+sqrt(disc))/(2*a); //求两个不相等的实根x2=(-b-sqrt(disc))/(2*a);printf("x1=%-7.2f,x2=%-7.2f\n", x1, x2); } else { p=-b/(2*a); //求两个共轭复根的实部和虚部q=sqrt(-disc)/(2*a);printf("x1=%.2f+%.2fi\n",p,q); //输出两个共轭复根printf("x2=%.2f-%.2fi\n",p,q); } } return 0; }
Sy3_2.输入一个不多于5位的正整数,要求:(1)求出它是几位数;(2)分别输出每一位数字;(3)按逆序输出各位数字。Sy3_2.输入一个不多于5位的正整数,要求:(1)求出它是几位数;(2)分别输出每一位数字;(3)按逆序输出各位数字。 #include <stdio.h> int main() { int num,n1,n2,n3,n4,n5,place; printf("input(0-99999):"); scanf("%d",&num); if(num>9999) place=5; else if(num>999) place=4; else if(num>99) place=3; else if(num>9) place=2; else place=1; printf("place=%d\n",place); n5=num/10000; n4=(num-n5*10000)/1000; n3=(num-n5*10000-n4* 1000)/100; n2=(num-n5*10000-n4*1000-n3*100) /10; n1=(num%10); n5=num/10000; n4=num/1000%10; n3=num/100%10; n2=num/10%10; n1=num%10;
printf("each digit is:"); switch(place) {case 5:printf("%d,%d,%d,%d,%d\n",n5,n4,n3,n2,n1); printf("the invers number is: %d,%d,%d,%d,%d\n", n1,n2,n3,n4,n5); break; case 4:printf("%d,%d,%d,%d\n",n4,n3,n2,n1); printf("the invers number is %d,%d,%d,%d\n",n1,n2,n3,n4); break; case3:printf("%d,%d,%d\n",n3,n2,n1); printf("the invers number is: %d,%d,%d\n", n1,n2,n3); break; case 2:printf("%d,%d\n",n2,n1); printf("the invers number is: %d,%d\n", n1,n2); break; case 1:printf("%d,%d\n", n1); printf("the invers number is: %d\n",n1);break; } return 0; }
【例4.10】已知某公司员工的保底薪水为500,某月所接工程的利【例4.10】已知某公司员工的保底薪水为500,某月所接工程的利 润profit(整数)与利润提成的关系如下(计量单位:元): profit≤1000 没有提成; 1000<profit≤2000 提成10%; 2000<profit≤5000 提成15%; 5000<profit≤10000 提成20%; 10000<profit 提成25%。 算法设计要点: 为使用switch语句,须将profit与提成的关系,转换成某些整数与提成的关系。分析本题可取:grade=(profit-1)/1000。 profit≤1000 对应grade=0 1000<profit≤2000 对应grade= 1 2000<profit≤5000 对应grade= 2、3、4 5000<profit≤10000 对应grade= 5、6、7、8、9 10000<profit 对应grade= 10、11、12、……
#include <stdio.h> int main( ) { int profit, grade; double salary=500; printf("Input profit: "); scanf("%d", &profit); //将利润转化成 switch语句中的case标号 grade = (profit – 1) / 1000;