第4章 选择结构程序设计 在现实生活中,需要进行判断和选择的情况是很多的 如果你在家,我去拜访你 如果考试不及格,要补考 第4章 选择结构程序设计 在现实生活中,需要进行判断和选择的情况是很多的 如果你在家,我去拜访你 如果考试不及格,要补考 输入一个整数,要求输出其绝对值 处理这些问题,关键在于进行条件判断 由于程序处理问题的需要,在大多数程序中都会包含选择结构,需要在进行下一个操作之前先进行条件判断 x>=0 输出x 输出-x 是 否
C语言有两种选择语句: (1)if语句,实现两个分支的选择结构 (2)switch语句,实现多分支的选择结构
(1)if语句(条件选择语句) if语句的三种形式 形式一: 格式:if (表达式) statement 执行过程: …… int x,y; 表达式为 0? 非0 statement statement 非0 =0 注意:若statement有几个语句,则用“{}”括起来。 表达式为 0? …… int x,y; scanf(“%d”,&x); y=x; if(x<0) y=-x; printf(“%d”,y); y= x (x>=0) -x(x<0)
例4.2 输入两个实数,按代数值由小到大的顺序输出这两个数。 a>b 非0 a与b交换 输出a,b 输入a,b
★ ● ● ★ 解题思路: 互换前 A B 互换后 A B 只需要做一次比较,然后进行一次交换即可 用if语句实现条件判断 关键是怎样实现两个变量值的互换 ★ ● 互换前 A B ● ★ 互换后 A B
C ★ ★ ● A B
C ★ ★ ● A ● B
C ★ ● A ● B ★
如果a>b 将a和b的值互换 #include <stdio.h> int main() { float a,b,t; scanf("%f,%f",&a,&b); if(a>b) { t=a; a=b; b=t; } printf("%5.2f,%5.2f\n",a,b); return 0; 如果a>b 将a和b的值互换
选择结构,用if语句实现的 #include <stdio.h> int main() { float a,b,t; scanf("%f,%f",&a,&b); if(a>b) { t=a; a=b; b=t; } printf("%5.2f,%5.2f\n",a,b); return 0; 选择结构,用if语句实现的
…… 形式二: int x,y; 格式:if (表达式) y= scanf(“%d”,&x); statement1 if(x>=0) y=x; else y=-x; printf(“%d”,y); 形式二: 格式:if (表达式) statement1 else statement2 执行过程: y= x (x>=0) -x(x<0) statement1 statement2 非0 =0 表达式为 0? 表达式为 0? 非0 statement1 statement2
else if (表达式2 ) statement2 else if (表达式3 ) statement3 …... 形式三: 格式: if ( 表达式1 ) statement1 else if (表达式2 ) statement2 else if (表达式3 ) statement3 …... [ else statementn ] 执行过程: 表达式1 statemnt1 非0 =0 表达式2 表达式3 statemntn statemnt3 statemnt2
分号不能丢 例: if (cost>1000) abate =0.6; 商品按销售额进行打折: abate= 0.6(cost>=1000) 0.7(800=<cost<1000) 0.8(600=<cost<800) 0.9(400=<cost<600) 1.0(cost<400) 分号不能丢 例: if (cost>1000) abate =0.6; else if (cost>800) abate =0.7; else if (cost>600) abate =0.8; else if (cost>400) abate =0.9; else abate =1.0;
#include<stdio.h> int main() { float cost,acount,abate; scanf("%f",&cost); if (cost>=1000) abate=0.6; else if (cost>=800) abate=0.7; else if (cost>=600) abate=0.8; else if (cost>=400) abate=0.9; else abate =1; acount=cost*abate; printf("cost=%.2f\nabate=%.1f\n%acount= %.2f\n", cost,abate,acount); return 0; }
关系运算和逻辑运算 1、关系运算符 2、关系运算表达式 3、逻辑运算符 4、逻辑运算表达式
关系运算 “关系运算”实际是“比较运算”。将两个值进行比较,判断其比较的结果是否符合给定的条件。 例如:a>3 关系运算符:>, >=, <, <=, = =, != 双目运算 优先级和结合性:6、7级,左结合 优先级低于算术运算 > >= < <= = = != 优先级相同(低) 优先级相同(高) 算术运算符 关系运算符 赋值运算符 (低) (高) c>(a+b) 等效于c>a+b (a>b)==c等效于a>b==c a==(b<c) 等效于a==b<c a=(b>c)等效于a=b>c
关系表达式 用关系运算符将两个数值或数值表达式连接起来的式子 关系表达式的值是一个逻辑值,即“真”或“假” 在C的逻辑运算中,以“1”代表“真”,以“0”代表“假”
例1: a=3,b=8,c=10; 例2: a=5; b=9; c=b>a; c=a+(a<b); a>b (a>b)>(b<c) ‘a’<‘b’ (a=3)>(b=5) 例2: a=5; b=9; c=b>a; c=a+(a<b); c=0 c=6 1
&&(逻辑与), ||(逻辑或)——双目运算 !(逻辑非)——单目运算 逻辑运算:表示简单条件组成的复合条件 逻辑运算符: &&(逻辑与), ||(逻辑或)——双目运算 !(逻辑非)——单目运算 a && b a|| b !a 优先次序: 优先级和结合性: !——2(右结合) &&——11,||——12(左结合) 算术运算符 关系运算符 &&和|| 赋值运算符 !(非) (低) (高) 例如: (a>b)&&(x>y) a>b&&x>y (a= =b)||(x= =y) a= =b||x= =y (!a)||(a>b) !a||a>b
逻辑运算表达式 逻辑表达式的值应该是逻辑量“真”或“假” 编译系统在表示逻辑运算结果时 以数值1代表“真”,以0代表“假” 但在判断一个量是否为“真”时 以0代表“假”,以非0代表“真” 注意:将一个非零的数值认作为“真”
修改后的逻辑运算真值表 (1) 若a=4,则!a的值为0 (2) 若a=4,b=5,则a && b的值为1 (5) 4 && 0 || 2的值为1 修改后的逻辑运算真值表 a b ! a ! b a && b a || b 非0 1 假
x=!(a>b)&&c>d; (1) 例:a=4; b=6; c=9; x=c<0||a-b; (1) y=!a&&b<c; (0) 例: 3<a<5 在C语言中写为: a>3&&a<5 程序中若将条件3<a<5表示成: 3<a<5会出现问题,分析一下程序段: int a; scanf(“%d”,&a); if (3<a <5) printf("a=%d,3<a<5\n",a); else printf("a=%d,a<3 or a>5\n",a);} 讨论: a=4 及a=2的情况
在逻辑表达式的求解中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符。即在一个复杂的逻辑表达式,有的表达式可能没有被运算到(短路)。 (1)a &&b && c。只有a为真(非0)时,才需要判断b的值。只有当a和b都为真的情况下才需要判别c的值。如果a为假,就不必判别b和c(此时整个表达式已确定为假)。如果a为真,b为假,不判别c。 例:a=9; b=8; c=3;d=0; z=(c=d)&&a>b; (2)a||b||c。只要a为真(非0),就不必判断b和c。只有a为假,才判别b。a和b都为假才判别c。 x=a<b&&(d=c); y=a<b||(c=d);
说明:关系表达式和逻辑表达式的值为0或1,并且在判断一个量是否为“真”时,以0代表“假”,以非0代表“真”。所以可以理解在if语句中表达式可以是任何数值表达式。 (1) if(x!=0)语句1 //表达式是关系表达式 (2) if(x>0 && y>0)语句2 //表达式是逻辑表达式 (3) if(x)语句3 //表达式是变量 (4) if(1)语句4 //表达式是非0整数 (5) if(0)语句4 //表达式是整数0 (6) if(x+3.5)语句4 //表达式是实数表达式
(2) if(‘a’) printf(“%d”,’a’); (3) int a=6; (或:int a; 说明: if后面的表达式类型任意 例: (1) if(3) printf(“OK”); (2) if(‘a’) printf(“%d”,’a’); (3) int a=6; (或:int a; if (a%3) scanf(“%d”,&a);) printf(“$”); else printf(“&”);
条件运算符和条件表达式 有一种if语句,当被判别的表达式的值为“真”或“假” 时,都执行一个赋值语句且向同一个变量赋值 如:if (a>b) max=a; else max=b; 条件运算符 max = (a > b) ? a : b;
条件运算符和条件表达式 有一种if语句,当被判别的表达式的值为“真”或“假” 时,都执行一个赋值语句且向同一个变量赋值 如:if (a>b) max=a; else max=b; max = (a > b) ? a : b; 条件表达式
条件表达式的一般形式为 表达式1?表达式2: 表达式3 条件运算符的执行顺序: 求解表达式1 若为非0(真)则求解表达式2,此时表达式2的值就作为整个条件表达式的值 若表达式1的值为0(假),则求解表达式3,表达式3的值就是整个条件表达式的值
“表达式2”和“表达式3”不仅可以是数值表达式,还可以是赋值表达式或函数表达式。 条件运算符优先于赋值运算符 max=(a>b)?a:b可以写成:max=a>b?a:b 条件运算符的结合方向为“自右至左” a>b?a:c>d?c:d 相当于 a>b?a:(c>d?c:d) 如果a=1,b=2,c=3,d=4,则条件表达式的值等于4 “表达式2”和“表达式3”不仅可以是数值表达式,还可以是赋值表达式或函数表达式。 是赋值表达式: a>b?(a=100) : (b=100) 是函数表达式:a>b?printf(“%d”,a):printf(“%d”,b)
例4.4 输入一个字符,判别它是否大写字母,如果是,将它转换成小写字母;如果不是,不转换。然后输出最后得到的字符。 解题思路:用条件表达式来处理,当字母是大写时,转换成小写字母,否则不转换
#include <stdio.h> int main() { char ch; scanf("%c",&ch); ch=(ch>='A' && ch<='Z ')?(ch+32):ch; printf("%c\n",ch); return 0; } if (ch>= 'A' &&ch<= 'Z') ch=ch+32; else ch=ch; if (ch>= 'A' &&ch<= 'Z') ch=ch+32; else ; if (ch>= 'A' &&ch<= 'Z') ch=ch+32;
选择结构的嵌套 在if语句中又包含一个或多个if语句称为if语句的嵌套 一般形式: else总是与它上面最近的未配对的if配对 if( )
if () 内嵌if { }限定了内嵌if范围 { if () 语句1 } else语句2
例: if (a==b) 修改: if (a==b) if(b==c) printf(“a==b==c”); else } else printf(“a!=b”); 实现if ~ else 正确配对方法:加{ }
例4.5有一函数: 编一程序,输入一个x值,要求输出相应的y值。
解题思路: 用if语句检查x的值,根据x的值决定赋予y的值 由于y的可能值不是两个而是三个,因此不可能只用一个简单的(无内嵌if)的if语句来实现
解题思路:方法1 scanf("%d",&x); if(x<0) y = -1; if(x==0) y = 0; printf("x=%d,y=%d\n",x,y); 解题思路:方法1 (1) 先后用3个独立的if语句处理: 输入x 若 x < 0, 则y =-1 若 x = 0, 则y = 0 若 x > 0, 则y = 1 输出x和y
解题思路:方法2 scanf("%d",&x); if(x<0) y=-1; else if(x==0) y=0; else y=1; printf("x=%d,y=%d\n",x,y); 解题思路:方法2 (2) 用一个嵌套的if语句处理: 输入x 若x < 0, 则y = -1 否则 若 x = 0, 则y = 0 否则 y = 1 输出x和y
提倡内嵌if放在else中 解题思路:方法2 scanf("%d",&x); if(x<0) y=-1; else else y=1; printf("x=%d,y=%d\n",x,y); 提倡内嵌if放在else中 解题思路:方法2 (2) 用一个嵌套的if语句处理: 输入x 若x < 0, 则y = -1 否则 若 x = 0, 则y = 0 否则 y = 1 输出x和y scanf("%d",&x); if (x>=0) if (x>0) y=1; else y=0; else y=-1; printf("x=%d,y=%d\n",x,y);
用switch语句实现多分支选择结构 switch语句用来实现多分支选择结构 学生成绩分类 人口统计分类 按年龄分为老、中、青、少、儿童 85分以上为’A’等 70~84分为’B’等 60~69分为’C’等 …… 人口统计分类 按年龄分为老、中、青、少、儿童
用switch语句实现多分支选择结构 例4.6 要求按照考试成绩的等级输出百分制分数段,A等为85分以上,B等为70~84分,C等为60~69分 ,D等为 60分以下 。成绩的等级由键盘输入。 ‘A’:85---100 ‘B’:70---84 ‘C’:60---69 ‘D’:<60
用switch语句实现多分支选择结构 解题思路: 判断出这是一个多分支选择问题 如果用if语句,至少要用3层嵌套的if,进行3次检查判断 …… if (grade= =‘A’) printf(“85---100 “); else if (grade= =‘B’) printf(“70---84 “); else if (grade= =‘C’) printf(“60---69“); else if (grade= =‘D’) printf(“<60“); else printf(“error“); 如果分支较多,则嵌套的if语句层数多,程序冗长而且可读性降低,C语言提供switch语句直接处理多分支选择。
#include <stdio.h> int main() { char grade; scanf("%c",&grade); printf("Your score:"); switch(grade) { case 'A': printf("85~100\n");break; case 'B': printf("70~84\n");break; case 'C': printf("60~69\n");break; case 'D': printf("<60\n");break; default: printf("enter data error!\n"); } return 0; 值为A
执行过程: switch 表达式 语句组1 语句组2 语句组n 语句组 …... E 1 E 2 En default case
说明: (1)switch后面括号内的“表达式”,其值的类型应为整数类型(包括字符型)。 (2)当表达式的值与某一个case后面的常量表达式的值相等时,就执行此case后面的语句,若所有的case中常量表达式的值都没有与表达式的值匹配的,就执行default后面的语句。 (3)“case 常量表达式”只是起语句标号作用,必须用 break跳出 (4) E1,E2,…En是常量表达式,且值必须互不相同;否则就会出现互相矛盾的现象。 (5)各个case和default的出现次序不影响执行结果。 (6)case后可包含多个可执行语句,且不必加{ } (7)多个case可共用一组执行语句 (8) switch可嵌套
switch语句的作用是根据表达式的值,使流程跳转到不同的语句 switch语句的一般形式: { case 常量1 :语句1 case 常量2 :语句2 ┇ ┇ ┇ case 常量n :语句n default : 语句n+1 } 整数类型(包括字符型)
switch语句的作用是根据表达式的值,使流程跳转到不同的语句 switch语句的一般形式: { case 常量1 :语句1 case 常量2 :语句2 ┇ ┇ ┇ case 常量n :语句n default : 语句n+1 } 不能相同
scanf("%c",&grade); printf("Your score:"); switch(grade) { case 'A': printf("85~100\n");break; case 'B': printf("70~84\n");break; case 'C': printf("60~69\n");break; case 'D': printf("<60\n");break; default: printf("enter data error!\n"); }
scanf("%c",&grade); printf("Your score:"); switch(grade) { case 'A': case 'B': case 'C': printf(“>60\n");break; case 'D': printf("<60\n");break; default: printf("enter data error!\n"); }
例 #include <stdio.h> int main() { int x=1,y=0,a=0,b=0; switch(x) { case 1: switch(y) { case 0: a++; break; case 1: b++; break; } case 2: a++;b++; break; case 3: a++;b++; printf(“\na=%d,b=%d”,a,b); return 0; 运行结果:a=2,b=1
例4.7 编写程序,用switch语句处理菜单命令。 解题思路:在许多应用程序中,用菜单对流程进行控制,例如从键盘输入一个’A’或’a’字符,就会执行A操作,输入一个’B’或’b’字符,就会执行B操作,等等。
#include <stdio.h> int main() { void action1(int,int),action2(int,int); char ch; int a=15,b=23; ch=getchar(); switch(ch) { case 'a': case 'A': action1(a,b);break; case 'b': case 'B': action2(a,b);break; default: putchar('\a'); } return 0; void action1(int x,int y) { printf("x+y=%d\n",x+y); } 输入a或A 调用action1函数,执行A操作
#include <stdio.h> int main() { void action1(int,int),action2(int,int); char ch; int a=15,b=23; ch=getchar(); switch(ch) { case 'a': case 'A': action1(a,b);break; case 'b': case 'B': action2(a,b);break; default: putchar('\a'); } return 0; void action2(int x,int y) { printf("x*y=%d\n",x*y); } 输入b或B 调用action2函数,执行B操作
#include <stdio.h> int main() { void action1(int,int),action2(int,int); char ch; int a=15,b=23; ch=getchar(); switch(ch) { case 'a': case ‘A’: action1(a,b);break; case 'b': case ‘B’: action2(a,b);break; default: putchar(‘\a’); } return 0; 输入其他字符 发出警告
可以按以上思路编写程序,把各action函数设计成不同的功能以实现各要求 这是一个非常简单的示意程序 实际应用中,所指定的操作可能比较复杂: A:输入全班学生各门课的成绩 B:计算并输出每个学生各门课的平均成绩 C:计算并输出各门课的全班平均成绩 D:对全班学生的平均成绩由高到低排序并输出 可以按以上思路编写程序,把各action函数设计成不同的功能以实现各要求
选择结构程序综合举例 例4.8 写一程序,判断某一年是否闰年。 解题思路: 闰年的条件是符合下面二者之一: ①能被4整除,但不能被100整除,如2008 ②能被400整除,如2000
用变量leap代表是否闰年的信息。若闰年,令leap=1;非闰年,leap=0。最后判断leap是否为1(真),若是,则输出“闰年”信息
#include <stdio.h> int main() {int year,leap; printf("enter year:"); scanf("%d",&year); if (year%4==0) if(year%100==0) if(year%400==0) leap=1; else leap=0; else leap=1; if (leap) printf("%d is ",year); else printf("%d is not ",year); printf("a leap year.\n"); return 0; } 标志变量 与if (leap!=0)含义相同
#include <stdio.h> int main() {int year,leap; printf("enter year:"); scanf("%d",&year); if (year%4==0) if(year%100==0) if(year%400==0) leap=1; else leap=0; else leap=1; if (leap) printf("%d is ",year); else printf("%d is not ",year); printf("a leap year.\n"); return 0; } if(year%4!=0) leap=0; else if (year%100!=0) leap=1; else if(year%400!=0) leap=0; else leap=1;
#include <stdio.h> int main() {int year,leap; printf("enter year:"); scanf("%d",&year); if (year%4==0) if(year%100==0) if(year%400==0) leap=1; else leap=0; else leap=1; if (leap) printf("%d is ",year); else printf("%d is not ",year); printf("a leap year.\n"); return 0; } if((year%4==0 && year%100!=0) || (year%400==0)) leap=1; else leap=0;
标准如下: 例4.10 运输公司对用户计算运输费用。路程(s km)越远,每吨·千米运费越低。 s < 250 没有折扣
解题思路: 设每吨每千米货物的基本运费为p,货物重为w,距离为s,折扣为d 总运费f的计算公式为f=p×w×s×(1-d)
折扣的变化规律(参见教材图4.15): 折扣的“变化点”都是250的倍数 在横轴上加一种坐标c,c的值为s/250 c代表250的倍数 1≤c<2时,表示250≤s<500,折扣d=2% 2≤c<4时,d=5%;4≤c<8时,d=8%; 8≤c<12时,d=10%;c≥12时,d=15%
#include <stdio.h> int main() { int c,s; float p,w,d,f; printf("please enter price,weight,discount:"); scanf("%f,%f,%d",&p,&w,&s); if(s>=3000) c=12; else c=s/250; 输入单价、重量、距离
switch(c) { case 0: d=0; break; case 1: d=2; break; case 2: case 3: d=5; break; case 4: case 5: case 6: case 7: d=8; break; case 8: case 9: case 10: case 11: d=10; break; case 12: d=15; break; }
f = p * w * s * (1 - d / 100); printf(“freight=%10.2f\n”,f); return 0; }