4、逻辑操作符:&& ,|| !
逻辑操作符提供逻辑判断功能,逻辑操作符可用于构建更复杂的表达式,逻辑操作符主要有如下三个:
(1)!:逻辑取反运算符(改变单个表达式的真假)
(2)&&:与运算符,就是并且的意思(两侧的表达式只有都为真时,才为真;只要有一个为假,就为假)
(3)||:或运算符,就是或者的意思(两侧至少有一个表达式为真,则为真,否则为假)
注意:逻辑操作符的结果也是0或1
4.1逻辑取反运算符!
逻辑取反运算符!是一个单目操作符(即:只有一个操作数)
a !a
非0 0
0 1
逻辑取反运算符想要表达的意思是,如果一个表达式a为真,那么取反即:!a,则!a为假。
示例:有一个变量叫flag,如果flag为假,则输出I am a student,此时代码就可以这样写:

如果flag为真,!flag就是假;如果flag为假,则!flag为真
4.2 &&与运算符
a b a&&b
非0 非0 1
非0 0 0
0 非0 0
0 0 0
&&就是与运算符,是并且的意思,&&是一个双目运算符,使用的方式是:a&&b,&&两边的表达式都是真的时候,整个表达式才为真,只要有一个为假,则整个表达式为假。
示例:月份是3月到5月,是春季,代码实现为:
cpp
//逻辑操作符:&&(与)
#include<stdio.h>
int main()
{
int month = 0;
scanf("%d", &month);
if (month >= 3 && month <= 5)
{
printf("春季\n");
}
return 0;
}
上述代码表示的意思是:month既要大于等于3,也要小于等于5,二者必须同时满足。
4.3或操作符||
a b a ||b
非0 非0 1
非0 0 1
0 非0 1
0 0 0
||就是或运算符,是或者的意思,||也是一个双目操作符,使用的方式是:a||b两边的表达式只要有一个是真,整个表达式就是真,两边的表达式都为假的时候,才为假
示例:月份是12月或者1月或者2月是冬季,代码实现为:
cpp
//逻辑操作符:||(或)
#include<stdio.h>
int main()
{
int month = 0;
scanf("%d", &month);
if (month ==12 || month==1 ||month==2)
{
printf("冬季\n");
}
return 0;
}
4.4短路
C语言逻辑运算符还有一个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是可以保证的。
如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值,这种情况称为"短路"。
如上面写的代码:
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(因为:对于||操作符而言,只要左右操作数有一个为真,则整个表达式结果就为真,只有左右操作数都为假的时候,整个表达式的结果才为假)
综合案例:
cpp
//逻辑运算符的短路现象
#include<stdio.h>
int main()
{
int i = 0;
int a = 0;
int b = 2;
int c = 3;
int d = 4;
i = a++ && ++b && d++;
printf("a=%d b=%d c=%d d=%d", a,b,c,d);
return 0;
}
结果:

结果分析:
因为a++是后置++,所以是:先使用,后+1,则此时a++为0,为假,此时因"短路"现象,则表达式:a++ && ++b &&d++表达式的结果就是0,
所以该表达式的++b,d++就不会执行。于是结果如上图所示。
5、switch语句
C语言中,除了if语句实现分支结构外,还提供了switch语句来实现分支结构
switch语句是一种特殊形式的if...else结构,用于判断条件有多个结果的情况。它把多重的else if改成更易用、可读性更好的形式。
语法格式:
switch (expression){
case value1: statement
case value2:statement
...
default: statement
}
上面代码中,根据表达式expreesion不同的值,执行相应的case分支。如果找不到对应的值,就执行default分支
注意:
(1)switch后的expression必须是整型表达式
(2)case后的值,必须是整型常量表达式
switch只能用于整型和字符型数据(因为字符型数据都有ASCII码值)
5.1if语句和switch语句的对比
案例:输入一个int型数据,计算模3(即:%3)之后的余数
用if语句实现代码:
cpp
//if语句实现:输入一个int型数据,计算模3(即:%3)之后的余数
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
if (n %3== 0)
{
printf("余数为0\n");
}
else if (n % 3 == 2)
{
printf("余数为2\n");
}
else
{
printf("余数为1\n");
}
return 0;
}
结果举例:

用switch语句实现:
cpp
//switch语句实现:输入一个int型数据,计算模3(即:%3)之后的余数
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
switch (n % 3)
{
case 0:
printf("余数为0\n");
break;
case 1:
printf("余数为1");
break;
case 2:
printf("余数为2");
break;
}
return 0;
}
结果举例:

上述switch代码,我们需要注意:
(1)case和后边的数字之间必须有空格
(2)每一个case语句中的代码执行完成后,需要加上break,才能跳出switch语句
5.2switch语句中的break
如果去掉上述switch语句中的break会发生什么呢?如下述代码所示:
cpp
//switch语句实现:输入一个int型数据,计算模3(即:%3)之后的余数
#include<stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
switch (n % 3)
{
case 0:
printf("余数为0\n");
break;
case 1:
printf("余数为1");
case 2:
printf("余数为2");
break;
}
return 0;
}
结果:

当输入7时,预期结果是:余数为1,那我什么结果是:余数为1余数为2呢?原因是:switch语句也是有分支效果的,只有在switch语句中使用break才能跳出switch语句,如果某一个case语句的后边没有break语句,代码会继续往下执行,这时有可能执行其他case语句中的代码,直到遇到break语句或者switch语句结束,比如上面的这个代码
所有在switch语句中break语句是非常重要的,能实现真正的分支效果。
具体来说,break也不是每一个case语句都要有,这就得根据实际情况来看。
比如:输入:1~5的数字,输出的是"工作日";输入:6~7的数字,输出"休息日"
代码:
cpp
//输入: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;
}
结果举例:

5.3switch语句中的default
在使用switch语句的时候,我们经常遇到一种情况,比如:switch语句后的表达式中的值无法匹配代码中的case语句的时候,这时候要不就不做处理,要不就得在switch语句中加入default子句。
switch (expression){
case value1: statement
case value2:statement
default: statement
}
switch后边的expression的结果不是value1,也不是value2的时候,就会执行default子句。
在这个案例"输入:1~5的数字,输出的是"工作日";输入:6~7的数字,输出"休息日""中,如果输入的day的值不在1~7之间,那我们可以这样提示:"输入错误,请输入1~7的数字"
代码:
cpp
//输入:1~5的数字,输出的是"工作日";输入:6~7的数字,输出"休息日",使用default
#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;
default:
printf("输入错误,请输入1~7的数字\n");
break;
}
return 0;
}
结果示例:

5.4switch语句中的case和default的顺序问题
在switch语句中case子句和default子句有顺序要求吗?default只能放在最后吗?
其实在switch语句中case语句和default语句是没有顺序要求的,只要你写的顺序是满足实际要求的就可以。
我们通常是把default子句放在最后处理的