分支结构
条件判断
**条件判断:**根据某个条件成立与否,决定是否执行指定的操作。
条件判断的结果是逻辑值。其结果为真(写代码的时候可以用非0,C语言给我们返回使用1)或者为假(0)。
小贴士:
① C语言中,条件表达式(作为分支或者循环条件的表达式称之为条件表达式)支持任意类型的表达式,包括如关系、逻辑、赋值、算术等表达式,但实质上有意义的表达式只有关系表达式和逻辑表达式。
② C语言中,条件表达式的结果是逻辑值,使用非0表示真,使用0表示假,但是底层是使用1和0来表示真假。
关系运算符及其表达式
问题抛出
我们在程序设计往往会遇到如下问题,比如下面的函数的计算:
y={1/x当x≠0时10000当x=0时
y = \begin{cases} 1/x \quad当x\neq0时\\ \\ 10000 \quad当x=0时 \end{cases}
y=⎩⎨⎧1/x当x=0时10000当x=0时
也就是我们必须要通过一个条件的结果来选择下一步的操作,算法上属于一个分支结构,C语言实现分支结构主要使用if。
其中的条件需要用关系表达式来表示:x!=0 就是一种关系表达式。
关系运算符及其优先级次序
关系运算符是用来进行比较的符号,C语言提供了6种关系运算符:
举例:
int a = 5, b = 6;
printf("%d\n", a > 5 != b > 5);// 1 解释:a > 5的结果和 b > 5的结果进行比较
关系表达式
关系表达式 = 关系运算符 + 表达式(操作数)
逻辑运算符及其表达式
问题抛出
有时,只用一个简单的关系表达式无法完整的表达一个条件:
y={1/x+1/a当x≠0,a≠0时10000其他
y = \begin{cases} 1/x+1/a \quad当x\neq0,a\neq0时\\ \\ 10000 \quad其他 \end{cases}
y=⎩⎨⎧1/x+1/a当x=0,a=0时10000其他
其中的条件需要用到逻辑表达式来表示:x!=0 && a!=0就是一种逻辑表达式。
逻辑运算符及其优先级
- 逻辑运算符是构成复杂的复合条件的运算符。
C语言中提供了三种逻辑运算符:
符号 | 名称 | 分类 | 说明 |
---|---|---|---|
&& | 逻辑与 | 双目运算符 | 两个量都为真时为真(1),否则为假(0) |
|| | 逻辑或 | 双目运算符 | 两个量中只要有一个为真即为真(1),只有两个量都为假时才为假(0) |
! | 逻辑非 | 单目运算符 | 运算量真时变为假(0),假时变为真(1) |
逻辑表达式
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 |
**定义:**用逻辑运算符将关系表达式或者逻辑表达式链接起来的构成有意义的算式称作逻辑表达式。
逻辑表达式中各种运算符的优先级顺序如下:
① !(逻辑非)
② 算数运算符(
*,/,%
(高)+,-
(低))③ 关系运算符(
>,>=,<,<=
(高)!=,==
(低))④ 逻辑运算符(
&&,||
)⑤ 赋值运算符(
=、+=、-=、*=、/=、%=
)
面试题:
① 使用表达式表示一个数num在0~100之间:
num >= 0 && num <=100
② 使用表达式表示一个数比0小,比100大:
num < 0 || num > 100
注意:这里的①和②属于真假判断。
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…
语法:
if (条件表达式)
{
语句;
}
// 如果是单语句,可以省略{},以下两种写法完全等价
if (条件表达式) 语句;
if (条件表达式)
语句;
流程图:
功能:
- 若表达式值为真(非0),则执行表达式后面的语句,执行完该语句后继续执行if语句后的其他语句。
- 若表达式值为假(0),则不执行表达式后面的语句而直接执行if语句后面的其他的语句。
说明:
- 如果表达式后面的是复合语句(语句超过1条),则需要使用一对
{}
括起来。
案例:
-
需求:计算并输出下列分段函数的值:
y={−2x<02x≥0 y = \begin{cases} -2 \quad x<0\\ \\ 2 \quad\quad x\geq0 \end{cases} y=⎩⎨⎧−2x<02x≥0 -
流程图:
-
代码:
#include <stdio.h> int main(int argc,char *argv[]) { // 创建两个变量x,y 存储数据 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
-
代码:
#include <stdio.h> int main(int argc,char *argv[]) { // 创建5个变量,a, b,c接受控制台输入,max和min分别存储最大和最小 int a,b,c,max,min; // 从控制台输入 printf("请输入三个整数:\n"); scanf("%d%d%d",&a, &b, &c); // 将赋值后的a作为max和min的初始值 max = min = a; // 链式操作,从右往左 // 最大值 if (max < b) max = b; if (max < c) max = 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…
语法:
if (条件表达式)
{
语句1;
}
else
{
语句2;
}
// 如果是单语句,可以省略{},以下两种写法等价
if (条件表达式) 语句1;
else 语句2;
if (条件表达式)
语句1;
else
语句2;
注意:else语句本身不能单独存在,必须和距离自己最近的未配对的if配对
流程图:
功能:
若表达式的值为1,则执行语句1;否则执行语句2。不管条件表达式成不成立,都要执行一个语句,其次需要注意的是,语句1和语句2都可以是单语句或者复合语句。
说明:
if…else…结构可以实现双分支选择结构。C语言允许if…else…结构嵌套。即在语句1与语句2中又可以包含完整的if语句或者if…else…语句,并且这种嵌套可以多层(为了保证程序的执行效率,建议不超过3~4层)。利用if…else…结构的嵌套,可以实现多分支结构。
案例:
-
需求:计算并输出下列分段函数的值:
y={−2x<02x≥0 y = \begin{cases} -2 \quad x<0\\ \\ 2 \quad\quad x\geq0 \end{cases} y=⎩⎨⎧−2x<02x≥0 -
流程图:
-
代码:
#include <stdio.h> int main(int argc,char *argv[]) { // 创建两个变量 int x, y; // 控制台输入 printf("请输入一个整数:\n"); 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)
-
代码:
#include <stdio.h> int main(int argc,char *argv[]) { // 创建一个变量,用来存储年份 int year; // 通过控制台给year赋值 printf("请输入一个年份:"); scanf("%d", &year); // 校验 if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) printf("%d年是闰年!\n", year); else printf("%d年是平年!\n", year); printf("打印变量的内存首地址:%p\n",&year); return 0; }
-
运行结果:
-
注意:对于单语句的双分支,我们可以使用三目运算符的写法进行简化!
双分支:三目运算符
三目运算符,又被称作三元运算符。
语法:
表达式1 ? 表达式2 : 表达式3;
说明:
① 如果表达式1的结果为真,就执行表达式2;否则执行表达式3。(表达式2和表达式3只能满足一个)
② 三目运算符的写法实际上就是单语句的双分支if的简写。
案例:
#include <stdio.h>
int main(int argc,char *argv[])
{
// 创建两个变量
int x, y;
// 控制台输入
printf("请输入一个整数:\n");
scanf("%d", &x);
// 判断
y = x < 0 ? -2 : 2;
// 打印输出
printf("x=%d,y=%d\n",x,y);
return 0;
}
案例:
-
需求:通过控制台输入a,b,c三个数,求出最大值
-
代码:
#include <stdio.h> int main(int argc,char *argv[]) { // 创建5个变量,a, b,c接受控制台输入,max和min分别存储最大和最小 int a,b,c,max,min; // 从控制台输入 printf("请输入三个整数:\n"); scanf("%d%d%d",&a, &b, &c); // 最大值 max = (a > b) ? (a > c ? a : c) : (b > c ? b : c); // 最小值 min = (a < b) ? (a < c ? a : c) : (b < c ? b : c); printf("%d,%d,%d中的最大值是%d,最小值是%d\n",a,b,c,max,min); return 0; }
多分支:if…else if…else…
语法:
// 写法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 语句n+1; // 根据需求,可选
// 如果是复合语句,{}不能省略
注意:多分支中else是可选的,根据自己的需求决定要不要写。
多分支:
注意:多分支中,同一时刻只能满足一个分支。
案例:
-
需求:根据学生的成绩,对学生进行评级:
- 成绩 >= 90 A
- 成绩 >= 80 B
- 成绩 >= 60 C
- 成绩 < 60 D
-
代码:
#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;
if语句的嵌套
语法:
if (..)
if (..) 语句1;
else 语句2;
else
if (..) 语句3;
else 语句4;
流程图:
注意:
① else总是与前面最近的未配对的if配对使用
② 可通过增加{}来确定配对关系
③ 只要if中包含if,都属于是if语句的嵌套
案例
-
需求:根据学生的成绩,对学生进行评级:
- 成绩 >= 90 A
- 成绩 >= 80 B
- 成绩 >= 60 C
- 成绩 < 60 D
-
代码:
#include <stdio.h> /** * 方式1: 借助于顺序执行,减少判断条件(顺序一旦打乱,程序执行就会出错) */ int if_test1() { // 创建一个变量,存储成绩 int score; // 通过控制台输入成绩 printf("请输入一个成绩:"); scanf("%d", &score); // 第一层校验:输入的合法性校验 if (score >= 0 && score <= 100) { // 第二层校验:成绩的等级校验 // 根据成绩评级 if (score >= 90) printf("A级\n"); else if (score >= 80) printf("B级\n"); else if (score >= 60) printf("C级\n"); else printf("D级\n"); } else { printf("请输入0~100之间的整数!\n"); } return 0; } /** * 方式2: 不借助于顺序执行,增加判断条件(顺序一旦打乱,程序执行不受影响) */ int if_test2() { // 创建一个变量,存储成绩 int score; // 通过控制台输入成绩 printf("请输入一个成绩:"); scanf("%d", &score); // 根据成绩评级 if (score < 0 || score > 100) printf("请输入0~100之间的整数!\n"); else 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; }
思考
- 如何拆分一个整数的个位、十位、百位…上的数?
举例:123
拆个位:123 % 10 = 3
拆十位:123 / 10 % 10 = 2
拆百位:123 / 10 / 10 = 1
用switch语句实现分支结构
我们也可以使用switch实现多分支选择结构(多分支也被称作多路分支)
语法:
switch (表达式) // 表达式返回结果最好是 字符或者整型
{
case 常量表达式1: // 这里一般使用字面量、符号常量、枚举
语句1;
break;
case 常量表达式2: // 这里一般使用字面量、符号常量、枚举
语句2;
break;
...
[case 常量表达式n: // 这里一般使用字面量、符号常量、枚举
语句n;
break;
default:
语句n+1;
break;]
}
// switch的{}不能省略
流程图:
说明:
① switch后括号内的表达式可以是任意类型的表达式,要求结果是整型、字符型。
② 若表达式的值与某个常量表达式的值相等时,执行case后面的语句;若没有相等的值时,执行default后面的语句。
③ 每个case后面的常量表达式的值必须不相同,否则出现矛盾。
④ 各个case出现的次序不影响执行结果。
⑤ case后面的语句中如果没有break语句,则执行完本case后的语句后会接着执行下面的case,直到遇到下一个break或者switch执行完毕为止,演示:
int num = 1;
switch(num)
{
case 1:
printf("A\n");//注意:这里没有break,会继续执行下一个case,直到遇到break或者执行结束(break穿透)
case 2:
printf("B\n");
break;
case 3:
printf("C\n");
break;
}
运行结果:
A
B
⑥ 多个case公用一组语句,演示:
// 需求:根据月份判断季节
// 分析:
// 春季:2~4
// 夏季:5~7
// 秋季:8~11
// 冬季:12~1
int month = 3; // 月份
switch (month)
{
case 2: // 2月份
case 3: // 3月份
case 4: // 4月份
printf("春季\n");
break;
...
}
案例
-
需求:按照考试成绩的等级输出百分制分数段
-
分析:
- A级:85~100段
- B级:70~84段
- C级:60~69段
- D级:< 60段
- 其他:错误
-
代码:
#include <stdio.h> int main() { // 创建一个变量,用来存放等级 char grade; // 通过键盘录入等级 printf("请输入一个英文字符:\n"); scanf("%c", &grade); getchar(); // 清空缓冲区 // 校验 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("错误\n"); break;// 如果default出现在所有case的最下面,break可以省略;如果default出现在case的上面,break一定不能省略。 } return 0; }
注意: 如果default出现在所有case的最下面,break可以省略;如果default出现在case的上面,break一定不能省略。
案例
-
需求:按照百分制考试分数输出等级。
-
分析:
- 若分段原则如下:
- 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~89的数 / 10 = 8
,依次类推
-
代码:
#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; }
案例
-
需求:设计一个简易计算器,要求能够实现简单的减减乘除运算
-
代码:
#include <stdio.h> int main(int argc,char *argv[]) { char op; // 保存运算符 double num1,num2; // 保存运算数 // 设置头 printf("--------------------\n"); printf("| 简易计算器 v1.0 |\n"); printf("--------------------\n"); printf("请输入两个运算数:\n"); scanf("%lf,%lf", &num1,&num2); printf("请输入运算符(+、-、*、/):"); getchar();// 清理缓存 scanf("%c",&op); // 计算 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; }