内容提要
- 分支结构
- 条件判断
- 用if语句实现分支结构
- 用switch语句实现分支结构
分支结构
问题抛出
我们在程序设计往往会遇到如下问题,比如下面的函数的计算:
y = { 1 x ,当 x ≠ 0 时 1000 ,当 u = 0 时 y = \begin{cases} \frac{1}{x},当x\neq0时 \\ 1000,当u=0时 \end{cases} y={x1,当x=0时1000,当u=0时
也就是我们必须要通过一个条件的结果来选择下一步的操作,算放上属于一个分支结构,C语言中实现分支结构主要使用if语句。
条件判断
条件判断:根据某个条件成立与否,决定是否执行指定的操作。

条件判断的结构是逻辑值,也就是布尔类型值,其结果为真(非0)或者假(0)
面试题:
①C语言中,条件表达式(作为分支或者循环条件的表达式称之为条件表达式)支持任意类型的表达式,包括如关系、逻辑、赋值、算术等表达式,但实质上有意义的表达式只有关系表达式和逻辑表达式。
②C语言中,条件表达式的结果是逻辑值,使用非0表示真,使用0表示假,但是底层是使用1和0来表示真假。
关系运算符及其表达式
关系运算符及其优先级次序
关系运算符时用来进行比较的符号,C语言提供了6种关系运算符:

举例:
c
int a = 5, b = 6;
printf("%d\n", a > 5 != b > 5); //解释:a > 5结果和b > 5的结果进行比较
关系表达式
关系表达式=关系运算符+表达式(操作数)

问题抛出
有时,只用一个简单的关系表达式无法完整的表达一个条件
y = { 1 x + 1 a ,当 x ≠ 0 , a ≠ 0 时 1000 ,其他 y = \begin{cases} \frac{1}{x}+\frac{1}{a},当x\neq0,a\neq0时 \\ \\ 1000,其他 \end{cases} y=⎩ ⎨ ⎧x1+a1,当x=0,a=0时1000,其他
其中的条件需要用逻辑表达式来表示:x!=0&&a!=0就是一种逻辑表达式。
逻辑运算符及其表达式
逻辑运算符及其优先级
- 逻辑运算符是构成复杂的复合条件的运算符。
C语言中提供了三种逻辑运算符:

逻辑表达式
a | b | !a | !b | a&&b | a||b |
---|---|---|---|---|---|
1 | 1 | 0 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 0 | 1 |
0 | 1 | 1 | 0 | 0 | 1 |
0 | 0 | 1 | 1 | 0 | 0 |
**定义:**用逻辑运算符将关系表达式或者逻辑表达式链接起来的构成有意义的算式称作逻辑表达式。

逻辑表达式中各种运算符的优先级顺序如下:
①!(逻辑非)
②算术运算符(
*、/、%
>+、---
)③关系运算符(
>、>=、<、<=
>==、!=
)④逻辑与和逻辑或(
&&、||
)⑤赋值运算符(
=、+=、-=、*=、/=、%=
)
C编译系统在表示逻辑运算符运算结果时,返回的也是逻辑值:用1表示真,用0表示假。
案例
假设a=4,b=5则:
表达式 | 结果 | 说明 |
---|---|---|
!a | 0 | 这里是对非0取反 |
a&&b | 1 | &&两边都是非0 |
a||b | 1 | ||左边是非0,触发短路效果 |
!a||b | 1 | ||右边是非0 |
4&&0||2 | 1 | 同级别运算,从左往右 |
小贴士:
实际上,逻辑运算符两侧的运算对象不但可以是0和1,或者是0和非0,而且也可以是字符型、实型和指针型等。系统最终是以0和非0来判定他们的真假的,例如:
'c'&&'d'结果为1
用if语句实现分支结构
单分支:if...
语法:
c
if(条件表达式)
{
语法;
}
//如果是单语句,可以省略{},以下两种写法完全等价
if(条件表达式)语句;
if(条件表达式)
语句;
流程图:

功能:
- 若表达式值为真(非0),则执行表达式后面的语句,执行完该语句后继续执行if语句后的其他语句。
- 若表达式为假(0),则不执行表达式后面的语句而直接执行if语句后面的其他的语句。
说明:
- 如果表达式后面的复合语句(语句超过1条),则需要使用一对
{}
括起来。
案例:
-
需求:计算并输出下列分段函数的值:
y = { − 2 , x < 0 2 , x > = 0 y = \begin{cases} -2,x<0 \\ \\ 2,x>=0 \end{cases} y=⎩ ⎨ ⎧−2,x<02,x>=0 -
流程图:
-
代码
c#include<stdio.h> int main() { // 创建2个变量,存储数据 int x, y = -2; // 通过控制台给x赋值 printf("请输入一个整数:"); scanf("%d", &x); //判断 if (x >= 0) y = 2; // 测试输出 printf("x=%d,y=%d\n",x,y); return 0 }
-
运行结果:
案例
-
需求:有啊a,b,c三个数,要求从控制台输入,并求出他们中最大数的最小数。
-
分析:
-
①首先创建5个变量,其中a,b,c用来接受控制台输入,max和min分别用来存储最大和最小
②默认a是max和min
③让max分别和b、c比较,如果b、c比max大,就将b、c的值赋值给max
④让min分别和b、c比较,如果b、c比min小,就将b、c的值赋值给min
-
代码:
c#include <stdio.h> int main(int argc,char *argv[]) { // 创建5个变量,a,b,c用来接收控制台输入,max和min存放最大和最小 int a,b,c,max,min // 从控制台输入 printf("请输入三个整数:"); scanf("%d%d%d",&a,&b,&c); // 给max和min赋值,默认将a赋与max和min,注意:要等到a实例化之后才可以 max = min = a; // 赋值运算是从右往左,向将a赋予min,再将min的值赋予max // 最大值 if(max < b) max = b; // b是a,b中的最大值 if(max < c) max = c; // c是a,b,c中的最大值 // 最小值 if(min > b) min = b; if(min > c) min = c; printf("%d,%d,%d中的最大值是%d,最小值是%d\n",a,b,c,max,min); return 0; }
-
运行结果:
-
有可能产生的问题:
- 在变量赋值前使用变量,导致运算结果错误,因为变量未赋之前,系统会给变量分配随机值。
小贴士:
建议的书写规范:
if(flag == 1)建议写做:if(flag)
if(flag == 0)建议写做:if(!flag)
双分支:if...else...
语法:
c
if(条件表达式)
{
语句1;
}
else
{
语句2;
}
//如果是单语句,可以省略(),以下两种写法完全等价
if(条件表达式)语句1;
else 语句2;
if(条件表达式)
语句1;
else
语句2;
注意:else语句本身不能单独存在,,必须和距离自己最近的未配对的if配对。
流程图:

功能:
若表达式的值为1,则执行语句1;否则执行语句2。不管条件表达式成不成立,都要执行一个语句,其次需要注意的是,语句1和雨具都可以是单语句或者复合语句。
说明:
if...else...结构可以实现双分支选择结构。C语言允许if...else...结构嵌套。即在语句1和语句2中又可以包含完整的if语句或者if...else...语句,并且这种嵌套可以多层(为了保存程序的执行效率,建议不超过3~4层)。利用if...else...结构的嵌套,可以实现多分支选择结构。
案例
-
需求:计算并输出下列分段函数的值:
-
y = { − 2 , x < 0 2 , x > = 0 y = \begin{cases} -2,x<0 \\ \\ 2,x>=0 \end{cases} y=⎩ ⎨ ⎧−2,x<02,x>=0
-
流程图:

-
代码:
c#include <stdio.h> int main(int argc,char *argv[]) { // 创建两个变量,用来存放数据 int x, y; // 通过控制台给x赋值 printf("请输入一个整数:"); scanf("%d",&x); // 根据条件赋 if (x < 0) y = -2; else y = 2; // 打印输出 printf("x=%d,y=%d\n",x,y); return 0; }
-
运行结果:
案例:
-
需求:通过控制台,输入一个年份,判断这个年份是闰年还是平年
-
分析:
- 判断条件:(year % 4 == 0 && year % 100 !=0) || year % 400 == 0
-
代码:
c#include <stdio.h> int main(int argc,char *argv[]) { // 创建一个变量,用来接收控制台输入的年份 int year; // 通过控制台输入一个年份 printf("请输入一个年份:"); scanf("%d",&year); // 判断这个输入的年份是闰年还是平年 if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0) printf("%d年是闰年!\n", year); else printf("%d年是平年!\n", year); return 0; }
-
运行结果:
-
注意:对于单语句的双分支,我们可以使用三目运算符的写法来简化!
双分支:三目运算符
三目运算符,又称作三元运算符。
语法:
c
表达式1 ? 表达式2 : 表达式3;
说明:
①如果表达式1的结果为真,就执行表达式2,否则执行表达式3。(表达式2和表达式3只能满足一个)
②三目运算符的写法实际上就是单语句的双分支if的简写
案例:
-
需求:将双分支案例改造为三目运算符的写法:
-
代码:
c#include <stdio.h> int main(int argc,char *argv[]) { // 创建两个变量,用来存放数据 int x, y; // 通过控制台给x赋值 printf("请输入一个整数:"); scanf("%d",&x); // 根据条件赋值 y = x < 0 ? -2 : 2; // 打印输出 printf("x=%d,y=%d\n",x,y); return 0; }
案例:
-
需求:通过控制陶输入a,b,c三个数,求出最大值
-
代码:
c#include <stdio.h> int main(int argc,char *argv[]) { // 创建4个变量,a,b,c存储控制台输入,max存储最大 int a,b,c,max; // 通过控制台给a,b,c赋值 printf("请输入三个整数:"); scanf("%d%d%d",&a,&b,&c); // 获取最大值 max = (a > b) ? (a > c ? a : c) : (b > c ? b : c); printf("%d,%d,%d中的最大数是%d\n",a,b,c,max); return 0; }
课堂练习
需求:从键盘录入一个整数,判断这个数是偶数还是奇数。
要求:分别使用单分支if、双分支if、三目运算符实现。
多分支:if...else if...else...
语法:
c
//写法1:嵌套if..else.. (不推荐)
if(表达式1)语句1;
else
if(表达式2)语句2;
else
...
else
if(表达式n)语句n;
else 语句n + 1;
//写法2:并列if..else if..else..(推荐)
if(表达式1)语句1;
else if(表达式2)语句2;
...
[else if(表达式n)语句n;] //根据需求,else可选不写
[else 语句n+1;] //根据需求,可选
//如果是复合语句,{}不能省略
注意:多分支中的else是可选的,根据自己的需求决定要不要写。
流程图:

注意:多分支中,同一时刻只能满足一个分支
案例
-
根据学生的成绩,对学生进行评级:
- 成绩 >= 90 A
- 成绩 >= 80 B
- 成绩 >= 60 C
- 成绩 < 60 D
-
代码:
c#include <stdio.h> /** * 方式1:借助于顺序执行,减少判断条件(顺序一旦打乱,程序执行就会出错) */ int if_test1() { // 创建一个变量保存考试成绩 int score; // 从控制台输入成绩 printf("请输入一个成绩:"); scanf("%d",&score); // 根据成绩评级 if (score >= 90) printf("A级\n"); else if (score >= 80) printf("B级\n"); else if (score >= 60) printf("C级\n"); else printf("D级\n"); return 0; } /** * 方式2:不借助于顺序执行,做更精确的条件判断 */ int if_test2() { // 创建一个变量保存考试成绩 int score; // 从控制台输入成绩 printf("请输入一个成绩:"); scanf("%d",&score); // 根据成绩评级 if (score < 60) printf("D级\n"); else if (score >= 60 && score < 80) printf("C级\n"); else if (score >= 80 && score < 90) printf("B级\n"); else printf("A级\n"); return 0; } int main(int argc,char *argv[]) { if_test1(); if_test2(); return 0; }
if...else结构注意点
if...else结构中的语句1和语句2都可以是复合语句。
在if...else结构中,语句1和语句2都可以是空语句。举例if(..);else;

课堂练习
要求:计算并输出下列分段函数值,其中x从键盘录入。
y = { 0 , x < − 10 2 x + 20 , − 10 ≤ x < 20 20 , 0 ≤ x < 20 30 − 0.5 x , 20 ≤ x < 40 50 − x , 40 ≤ x < 50 0 , x ≥ 50 y = \begin{cases} 0,x<-10 \\ 2x+20,-10\le x<20 \\ 20,0\le x<20 \\ 30-0.5x,20\le x<40 \\ 50-x,40\le x<50 \\ 0,x\ge50 \end{cases} y=⎩ ⎨ ⎧0,x<−102x+20,−10≤x<2020,0≤x<2030−0.5x,20≤x<4050−x,40≤x<500,x≥50
if语句的嵌套
语法:
c
if (..)
if (..) 语句1;
[else 语句2;]
[else
if (..) 语句3;
else 语句4;
]
流程图:

注意:
①else总是与前面最近的未配对的if配对使用
②可通过增加{}来确定配对关系
③只要if中包含if,都属于是if语句的嵌套
课后练习
1、如何拆分一个整数的个位、十位、百位...上的数?
举例:123
拆个位数:123 % 10 = 3
拆十位:123 / 10 % 10 = 2
拆百位:123 / 10 /10 = 1
2、什么是水仙花数?
用switch语句实现分支结构
我们可以使用switch实现多分支选择结构(多分支也被称多路分支)
语法:
c
switch(表达式) //表达式的结果建议是 字符 或者 整型
{
case 常量表达式1: //这里一般使用字面量,符号常量、枚举
语句1;
break;
case 常量表达式2: //这里一般使用字面量,符号常量、枚举
语句2;
break;
....
case 常量表达式n: //这里一般使用字面量,符号常量、枚举
语句n;
break;
}
流程图:

说明:
①switch后括号内的表达式可以是任意类型的表达式,建议表达式的结果是整型、字符型
②若表达式的值与某个常量表达式的值相等时,执行case后面的语句;若没有相等的值时,执行default后面的语句。
③每个case后面的常量表达式的值必须不相同,否则出现矛盾。
④各个case出现的次序不影响执行结果。
⑤ case后面的语句中如果没有break语句,则执行完本case后的语句后会接着执行下面的case,直到遇到下一个break或者switch执行完毕为止。
c
int num = 1;
switch (num)
{
case 1:
printf("A\n"); //注意:这里没有break,会继续执行下一个case,直到遇到break或者执行结束
case 2:
printf("B\n");
break;
case 3:
printf("C\n");
break;
}
运行结果:
A
B
⑥多个case公用一组语句,演示:
c
//需求:根据月份判断季节
//分析:
// 春季:2~4
// 夏季:5~7
int month = 3; //月份
switch (month)
{
case 2:
case 3:
case 4:
printf("春季\n");
}
案例:
- 需求:按照考试成绩的等级输出百分制分数段
- 分析:
- A级:85~100段
- B级:70~84段
- C级:60~69段
- D级:<60段
- 其他:错误
- 代码:
c
#include <stdio.h>
int main(int argc,char *argv[])
{
// 创建一个变量,用来存放等级
char grade;
// 通过键盘输入等级
printf("请输入一个字符:\n");
scanf("%c",&grade);
// 校验,根据等级输出分数段
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("Error\n");
break; // 如果default在所有case的下面,default后面的break可以省略, 否则break不能省略
}
return 0;
}
案例
-
需求:按照百分制开始输出等级。
-
分析:
- 若分段原则如下:
- 90~100 A级
- 80~89 B级
- 70~79 C级
- 60~69 D级
- 其他 E级
- 若分段原则如下:
-
解析:
case score >= 90 && score <= 100
在switch中是错误的写法,无法通过编译- 改造判断条件:
90~100的数 / 10 = 9|10
,80~90的数 / 10 = 8
,以此类推
-
代码:
c#include <stdio.h> int main(int argc,char *argv[]) { // 创建一个变量,用来保存成绩 int score; // 通过控制台输入一个成绩 printf("请输入一个整数:"); scanf("%d",&score); // 非法校验 if (score < 0 || score > 100) { printf("Error\n"); } else { switch (score / 10) { default: printf("E级\n"); break;// 此处break不能省略 case 10: // 100 case 9: // 90~99 printf("A级\n"); break; case 8: // 80~89 printf("B级\n"); break; case 7: // 70~79 printf("C级\n"); break; case 6: // 60~69 printf("D级\n"); break; // 此时的break可以省略 } } return 0; }
案例
-
需求:设计一个简易计算器,要求能够实现简单的
-
代码:
c#include<stdio.h> int main(int argc,char *argv[]) { char op; // 运算符 double num1,num2; // 运算数 printf("-----------------------\n"); printf("| 简易计算器v1.0 |\n"); printf("-----------------------\n"); printf("请输入两个运算数:"); scanf("%lf,%lf",&num1,&num2); printf("请输入运算符(+,-,*,/):"); // 清空输入缓冲区中的\n getchar(); scanf("%c",&op);// 此时需要提前清空输入缓冲区上次输入时回车产生的\n字符,否则无法输入新字符 // 计算 switch (op) { case '+': printf("%.2lf + %.2lf = %.2lf\n",num1,num2,num1 + num2); break; case '-': printf("%.2lf - %.2lf = %.2lf\n",num1,num2,num1 - num2); break; case '*': printf("%.2lf * %.2lf = %.2lf\n",num1,num2,num1 * num2); break; case '/': if(num2 != 0) printf("%.2lf / %.2lf = %.2lf\n",num1,num2,num1 / num2); else printf("错误,除数不能为0!\n"); break; default: printf("错误,无效的运算符!\n"); } return 0; }