第四章 选择结构程序设计

5/28/2022 C语言

讲师介绍:软件工程师,阿里云技术专家,《智能前端技术与实践》作者

考试科目:883 《C程序设计》(第五版)谭浩强,清华大学出版社

参考资料:《C程序设计(第五版)》谭浩强

# 前言

顺序结构:各语句按照自上而下的顺序执行,执行完上一个语句就自动执行下一个语句,是无条件的,不必做任何判断。

在很多实际情况中,需要根据某个条件是否满足来决定是否执行指定的操作任务,或者从给定的两种或多种操作选择其一。

# 4.1 选择结构和条件判断

由于程序处理问题的需要,在大多数程序中都包含选择结构,需要在进行下一个操作之前先进行判断。

C语言有两种选择语句:

  • if语句:用来实现两个分支的选择结构;
  • switch语句:用来实现多分支的选择结构;

例4.1 求ax2+bx+c=0方程的根,a,b,c由键盘输入。

思路:(1) 根据方程系数判断方程根的个数;(2) 求根公式

#include<stdio.h>
#include<math.h>
int main(){
    float a,b,c,disc,p,q,x1,x2;
    printf("请输入a,b,c的值:");
    scanf("%f %f %f",&a,&b,&c);
    disc = b * b -4*a*c;
    if(disc>0){
        p = -b/(2.0*a);
        q = sqrt(disc)/(2.0*a);
        x1 = p+q;
        x2 = p-q;
        printf("x1=%.2f\nx2=%.2f\n",x1,x2);
    }else{
        printf("该方程没有根,请重新输入系数!\n");
    }
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 4.2 用if语句实现选择结构

# 4.2.1 用if语句实现选择结构

两个变量值互换必须借助第三个变量,可以这样考虑:将AB两个杯子中的水互换,用两个杯子的水倒来倒去的办法是无法实现的,必须借助于第3个杯子C,先把A杯的水倒在C中,再把B杯中的水倒在A中,最后把C杯的水倒在B中,这就实现了两个杯子中的水互换。

例4.2 输入两个实数,按代数值由小到大的顺序输出这两个数。

#include<stdio.h>
int main(){
    float a,b,t;
    printf("请任意输入两个数字:");
    scanf("%f %f",&a,&b);
    if(a>b){
        t = a;
        a = b;
        b = t;
    }
    printf("所输入的两个数字由小到大的顺序为:%.1f、%.1f\n",a,b);
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13

例4.3 输入3个数a,b,c,要求按由小到大的顺序输出。

#include<stdio.h>
#include<math.h>
int main(){
    float a,b,c,t;
    printf("请输入a、b、c三个数字:");
    scanf("%f %f %f",&a,&b,&c);
    if(a>b){
        t = a;
        a = b;
        b = t;
    }
    if(a>c){
        t = a;
        a = c;
        c = t;
    }
    if(b>c){
        t = b;
        b = c;
        c = t;
    }
    printf("所输入的三个数字有小到大的顺序为:%.1f、%.1f、%.1f\n",a,b,c);
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 4.2.2 if语句的一般形式

if语句的一般形式如下:

if(表达式) 语句1

	 [else 语句2]
1
2
3

if语句中的表达式可以是关系表达式、逻辑表达式、数值表达式。

在上面if语句的一般形式中,方括号内的部分(即else语句)为可选的,即可以有,也可以没有;语句1和语句2可以是一个简单的语句,也可以是一个复合语句,还可以是另一个if语句(即在一个if语句中又包括另一个或多个内嵌的if语句)。

在系统对if语句编译时,若发现内嵌语句结束(出现分号),还要检查其后有无else,如果无else,就认为整个if语句结束,如果有else,则把else子句作为if语句的一部分,注意else子句不能作为单独语句使用,它必须是if语句的一部分,与if配对使用。

示意图(搞笑图):

# 4.3 关系运算符和关系表达式

C语言中,比较符(或称比较运算符)称为关系运算符,所谓“关系运算” 就是“比较运算”,将两个数值进行比较,判断其比较的结果是否符合给定的条件。

# 4.3.1 关系运算符及其优先次序

  • 优先级相同(<、<=、>、>=)> 优先级相同(==、!=)
  • 优先级:算术运算符 > 关系运算符 > 赋值运算符

【例】:

  • c > a+b:等效于c > (a+b)
  • a>b==c:等效于(a>b) == c
  • a==b<c:a == (b<c)
  • a=b>c:a=(b>c)

【例】:设a=3,b=4,c=5

  • a+b>c && b==c 结果:0
  • a||b+c && b-c 结果:1
  • !(a>b) && !c||1 结果:1
  • !(x=a) && (y=b) && 0 结果:0
  • !(a+b)+c-1 && b+c/2 结果:1

# 4.3.2 关系表达式

用关系运算符将两个数值或数值表达式连接起来的式子称为关系表达式,关系表达式的值是一个逻辑值,即“真”或“假”。

# 4.4 逻辑运算符和逻辑表达式

用逻辑运算符将关系表达式或其他逻辑量连接起来的式子就是逻辑表达式。

# 4.4.1 逻辑运算符及其优先次序

【注】:

  • &&||是双目运算符,它要求有两个运算对象(操作数),如(a>b)&&(x>y),(a>b)||(x>y);
  • !是一目(元)运算符,只要求有一个运算对象,如!(a>b);

【注】:优先级:! > 算术运算符 > 关系运算符 > &&和|| > 赋值运算符

# 4.4.2 逻辑表达式

C语言编译系统在表示逻辑运算结果时,以数值1代表“真”,以0代表“假”,但在判断一个量是否为“真”时,以0代表“假”,以非0代表“真”,如4&&0||2的值为1。

【例】:5 > 3 && 8<4 - !0:结果为0

实际上,逻辑运算符两侧的运算对象不但可以是0和1,或者是0或非0的整数,也可以是字符型、浮点型、枚举型或指针型的纯量刑数据,系统最终以0或非0来判定它们属于“真”或“假”,如‘c’&&'d'的值为1,因为它们的ASCII值都不为0,按“真”处理。

在逻辑表达式的求解中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符。

【例】:(m= a>b) && (n = c>d)

a=1,b=2,c=3,d=4mn的原值为1时,由于a>b的值为0,因此m=0,此时已能判定整个表达式不可能为真,不必再进行n=c>d的运算,因此n的值是0不是1。

# 4.4.3 逻辑型变量

在头文件stdbool.h中,将bool定义为_Bool的同义词,同时定义了两个符号常量truefalsetrue代表1,false代表0,用它们分别代表真和假。

例4.4 逻辑型变量

#include<stdio.h>
#include<stdbool.h>
int main(){ 
    float score;
    bool a,b;
    printf("请输入学生成绩:");
    scanf("%f",&score);
    a = score>=60;
    b = score<=69;
    if(a&&b){
        printf("该学生成绩合格!\n");
    }
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 4.5 条件运算符

条件运算符由两个符号(?和:)组成,必须一起使用,要求有3个操作对象,称为三目(元)运算符,它是C语言中的唯一的一个三目运算符,其一般形式为:条件表达式1?表达式2:表达式3,条件运算符的优先级低于关系运算符和算术运算符。

例4.5 将输入字符串中的大写字母转换成小写字母,小写字母转换成大写字母。

  • 方法1:遍历数组
#include<stdio.h>
int main(){
    char str[100];
    printf("请输入一个字符串:");
    fgets(str,sizeof(str)/sizeof(str[0]),stdin);
    for (int i = 0; str[i]!='\0'; i++) {
        if(str[i]>='a'&&str[i]<='z'){
            str[i] -= 32;
        }else if(str[i]>='A'&&str[i]<='Z'){
            str[i] += 32;
        }
    }
    printf("转换结果为:%s\n",str);
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

官方文档

scanf函数和gets函数都可用于输入字符串,但gets可以接收空格,而scanf遇到空格、回车、Tab键都会认为结束,所以他不能接收空格。

  • 方法二:使用toupper函数和tolower函数
#include <ctype.h>
#include <stdio.h>
int main(){
    char str[100];
    printf("请输入一个字符串:");
    fgets(str,sizeof(str)/sizeof(str[0]),stdin);
    for(int i = 0; i < sizeof(str); i++)
        str[i] = toupper(str[i]);
    printf("转换后的结果为: %s\n", str);
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11

# 4.6 选择结构的嵌套

例4.6 根据公式输入一个x值,要求输出相应的y值。

#include <stdio.h>
int main(){
    int x,y;
    printf("请输入x的值:");
    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);
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 4.7 用switch语句实现多分支选择结构

switch语句是多分支选择语句,其一般形式如下:

switch(表达式){
	case 常量1 :语句1
	case 常量2 :语句2
		.						.
		.						.
		.						.
	case 常量n :语句n
	default:语句n+1
}
1
2
3
4
5
6
7
8
9
10
  • continue:跳出当前循环,进入下一次循环;
  • break:终止循环

例4.7 用switch语句处理菜单命令

#include <stdio.h>
int main(){
    int score;
    char grade;
    printf("请输入学生成绩:");
    scanf("%d",&score);
    int i = score / 10;
    switch (i) {
        case 0:
        case 1:
        case 2:
        case 3:
        case 4:
        case 5:
            grade = 'E';
            break;
        case 6:
            grade = 'D';
            break;
        case 7:
            grade = 'C';
            break;
        case 8:
            grade = 'B';
            break;
        case 9:
            grade = 'A';
            break;
        default:
            break;
    }
    printf("输入成绩为%d,其对应的等级为%c\n",score,grade);
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 4.8 选择结构程序综合举例

例4.8 运输公司对用户计算运输费用,路程s km越远,每吨/km运费越低,标准如下。

#include <stdio.h>
int main(){
    int c,s;
    float price,weight,discount,fee;
    printf("请输入price、weight、s的值:");
    scanf("%f %f %d",&price,&weight,&s);
    if(s>=3000){
        c = 12;
    }else{
        c = s/250;
    }
    switch (c) {
        case 0:
            discount = 0;
            break;
        case 1:
            discount = 2;
            break;
        case 2:
        case 3:
            discount = 5;
            break;
        case 4:
        case 5:
        case 6:
        case 7:
            discount = 8;
            break;
        case 8:
        case 9:
        case 10:
        case 11:
            discount = 10;
            break;
        case 12:
            discount = 15;
            break;
    }
    fee = price * weight * s * (1-discount/100);
    printf("总运费为:%.2f\n",fee);
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

课后题:4、5、6、7、8、9、10、11