前言
C语⾔是结构化的程序设计语⾔,这⾥的结构指的是顺序结构、选择结构、循环结构,C语⾔是能够实现这三种结构的,其实我们如果仔细分析,我们⽇常所⻅的事情都可以拆分为这三种结构或者这三种结构的组合。
在C语言中,我们就可以使⽤ if 、 switch 实现分⽀结构,使⽤ for 、 while 、 do while 实现循环结构。
这期博客先来看看 分支结构中的if switch语句
一、 if语句
1. if
if 语句的语法形式如下:
if ( 表达式 ) 语句;
表达式成立(为真),则语句执行,表达式不成立(为假),则语句不执行
这里还要强调一下
在C语言中,0表示假,非0表示真
也就是表达式的结果如果是0,则语句不执行,表达式的结果如果是不是0,则语句执行。
下面有一个程序流程图,这样大家就会理解深刻
我们可以尝试使用一下
例:输⼊⼀个整数,判断是否为奇数
#include <stdio.h> int main() { int num = 0; scanf("%d", &num); if (num % 2 == 1) printf("%d 是奇数\n", num); return 0; }
程序执行过程是这样的
2. else
如果⼀个数不是奇数,那就是偶数了,如果任意⼀个整数,我们要清楚的判断是奇数还是偶数怎么表⽰呢?
这⾥就需要 if...else... 语句了,语法形式如下:
if(表达式){ 语句1; } else { 语句2; }
例:输⼊⼀个整数,判断是否为奇数,如果是奇数打印是奇数,否则打印数偶数。
#include <stdio.h> int main() { int num = 0; scanf("%d", &num); if (num % 2 == 1) printf("%d 是奇数\n", num); else printf("%d 是偶数\n", num); return 0; }
练习:输⼊⼀个年龄,>= 18岁就输出:成年,否则就输出:未成年
#include <stdio.h> int main() { int age = 0; scanf("%d", &age); if (age >= 18) printf("成年\n"); else printf("未成年\n"); return 0; }
3. 分⽀中包含多条语句
默认在 if 和 else 语句中默认都只控制⼀条语句,⽐如:
你会发现,上⾯的代码,输⼊的值不管是>=18 还是<18,"可以谈恋爱了" 都会打印在屏幕上。
这是因为 if 语句只能控制⼀条语句,就是 printf("成年了\n"); ,if语句为真,则打印成年了, if语句为假,则不打印,对于 printf("可以谈恋爱了\n"); 是独⽴存在的,不管if语句的条件的真假,都会被执⾏。
那如果我们要if语句同时控制2条语句,怎么办呢?那就要使⽤ {} 将代码括起来, else 后也可以跟上⼤括号。如下:
#include <stdio.h> int main() { int age = 0; scanf("%d", &age); if (age >= 18) { printf("成年\n"); printf("可以谈恋爱了\n"); } return 0; }
#include <stdio.h> int main() { int age = 0; scanf("%d", &age); if (age >= 18) { printf("成年了\n"); printf("可以谈恋爱\n"); } else { printf("未成年\n"); printf("不可以早恋\n"); } return 0; }
4. 嵌套if
在 if else 语句中, else 可以与另⼀个 if 语句连⽤,构成多重判断。
⽐如:要求输⼊⼀个整数,判断输⼊的整数是0,还是正数或者负数。
#include <stdio.h> int main() { int num = 0; scanf("%d", &num); if (num == 0) printf("输⼊的数字是0\n"); else if (num > 0) //这⾥的if 相当于嵌套在els语句中,形成了嵌套结构 printf("输⼊的数字是正数\n"); else printf("输⼊的数字是负数\n"); return 0; }
再⽐如:输⼊⼀个整数,如果是正数,再判断是奇数还是偶数,并输出;如果不是正数则输出:负数。
#include <stdio.h> int main() { int num = 0; scanf("%d", &num); if (num > 0) { if (num % 2 == 0) printf("偶数\n"); else printf("奇数\n"); } else { printf("负数\n"); } return 0; }
这是嵌套在 if 语句中的,构成了嵌套的 if 语句
有了嵌套if语句,能让我们的逻辑判断更加的清晰
5. 悬空else问题 🌟🌟
如果有多个 if 和 else ,可以记住这样⼀条规则,else 总是跟最接近的 if 匹配。
我们来看下面这个代码:
这个程序运行的结果是什么?
#include <stdio.h> int main() { int a = 0; int b = 2; if (a == 1) if (b == 2) printf("hehe\n"); else printf("haha\n"); return 0; }
大多数同学可能这样分析,上来以判断 a 是 0,不等于 1,为假,那就执⾏ else ⼦句,打印 haha
但是实际上,当你运行代码,你会发现,运行的结果是:什么也不输出
这是为什么呢?
这就是悬空 else 的问题,如果有多个 if 和 else ,可以记住这样⼀条规则, else 总是跟最接近的 if 匹配。
出错的原因可能是,我们以为代码是下面这样的排版问题,让我们错误以为以为 else 是和第⼀个if匹配的,当 if语句不成⽴的时候,就执⾏ else ⼦句,打印 haha 。
但实际上 else 是和第⼆个 if进⾏匹配的,这样后边的 if...else 语句是嵌套在第⼀个 if 语句中的,如果第⼀个 if 语句就不成⽴,嵌套 if 和 else 就没机会执⾏了,最终啥都不打印。
那么为了避免刚才读代码时的错误判断,代码改成下⾯这样就容易理解
#include <stdio.h> int main() { int a = 0; int b = 2; if (a == 1) { if (b == 2) printf("hehe\n"); else printf("haha\n"); } return 0; }
只要带上代码块({ }),代码的逻辑就会更加的清晰,
所以⼤家以后在写代码的时候,可以适当加上大括号,让代码的可读性更⾼
二、关系操作符
在if语句中,我们需要判断表达式的真假,在表达式判断中,就涉及到判断中遇到的关系操作符。
C 语⾔⽤于⽐较的表达式,称为 “关系表达式”,⾥⾯使⽤的运算符就称为“关系运算符”,主要有下⾯6个。
> ⼤于运算符
< ⼩于运算符
>= ⼤于等于运算符
<= ⼩于等于运算符
== 相等运算符
!= 不相等运算符
例如:
a == b; a != b; a < b; a > b; a <= b; a >= b;
关系表达式通常返回 0 或 1 ,表⽰真假。
C 语⾔中, 0 表示假,所有⾮零值表示真。
⽐如, 20 > 12 返回 1 , 12 > 20 返回 0 。
关系表达式常⽤于 if 或 while 结构。
if (x == 3) { printf("x is 3.\n"); } while (x == 3) { printf("x is 3.\n"); }
注意:相等运算符 == 与赋值运算符 = 是两个不⼀样的运算符,不要混淆。
三、条件操作符
条件操作符也叫三目操作符,需要接受三个操作数的,形式如下:
exp1 ? exp2 : exp3
条件操作符的计算逻辑是:
如果 exp1 为真, exp2 计算,计算的结果是整个表达式的结果;
如果exp1 为假, exp3 计算,计算的结果是整个表达式的结果。
例1:使⽤条件操作符表示下⾯代码的逻辑
#include <stdio.h> int main() { int a = 0; int b = 0; scanf("%d %d", &a, &b); if (a > 5) b = 3; else b = -3; printf("%d\n", b); return 0; } //改造后: #include <stdio.h> int main() { int a = 0; int b = 0; scanf("%d %d", &a, &b); b = a > 5 ? 3 : -3; printf("%d\n", b); return 0; }
例2:使⽤条件表达式实现找两个数中较⼤值。
#include <stdio.h> int main() { int a = 0; int b = 0; scanf("%d %d", &a, &b); int m = a>b ? a : b; printf("%d\n", m); return 0; }
四、 逻辑操作符:&& , || , !
逻辑运算符提供逻辑判断功能,⽤于构建更复杂的表达式,主要有下⾯三个运算符。
! :逻辑取反运算符(改变单个表达式的真假)。
&& :与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假)。
|| :或运算符,就是或者的意思(两侧⾄少有⼀个表达式为真,则为真,否则为假)。
注:C语⾔中,⾮0表示真,0表示假
1. !逻辑取反运算符
运算规则
如: 我们有⼀个变量叫 flag ,如果flag为假,打印hehe,就可以这样写代码:
#include <stdio.h> int main() { int flag = 0; if(!flag) { printf("do something\n"); } return 0; }
如果 flag 为真, !flag 就是假,如果 flag 为假, !flag 就是真
所以上⾯的代码的意思就是 flag 为假,执⾏if语句中的代码。
2. && 与运算符
运算规则
&& 就是与运算符,也是并且的意思, && 是⼀个双⽬操作符,使⽤的⽅式是 a&&b
&& 两边的表达式都是真的时候,整个表达式才为真,只要有⼀个是假,则整个表达式为假。
如:实现一个代码,表示 “如果⽉份是3⽉到5⽉,是春天”
int main() { int month = 0; scanf("%d", &month); if (month >= 3 && month <= 5) { printf("春季\n"); } return 0; }
这⾥ month >= 3 && month <= 5 表达的意思就是
month既要⼤于等于3,⼜要⼩于等于5,必须同时满⾜。
3. || 或运算符
运算规则
|| 就是或运算符,也就是或者的意思, || 也是⼀个双⽬操作符,使⽤的⽅式是 a || b ,
||两边的表达式只要有⼀个是真,整个表达式就是真,两边的表达式都为假的时候,才为假。
例:实现一个代码,表示 “⼀年中⽉份是12月或1月或2月是冬天”
int main() { int month = 0; scanf("%d", &month); if (month == 12 || month == 1 || month == 2) { printf("冬季\n"); } return 0; }
4. 代码练习:闰年的判断
输⼊⼀个年份year,判断year是否是闰年
首先我们要知道 闰年判断的规则:
1. 能被4整除并且不能被100整除是闰年
2. 能被400整除是闰年
#include <stdio.h> //代码1 int main() { int year = 0; scanf("%d", &year); if (year % 4 == 0 && year % 100 != 0) printf("是闰年\n"); else if (year % 400 == 0) printf("是闰年\n"); return 0; } //代码2 int main() { int year = 0; scanf("%d", &year); if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) printf("是闰年\n"); return 0; }
5. 短路
如果左边的表达式满⾜逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。
if(month >= 3 && month <= 5)
我们发现,表达式中&& 的左操作数是 month >= 3 ,右操作数是 month <= 5 ,
当左操作数 month >= 3 的结果是0的时候,即使不判断 month <= 5 ,整个表达式的结果也是0(不是春季)。
所以,对于&&操作符来说,左边操作数的结果是0的时候,右边操作数就不再执⾏。整个表达式就为假。
对于 || 操作符是怎么样呢?
if(month == 12 || month==1 || month == 2)
如果month == 12,则不⽤再判断month是否等于1或者2,整个表达式的结果也是1(是冬季)。 所以, || 操作符的左操作数的结果不为0时,就⽆需执⾏右操作数。整个表达式依然为真。
像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进⾏计算的运算称为短路求值。
#include <stdio.h> #include <stdio.h> int main() { int i = 0,a=0,b=2,c =3,d=4; i = a++ && ++b && d++; //i = a++||++b||d++; printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d); return 0; }
分析:
首先分析 i = a++ && ++b && d++;
这部分:a++
先使用 a
的值(0)进行逻辑运算,然后 a
的值增加 1 变为 1。因为 0 在逻辑运算中为假,所以整个逻辑表达式的后续部分不再计算。所以 b
和 d
的值不会发生变化,最终 a
变为 1,b
仍为 2,c
为 3,d
为 4。
五、switch 语句
除了 if 语句外,C语⾔还提供了 switch 语句来实现分⽀结构。
switch 语句是⼀种特殊形式的 if...else 结构,⽤于判断条件有多个结果的情况。
根据表达式 expression 不同的值,执⾏相应的 case 分⽀。如果找不到对应的值,就执⾏ default 分⽀。
switch (expression) { case value1: statement case value2: statement default: statement }
注:
• switch 后的 expression 必须是整型表达式
• case 后的值,必须是整形常量表达式
1. 练习:输⼊任意⼀个整数值,计算除3之后的余数
如果使⽤switch语句完成,如下:
#include <stdio.h> int main() { int n = 0; scanf("%d", &n); switch (n % 3) { case 0: printf("整除,余数为0\n"); break; case 1: printf("余数是1\n"); break; case 2: printf("余数是2\n"); break; } return 0; }
上述代码,我们要注意:
1. case 和后边的数字之间必须有空格
2. 每⼀个 case 语句中的代码执⾏完成后,需要加上 break ,才能跳出这个switch语句。
2. switch语句中的break
前⾯的代码中,如果我们去掉case语句中的break,会出现什么情况呢?
#include <stdio.h> int main() { int n = 0; scanf("%d", &n); switch (n % 3) { case 0: printf("整除,余数为0\n"); case 1: printf("余数是1\n"); case 2: printf("余数是2\n"); } return 0; }
看一下运行结果
10除以3本来余数是1,但是我们发现程序运⾏的结果多了⼀⾏“余数是2”的打印。
这是为什么呢?
原因是
switch 语句也是分⽀效果的,只有在 switch 语句中使⽤ break 才能在跳出 switch 语句,如果某⼀个 case 语句的后边没有 break 语句,代码会继续玩下执⾏,有可能执⾏其他 case语句中的代码,直到遇到 break 语句或者 switch 语句结束。就⽐如上⾯的代码就执⾏了 case 2 中的语句。
所以在 switch 语句中 break 语句是⾮常重要的,能实现真正的分⽀效果。
当然, break 也不是每个 case 语句都得有,这就得根据实际情况来看了。
下面我们就来个练习:
输⼊⼀个1~7的数字,打印对应的星期⼏
例如:
输⼊:1 输出:星期⼀
输⼊:2 输出:星期⼆
输⼊:3 输出:星期三
输⼊:4 输出:星期四
输⼊:5 输出:星期五
输⼊:6 输出:星期六
输⼊:7 输出:星期天
代码实现:
#include <stdio.h> int main() { int day = 0; scanf("%d", &day); switch (day) { case 1: printf("星期⼀\n"); break; case 2: printf("星期⼆\n"); break; case 3: printf("星期三\n"); break; case 4: printf("星期四\n"); break; case 5: printf("星期五\n"); break; case 6: printf("星期六\n"); break; case 7: printf("星期天\n"); break; } return 0; }
如果我们想
输⼊1-5,输出的是“⼯作⽇”;
输⼊6-7,输出“休息⽇”
那我们的代码就可以这样实现了:
#include <stdio.h> int main() { int day = 0; scanf("%d", &day); switch (day) { case 1: case 2: case 3: case 4: case 5: printf("⼯作⽇\n"); break; case 6: case 7: printf("休息⽇\n"); break; } return 0; }
✅通过上面的练习,
我们发现应该根据实际的情况,适当加break,才能正确完成实际的需求。
3. switch语句中的default
当switch 后的表达式中的值⽆法匹配代码中的 case 语句的时候,
这时候要不就不做处理,要不就得在 switch 语句中加⼊default ⼦句。
如打印星期的练习,如果 day 的输⼊不是1~7的值,如果我们要提⽰:输⼊错误,
则可以这样完成代码:
4. switch语句中的case和default的顺序问题
我们会想,在 switch 语句中 case ⼦句和 default ⼦句有要求顺序吗? default 只能放在最后吗?
其实,在 switch 语句中 case 语句和 default 语句是没有顺序要求的,
只要你的顺序是满⾜实际需求的就可以。不过我们通常是把 default ⼦句放在最后处理的。
————————————————————————————————————
那么以上就是分支语句中if 和 switch 的用法了,
下期博客会给大家讲解循环语句中for 、 while 、 do while 的用法,希望对你有用~