判断(选择结构)
1. 做判断
还记得学习笔记(二)第1节中,我们介绍表达式的时候引入的计算时间差的小例子:
eg:输入两个时间,每个时间分别输入小时和分钟的值,然后输出两个时间之间的差,也以几小时几分表示。
如果直接分钟减分钟,小时减小时,会出现分钟借位的情况:1:40和2:10分的差???
思路:就用分别减的方案,减完后看看有没有借位,如果出现借位,小时数减1
,分钟数加60
。
代码如下:
# include "stdio.h"
int main(){
int hour1, min1;
int hour2, min2;
scanf("%d %d", &hour1, &min1);
scanf("%d %d", &hour2, &min2);
int h = hour2 - hour1;
int m = min2 - min1;
if (m < 0)
{
m = m + 60;
h--;
}
printf("时间差是%d小时%d分。\n", h, m);
return 0;
}
2. 判断的条件
首先,我们需要了解什么是关系运算:
计算两个值之间的关系,所以叫做关系运算。C语言中的关系运算符(也叫比较运算符)如下:
运算符 | 意义 |
---|---|
== | 相等 |
!= | 不相等 |
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
注:
- 关系运算符的结果只有两个值:
0
和1
。当两个值的关系符合关系运算符的预期时,关系运算的结果为整数1
,否则为整数0
。
eg:printf("%d\n", 5 == 3);
输出结果为0
printf("%d\n", 5 > 3);
输出结果为1
- 关系运算符的优先级比算术运算的低,但是比赋值运算的高。
- 判断是否相等的
==
和!=
的优先级比其他的低,而连续的关系运算是从左到右进行的。
eg:5 > 3 == 6 > 4
先判断5 > 3
结果为1
,再判断6 > 4
结果为1
,最后判断1 == 1
结果为1
,所以该表达式的结果为1
。
eg:6 > 5 > 4
先判断6 > 5
结果为1
,再判断1 > 4
结果为0
,所以该表达式的结果为0
。
下面通过一个例子更深刻的理解选择结构:
找零计算器需要用户做两个操作:输入购买的金额,输入支付的票面,而找零计算器则根据用户的输入做出相应的动作:计算并打印找零,或告知用户余额不足以购买。
思路:从计算机程序的角度看,这就是意味着程序需要读用户的两个输入,然后进行一些计算和判断,最后输出结果。流程图如下:
代码如下(此处代码有点小问题,下节会再讲):
#include "stdio.h"
int main(){
// 初始化
int price = 0;
int bill = 0;
// 读入金额和票面
printf("请您输入金额及票面:");
scanf("%d %d", &price, &bill);
// 计算找零
if (bill >= price)
{
printf("找零%d元。", bill - price);
}
printf("您的余额不足,请重新支付!");
return 0;
}
上面代码中以两个斜杠“//”开头的语句就是注释,插入在程序代码中,用来向读者提供解释信息。它对于程序的功能没有任何影响,但是往往能使得程序更容易被人类读者理解。
延续数行的注释,要用多行注释的格式来写。多行注释由一对字符序列“/*”开始,而以“*/"结束,这种形式也可用于一行内的注释。
eg:int ak = 47 /*36*/, y = 9;
3. 否则的话
上面找零的例子代码其实是有问题的,因为无论你给的钱够不够都会输出"您的余额不足,请重新支付!"
。这样给人的体验感很不好,有没有什么方法能够让程序在满足条件时做一件事,在不满足条件时做另一件事呢?
else
:否则的话
找零代码更改如下:
#include "stdio.h"
int main(){
// 初始化
int price = 0;
int bill = 0;
// 读入金额和票面
printf("请您输入金额及票面:");
scanf("%d %d", &price, &bill);
// 计算找零
if (bill - price >= 0)
{
printf("找零%d元。", bill - price);
} else{
printf("您的余额不足,请重新支付!");
}
return 0;
}
下面我们再看一个例子:
比较两个数的大小。
#include "stdio.h"
int main(){
int a, b;
printf("请输入两个整数:");
scanf("%d %d", &a, &b);
int max = 0;
if (a > b)
{
max = a;
}
printf("大的那个数是:%d", max);
return 0;
}
上面的程序有什么问题???
它没有解决b
大于a
的问题,当a > b
的条件不成立时,程序就结束了,max
没有得到值。
解决方案1:
#include "stdio.h"
int main(){
int a, b;
printf("请输入两个整数:");
scanf("%d %d", &a, &b);
int max = 0;
if (a > b)
{
max = a;
}
if (b > a)
{
max = b;
}
printf("大的那个数是:%d", max);
return 0;
}
解决方案2:
#include "stdio.h"
int main(){
int a, b;
printf("请输入两个整数:");
scanf("%d %d", &a, &b);
int max = 0;
if (a > b)
{
max = a;
}else{
max = b;
}
printf("大的那个数是:%d", max);
return 0;
}
解决方案3:
#include "stdio.h"
int main(){
int a, b;
printf("请输入两个整数:");
scanf("%d %d", &a, &b);
int max = b;
if (a > b)
{
max = a;
}
printf("大的那个数是:%d", max);
return 0;
}
上述3种方案各有优劣,方案1,做了两次判断,比较麻烦,方案二通俗易懂,方案3只做了一次判断,但不如前两种方案好理解。
4. if语句再探
一个基本的if
语句由一个关键字if
开头,跟上在括号里的一个表示条件的逻辑表达式,然后是一对大括号{}
之间的若干条语句。如果表示条件的逻辑表达式的结果不是零,那么就执行后面跟着的这对大括号中的语句,否则就跳过这些语句不执行,而继续下面的其他语句。
if
语句也可不加大括号{}
,如:
if (total > amount)
total += amount + 10;
if
语句这一行结束的时候并没有表示语句结束的;
,而后面的赋值语句写在if
的下一行,并且缩进了,在这一行结束的时候有一个表示语句结束的;
。这表明这条赋值语句是if
语句的一部分,if
语句拥有和控制这条赋值语句,决定它是否要被执行。else
同理。
注:
if
语句有没有{}
的结果可能会不一样,强烈建议后面始终加{}
,防止出现错误!!!
5. 嵌套的if-else
在上面第3节中举了两个数比较大小的例子,用到了一个if-else结构:
#include "stdio.h"
int main(){
int a, b;
printf("请输入两个整数:");
scanf("%d %d", &a, &b);
int max = 0;
if (a > b)
{
max = a;
}else{
max = b;
}
printf("大的那个数是:%d", max);
return 0;
}
如果现在要求输入三个整数,输出其中最大的,应该怎么做?
具体思路如下:
具体代码如下:
#include "stdio.h"
int main(){
int a, b, c;
int max = 0;
printf("请输入三个整数:");
scanf("%d %d %d", &a, &b, &c);
if (a > b)
{
if (a > c)
{
max = a;
}else{
max = c;
}
}else{
if (b > c)
{
max = b;
}else{
max = c;
}
}
printf("最大的整数是:%d", max);
return 0;
}
当if
的条件满足或者不满足的时候要执行的语句也可以是一条if
或if-else
语句,这就是嵌套的if
语句。
注:在if或else后面总是用{},即使只有一条语句的时候。
6. 级联的if-else if
分段函数在数学中十分常见,现有如下分段函数:
f
(
x
)
=
{
−
1
;
x
<
0
0
;
x
=
0
2
x
;
x
>
0
f(x) = \left\{\begin{matrix} -1; & x<0\\ 0; & x=0 \\ 2x;& x>0 \end{matrix}\right.
f(x)=⎩⎨⎧−1;0;2x;x<0x=0x>0
如何用程序实现输入输出呢?
#include "stdio.h"
int main(){
int x, f;
scanf("%d", &x);
if (x < 0)
{
f = -1;
}
else if (x == 0)
{
f = 0;
}
else
{
f = 2 * x;
}
printf("f(%d)=%d", x, f);
return 0;
}
上面程序中就包含级联的if-else if
if (exp1){
stl1;
}
else if (exp2){
stl2;
}
else{
stl3;
}
另外,分段函数的代码不建议写成如下形式:
#include "stdio.h"
int main(){
int x;
scanf("%d", &x);
if (x < 0)
{
printf("%d", -1);
}
else if (x == 0)
{
printf("%d", 0);
}
else
{
printf("%d", 2 * x);
}
return 0;
}
该形式不是单一出口,每次形式固定,不具有灵活性!
7. 多路分支(switch-case)
我们需要在一些时候,当一个变量等于这个值时,做什么事情,等于另外一个值时,又做什么事情,我们可以用级联的if-else if去完成,如下例子所示:
#include "stdio.h"
int main(){
int type;
scanf("%d", &type);
if (type == 1)
{
printf("你好!");
}
else if (type == 2)
{
printf("早上好!");
}
else if (type == 3)
{
printf("晚上好!");
}
else if (type == 4)
{
printf("再见!");
}
else
{
printf("啊,什么啊?");
}
return 0;
}
这样的代码结构不是太好,如果运气好,type=1
,直接运行第一个判断,如果运气不好,不等于1
2
3
4
中的任何一个,就要逐一比较每个if
里面的条件,每个都比较过后,执行最后一个else
中的语句。
有没有什么方法能改变这种情况呢?请看下面的代码:
#include "stdio.h"
int main(){
int type;
scanf("%d", &type);
switch (type)
{
case 1:
printf("您好!");
break;
case 2:
printf("早上好!");
break;
case 3:
printf("晚上好!");
break;
case 4:
printf("再见!");
break;
default:
printf("啊,什么啊?");
break;
}
return 0;
}
上述代码就是switch-case
的用法,type
等于几就执行相应的case
里面的语句,而不需要像级联if-else if那样逐个比对判断条件。
注:
- 千万不要忘记每个
case
里面的break;
语句,忘记了代码就会执行到下一个case
中的语句,直到遇到break;
或者return 0;
!!!switch
后面跟的控制表达式只能是整数型的结果,否则会报错!
case
后面跟的常量可以是常数,也可以是常数计算的表达式。switch
语句可以看作是一种基于计算的跳转,计算控制表达式的值后,程序会跳转到相匹配的case
(分支标号)处。分支标号只是说明switch
内部位置的路标,在执行完分支中的最后一条语句后,如果后面没有break
,就会顺序执行到下面的case
里去,直到遇到一个break
,或者switch
结束为止。所以case并不是划分一段一段的标志,case
只是一个入口,case
不能阻值句子继续往下执行,只有break
可以。
下面举个例子巩固一下:
本题要求编写程序将一个百分制成绩转换为五分制成绩。转换规则:
- 大于等于90分为A;
- 小于90且大于等于80为B;
- 小于80且大于等于70为C;
- 小于70且大于等于60为D;
- 小于60为E。
代码如下:
#include "stdio.h"
int main(){
int grade;
scanf("%d", &grade);
grade /= 10;
switch (grade)
{
case 10:
case 9:
printf("A\n");
break;
case 8:
printf("B\n");
break;
case 7:
printf("C\n");
break;
case 6:
printf("D\n");
break;
default:
printf("F\n");
break;
}
return 0;
}
上述代码不符合之前所说的“单一出口”原则,后续学过字符串处理后再做优化。