第 5章 选择结构程序设计主要内容,关系运算符和关系表达式逻辑运算符和逻辑表达式
if - else(重点、难点)
switch
条件运算符和条件表达式 (了解 )
根据选择结构的组成特点,我们在分析问题时着重明确以下两点:
1)条件是什 么。
2)条件成立和不成立时分别执行什么操作。
简单条件用关系表达式来表示
例 5.1 判断一个整数 n是奇数还是偶数(设 n
由用户输入)
分析:第一步,输入整数 n。第二步,判断:
若条件,n%2等于 0“成立,则输出,n为偶数“;否则输出,n为奇数“。
5.1关系运算符和关系表达式
main()
{ int n;
printf(“\n enter int n:”);
scanf(“%d”,&n);
if( n%2==0)
printf(“\n %d is even number“,n);
else
printf(“\n %d is odd number”,n);}
开始输入 n
n%2为 0
是偶数 是奇数结束输入
例 5.2输入任一考生的考号及成绩,判断其是否能上大学。
(设分数线为 600,若能上,则输出,success“,否则输出” failure”)。
分析:第二步是选择结构,条件是,score大于等于 600”,
main()
{ int no;
float score;
printf(“\n enter no,score:”);
scanf(“%d%f”,&no,&score);
if( score>=600)
printf(“\n %d,success”,no);
else
printf(“\n %d,failure.”,no);
}
关系表达式的值,若条件满足,则关系表达式的值为 ture( 1);
否则,关系表达式的值为 false(0)。
1.关系运算符,
< <= > >= == !=
例如下列关系表达式,
a>b 表示条件,a 大于 b“,
x! =0 表示条件,x 等于 0“,
a+b<x*y 表示条件,a+b 小于 x*y“。
2,优先级算术运算符 > 关系运算符 > 赋值运算符且 < <= > >= 高于 == !=
3,结合性,自左向右(一般很少连用)。
如,a>b<c 表示 (a>b)<c
f=a<g+1 表示 f=(a<(g+1) )
特别提示:关系运算符,==”与赋值运算符,=”
不同。
比较,k=1 与 k==1
特别提示:表达式 a+b>d>c也是合法的关系表达式,但在实际应用中很少使用;因为它不能表示:
a+b大于 c且大于 d。
问题,
如何表示,a < x < b
0<y<10 等条件
5.2 逻辑运算符和逻辑表达式
复杂条件可用逻辑表达式来描述
例 5.3 判断当前温度是否满足观赏鱼正常生活需要的温度
( 15~20摄氏度)。(设当前温度由用户输入)。
main()
{ int temperature;
printf(“\n enter the temperature,”);
scanf(“%d”,&temperature);
if(temperature>=15 &&temperature<=20) /*条件 */
printf(“\n normal,”);
else
printf((“\n not normal.”);
}
1,逻辑运算符
&& || !
(其含义分别是,and与,or 或,negative 非)
逻辑运算规则 (见 P89)
由表可得逻辑运算的规律:
(1)任何值与 0相与,结果为 0
( 2)任何值与 1相或,结果为 1
( 3)非运算将“非 0值”变为 0,将 0变为 1
如,int x=0,y=5 ; 则 !x->1,!y->0
x&&y -> 0 x || y ->1
特别提示,if( !x ) 等价于 if( x==0)
2,逻辑表达式,由逻辑运算符将一个或多个表达式连接起来的式子。比如:
1)"a和 b中只有一个为 0"的逻辑表达式为:
a+b!=0&&a*b==0
2)某英语专业的招生条件“总分 (total )超过分数线
(600)并且英语成绩( score)不低于 85分“,该条件的逻辑表达式为:
total>600&&score>=85
3)判断某年是润年应满足以下两个条件之一:该年能被 4整除但不能被 100整除,或该年能被 400整除。
该条件对应的逻辑表达式为:
year%4==0&&year%100!=0 || year%400==0
3,逻辑运算符的优先级和结合性当条件表达式中同时出现多个运算符时,首先按优先级计算,当同时出现多个优先级相同的运算符时,再按结合性计算。
优先级:
! >算术运算符 >关系运算符 >&& >|| >赋值运算符结合性:
逻辑与 &&、逻辑或 ||的结合性,自左向右,
逻辑非 ! 的结合性,自右向左例如,(下页)
优先级与结合性举例
例如,设 int h=3,j=3,k=3;
double x=0,y=2.3;
计算下列表达式的值:
① h&& j && k 等价于 (h&& j) && k
② h<j &&x<y 等价于 ( h<j) &&(x<y)
③ h<k || x<y 等价于 ( h<k) || (x<y)
④ x!=y && j+1==!k+4
等价于 (x!=y) &&(( j+1)==((!k)+4 ))
结果,1,0,1,1
逻辑表达式计算特例
在逻辑表达式的计算过程中,当该表达式的值能够确定时,就停止该表达式的计算,即并不是表达式中所有的运算符都被执行。
例 5.4:
1) 设有如下定义:
int a=1,b=2,c=3,d=4,m=2,n=2;
则执行表达式,(m=a>b) && (n=c>d) 后,n的值为
()。 A,1 B,0 C,2 D.3
2)当 c 的值不为 0时,在下列选项中能正确将 c的值赋给变量 a,b的是()
A,c=b=a; B,(a=c)||(b=c); C,(a=c)&&(b=c); D,
a=c=b;
5.3 if 语句
if语句能实现所有的选择结构
例 5.5 将任意两个整数 m,n中的较大数送给 x,较小数送给 y,然后按大小顺序输出 (设 m,n的值由键盘输入)
分析:共分三步,
S1,输入两个整数给 m和 n。
S2,判断 m,n的大小并分别给 x和 y 赋值。
S3,输出 x和 y。
其中第二步用选择结构,
main()
{ int m,n,x,y;
printf(“\n please enter two integers:” );
scanf(“%d%d”,&m,&n);
if(m>n) {x=m; y=n; } /*复合语句 */
else
{x=n; y=m;}
printf(“\n x=%d,y=%d”,x,y);
}
思考:若条件改为,m<n,如何实现?
1,If语句的一般形式:
if( 表达式 )
语句 1
else
语句 2
执行过程,(如右图 )
格式说明,语句 1 和 语句 2 在语法上是一个语句,可以是简单语句,也可以是复合语句。在此要特别注意复合语句中一对 { }的正确使用 。
条件表达式语句 1 语句 2
Y N
2,if 语句的简化形式
例 5.6 从键盘接收一个字符,若为大写字母,则将其转换成小写字母并输出;否则输出原字符。
分析:共三步,其中第二步判断 ch是大写字母的条件是,ch
在 A~Z之间
#include <stdio.h>
main()
{ char ch;
printf(“\n enter a character:”); /*第一步,输入 ch */
ch=getchar(); getchar();
if( ch>=’A’ && ch<=’Z’) /*第二步,判断并处理 */
ch=ch+32; /*32:大小写字母的 ASCII码之差为 32*/
putchar(ch); /*第三步,输出 */
}
2,if语句的简化形式
if(expression)
statement1
执行过程如图:
例:输入任意数 n,
输出其绝对值。
main()
{ float a;
scanf(“%f”,&a);
if(a<0) a=-a;
printf(“\n |a| is:%f,,a);
}
条件表达式语句 1
Y N
3,if语句的嵌套
当 if语句中的语句 1或语句 2又是 if语句时,就构成了 if语句的嵌套,嵌套的 if语句能实现多分支结构。
例 5.7 猜数游戏:假设 m是一个整型数 15,让用户从键盘上输入所猜数字(用户已知数的范围是 10~20),若猜对,则输出
,RIGHT”,否则,输出” WRONG“,并指出所猜的数比 m大还是小。
分析,共 3个分支第一步,输入猜测的数 n。
第二步,判断并输出结果:条件可以是,m等于 n”,若条件成立,
则输出 RIGHT;否则,需执行两步操作:①输出 WRONG,
②判断 m,n的大小:条件可以是,n>m”;条件成立时输出
,big”;否则输出,small”。
很明显,②又是一个选择结构 。
main()
{ int m=15,n;
printf("\n guess a num:");
scanf("%d",&n); /
if( m= =n)
printf(" RIGHT"); /*语句 1*/
else
{printf("\n WRONG");
if( n>m)
printf(" BIG"); /*语句 2*/
else
printf(" SMALL");
}
}
例 5.8某幼儿园只接收 2~6岁的小孩,其中 2~3岁编入小班,4~5岁编入中班,6岁编入大班。编程实现,对输入的任意一个年龄,输出该编入什麽班,
或者告知“不收“。
分析:首先根据条件,年龄在 2~6岁之间,判断是“收”还是“不收“,若条件满足,则执行的操作为:( 1)判断该编入何班;否则,输出
“不收”。
其次,分析( 1)如何实现。
提示:本例可用不同的程序实现。
如将条件改为“年龄超出 2~6岁”;或者从条件
“年龄小于 2”开始判断。试编程实现。
main()
{ int age;
printf(“\n enter age:”);
scanf(“%d”,&age);
if(age>=2&&age<=6)
if(age<=3) /*语句 1开始 */
printf(“\n small class”); /*语句 1_1*/
else
if(age<=5) /*语句 1_2*/
printf(“\n middle class”);
else
printf(“\n big class”); /*语句 1结束 */
else
printf(“\n can not accept”); /*语句 2*/
}
If语句中的语句 1和语句 2都可以包含 if语句。
If语句的嵌套结构中,因为 else 是可选项,所以要注意 if与 else的匹配。
C语言规定:
else总是与其前面最近的、还没有匹配过的 if相匹配,并且是由里向外逐对对匹配。 编程时,可以通过合理使用 { }来明确 if与 else匹配关系。
例 5.10:分析以下两个程序,哪一个能实现:从键盘上接收一个整数,若该数为正偶数,则输出,positive and even.”;若为负数,则输出,negative”。
程序( 1):
main()
{ int n;
printf(“\n enter a integer:”);
scanf(“%d”,&n);
if(n>0)
if(n%2==0)
printf(“positive and even.\n”);
else
printf(“negative\n”);
}
画出该程序的流程图,程序结构更清楚。
例 5.10程序( 2):
main()
{ int n;
printf(“\n enter a integer:”);
scanf(“%d”,&n);
if(n>0)
{if(n%2==0)
printf(“positive and even.\n”);
}
else
printf(“negative\n”);
}
4.条件运算符
使用 if语句时,有时是为了根据条件给同一个变量赋不同的值,比如:
main()
{ int x,y;
scanf(“%d”,&x);
if(x>0) y=x+1;
else y=x*x+1;
printf(“\n x=%d,y=%d”,x,y);
}
本例中,当条件满足或不满足时分别执行一个赋值语句,
且都是给变量 y 赋值。用 C语言提供的条件运算符描述,
比用 if语句更简练。上述 if语句等价于:
y= x>0? x+1,x*x+1;
其中,x>0? x+1,x*x+1”是一个“条件表达式”,
条件运算符,?,
条件表达式的一般格式:
表达式 1?表达式 2,表达式 3
计算过程,
首先计算表达式 1;若其值为真(非 0),则计算表达式 2,
取表达式 2的值作为整个条件表达式的值;否则,计算表达式 3,取表达式 3的值作为整个条件表达式的值。
优先级,条件运算符的优先级比关系运算符和算术运算符都低,比赋值运算符高。
例如,y=x>0?x+1:x*x+1 等价于
y=(( x>0)?( x+1),( x*x+1) )
说明:并不是所有的 if语句都能用条件表达式实现。如
if(n>0) a=6;
else b=8;
5.4 switch语句
switch语句可用来处理 一部分特殊的多分支选择结构 。即根据某个表达式的值进行选择,而不能根据表达式的取值范围作出选择,所以使用时有很大的局限性。,
如学生成绩等级分类,幼儿园分班等。
若用 if语句实现,程序冗长,嵌套层次多,结构不够清晰。而用 switch语句则更清楚。
例 5.12输入某个成绩等级,输出该等级对应的分数段。
( A:90~100,B:80~89,C:70~79,D:60~70,E:60以下)
#include <stdio.h> /*例 5.12*/
main()
{ char grade;
printf("\n enter score grade(a~e):"); /*输出提示信息 */
grade=getchar(); getchar(); /*接收输入的一个字符 */
switch(grade)
{ case 'a',printf("\n 90~100"); /*case后是一常量 */
break; /*多个语句组成的语句段
1*/
case 'b',printf("\n 80~89"); break;
case 'c',printf(“\n 70~79”); break; /*case后有空格 */
case 'd',printf("\n 60~69."); break;
case 'e',printf("\n <60"); break;
default,printf("\n error:out of the field(a~e).");
} /*switch 语句结束 */
}
switch 语句的一般形式为,
switch(expression)
{ case 常量表达式 1,语句段 1
[break;]
case 常量表达式 2:语句段 2
[break;]

case 常量表达式 N,语句段 N
[break;]
[default,语句段 N+1]
} (格式说明 )
switch语句的执行过程,
①计算 switch 后面括号中的表达式。
② 将表达式的值与第一个 case后的常量表达式的值比较,
若相等,则从语句段 1开始,执行语句段 1及其以后的所有语句,不再进行判断 (即执行完语句段 1后,
接着执行后面的 case或 default语句中的语句段 ),
直至遇到 break语句或执行至 switch 语句的末尾;
若不相等,再与第二个 case 后的常量表达式比较,
依此类推;若所有的 case均不匹配,则执行 default
后的语句段 n+1。
main() /*幼儿园编班问题 */
{ int age;
printf("\n enter child's age:");
scanf("%d",&age);
switch(age)
{ case 2,
case 3,printf(“\n small class”); /*当 age 为 2或 3时 */
break; /*跳出 switch语句 */
case 4:
case 5,printf("\n middle class."); break;
case 6,printf("\n big class."); break;
default:printf("\n can't accept.");
}
} /*实现多个 case分支共用一个语句段 。 */
例 5.14输入任一百分之成绩,输出其对应的成绩等级,A(90~100),B(80~89),C( 70~79),
D(60~69),E(<60)。
分析:因为 case后必须是一常量,所以要用
switch语句实现,必须先找出各个分数段对应的常量。很容易可看出,除 100分,60分以下的分数外,其它分数段内的分数除以 10取整结果相同。
main() / *例 5.14*/
{ int score,n;
printf("\n enter a score(0~100):");
scanf("%d",&score);
if(score<=100) n=score/10; else n=11;
if(n<6) n=5; /*当 n<6时,说明 score<60,令 n=5*/
switch(n)
{ case 10,/*当 score为 100时,n的值为 10*/
case 9,printf(“\nA”); break; / *n为 9或 10时共用该语句段 */
case 8,printf("\nB"); break;
case 7,printf("\nC"); break;
case 6,printf("\nD"); break;
case 5,printf("\nE"); break;
default:printf("\n enter error."); }
}
思考:如果将分数段的划分改为,A(100~85),
B(70~84),C(60~69),D(<60),用 switch 语句实现是否合适?
特别说明,并不是所有的多分支结构都可用
switch 语句实现,只有当各个分支能分别与某个常量对应时,才适合采用 switch语句。
上机调试
一、习题 第一部分
5、下面程序的执行结果是:
main()
{ int x=-1,y=3,k;
k=(x++<=0)&&(!(y--<=0));
printf(“\n %d,%d,%d”,k,x,y);
}
提示:注意逻辑表达式的计算过程,特别是
x++,y—的计算。
5.5上机调试二.测试用例的设计
调试选择结构程序时,所用的测试用例至少必须保证所有的分支都能执行一遍。也就是说,测试用例应该能使各个基本条件都有成立和不成立的机会。否则,即使程序由是能运行,也不能保证整个程序是正确的。
例 5.5.1邮局对包裹邮费规定如下:重量
(千克)不超过 10,收费标准为 0.80元 /千克;
不超过 20,收费标准为 0.75元 /千克;不超过
30,收费标准为 0.70元 /千克;超过 30千克不予邮寄。另对每件包裹收手续费 0.2元。
main()
{ float weight,r,money;
printf("\n enter weight:");
scanf("%f",&weight);
if(weight>30) r=-1; /*用 -1标记不予邮寄 */
else if(weight>20) r=0.70; /*r保存实际邮寄费率 */
else if(weight>10) r=0.75;
else r=0.8;
if(r!=-1)
{ money=r*weight+0.2;
printf("\n weight:%f,money:%f",weight,money);
} else printf("\n can't post.");
}
分析该程序,共有 4个分支,分别对应 weight的取值为:
>30,>20且 <=30,>10且 <=20,<=10; 因此若要实的每个分支都能执行一遍,weight应分别从上述每一范围中至少取一个值。
考虑到 边界容易出错,所以 weight应分别取 10,20,30作为测试数据,或直接将 30,20 10作为后 3个范围中的测试数据。
测试用例:
35,30,20,10(至少 4个测试数据)
或者使用,35,25,15,5,30,20,10(每个范围取一个测试数据,在加上边界数据供 7组)。
5.5 上机调试三、单步执行( run/step或 F7或 F8)
具体方法是:根据某个测试用例,若程序的运行结果不正确,则采用单步执行方式,利用原来的测试数据,重新运行该程序,根据亮条光标的移动,可以很清楚的看到程序的执行过程,
然后与该程序要实现的任务比较,很容易找出程序中哪儿与实际不符。
同时使用 break/watch 可添加表达式,利用单步执行观察 watch窗口中该表达式或变量的值,
则更容易找出是哪一步出错了。
比如:上例的执行。
作业
2,习题 5,8,10,12