这是目录呀
前言
(嘿嘿,我编的,感兴趣可以看一下)很久很久以前,在一个普通的日子里,在一个不起眼的角落里,一个神奇的世界悄然诞生—C语言世界。这里三足鼎立,哪三足?他们就是顺序结构,选择结构和循环结构。他们以独自或合作的方式来把控着这里的秩序。(我们日常所见的事情都可以拆分为这三种结构或者这三种结构的组合。)
1.操作符
1.1 关系操作符
C 语言用于比较的表达式,称为 “关系表达式”(relational expression),里面使用的运算符就称为“关系运算符”(relational operator),主要有下面6个。
>
大于运算符<
小于运算符>=
大于等于运算符<=
小于等于运算符==
相等运算符!=
不相等运算符
❤️关系表达式通常返回0 或1 【是确切的1,不是随机的 非零】,表示真假。
注意:相等运算符== 与赋值运算符= 是两个不一样的运算符,不要混淆。
例如(不报错):
1 if(x = 3) ...
上面示例中,原意是x == 3 ,但是不小心写成x = 3 。这个式子表示对变量x 赋值3 ,它的返回值为3 ,所以if 判断总是为真。
解决办法(让编译器报错): 将变量写在等号的右边。
1 /*报错*/
2 if(3 = x) ...
❤️多个关系运算符不宜连用
1 i < j < k
上面示例中,连续使用两个小于运算符。这是合法表达式,不会报错,但是通常达不到想要的结果,即不是保证变量j 的值在i 和k 之间。因为关系运算符是从左到右计算,所以实际执行的是下面的表达式。
1 (i < j) < k
上面式子中, i < j 返回0 或1 ,所以最终是0 或1 与变量k 进行比较。如果想要判断变量j的值是否在i 和k 之间,应该使用下面的写法。
1 i < j && j < k
&&是 并且 的意思
1.2 条件操作符
条件操作符也叫三目操作符,需要接受三个操作数的,形式如下:
1 exp1 ? exp2 : exp3
条件操作符的计算逻辑是:如果exp1 为真, exp2 计算,计算的结果是整个表达式的结果;如果exp1 为假, exp3 计算,计算的结果是整个表达式的结果。
1.3 逻辑操作符
逻辑运算符提供逻辑判断功能,用于构建更复杂的表达式,主要有下面三个运算符。
!
:逻辑取反运算符(改变单个表达式的真假)。&&
:与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假)。||
:或运算符,就是或者的意思(两侧至少有一个表达式为真,则为真,否则为假)。
1.3.1 逻辑取反运算符 !
a | !a |
---|---|
非0 | 0 |
0 | 1 |
妙:比如,我们有一个变量叫flag ,如果flag为假,那 !flag就是真。如:
1 int flag = 0;
2 if(!flag)
3 {
4 ...
5 }
所以上面的代码的意思就是flag 为假,执行if语句中的代码。
如果flag 为真【非0】, !flag 就是假【0】,如果flag 为假, !flag 就是真。
1.3.2 与运算符&&
a | b | a&&b |
---|---|---|
非2 | 非0 | 1 |
非0 | 0 | 0 |
0 | 非0 | 0 |
0 | 0 | 0 |
&& 是一个双目操作符,使用的方式是a&&b , && 两边的表达式都是真的时候,整个表达式才为真,只要有一个是假,则整个表达式为假。
1.3.3 或运算符||
|| 也是一个双目操作符,使用的方式是a || b , ||两边的表达式只要有一个是真,整个表达式就是真,两边的表达式都为假的时候,才为假。
1.3.4 短路
C语言逻辑运算符还有一个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。
如果左边的表达式满足逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。
对&&来说,如:
1 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时,就无需执行右操作数。
像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进行计算的运算称为短路求值。
2.分支家族
2.1 if语句
2.1.1 if
语法形式
1 if(表达式)
2 语句
if(真) 执行,if(假) 不执行
C语言世界里,0为假,非0为真
2.1.2 else
两条语句的分支
if…else…语句 语法形式
1 if(表达式)
2 语句1
3 else
4 语句2
if(真) 执行 语句1 ,否则【即 if(假)】执行语句2
2.2.3 多条语句的分支
默认在if和else语句中都只控制一条语句
{…}算一条语句
2.2.4 嵌套if
语法形式,如【嵌套在if里】:
1 if(表达式1)
2 {
3 if(表达式2)
4 语句2
5 else
6 语句3
7 }
8 else
9 {
10 语句4
11 }
2~7行【即 被嵌套 的语句】是 语句1,属于 if(表达式1)
又如【嵌套在else里】:
1 if(表达式1)
2 语句1
3 else /*if(表达式3)
4 语句3
5 else
6 语句4*/
被注释部分【即 被嵌套 的语句】是 语句2, 属于 第9行的else
else if 的本质 是 else的嵌套
2.2.5 悬空else问题
else会跟 最接近 的if匹配,不是 以“是否对齐”为标准的!!
例如:
1 if(表达式1)
2 if(表达式2)
3 语句2
4 else
5 语句3
与else 匹配的是 第2行的 if(表达式2)
switch语句
本质:switch 语句是一种特殊形式的 if…else 结构,用于判断条件有多个结果的情况。它把多重的else if 改成更易用、可读性更好的形式。
如:
1 switch(expression)
2 case value1: statement
3 case value2: statement
4 default: statement
上面代码中,根据表达式expression 不同的值,执行相应的case 分支。如果找不到对应的值,就执行 default 分支。
注意:
- switch 后的expression 必须是整型表达式
- case 后的值,必须是整型常量表达式
- case 和后边的数字之间必须有空格
- 只有在switch 语句中使用 break 才能在跳出switch 语句,如果某一个case 语句的后边没有break 语句,代码会继续往下执行,有可能执行其他case语句中的代码,直到遇到break 语句或者switch 语句结束。【入口由case决定,出口由break决定】。如(妙):
1 switch (day)
2 {
3 case 1:
4 case 2:
5 case 3:
6 case 4:
7 case 5:
8 printf("工作日\n");
9 break;
10 case 6:
11 case 7:
12 printf("休息日\n");
13 break;
14 }
15 return 0;
16 }
8
输入day为 1 ,2 ,3 ,4 ,5 时都打印 工作日,为 6 ,7 时都打印休息日
case和default的顺序问题
- 在switch 语句中case 子句和default 子句有要求顺序吗?
- default 只能放在最后吗?
其实,在switch 语句中case 语句和default 语句是没有顺序要求的,只要你的顺序是满足实际需求的就可以。不过我们通常是把default 子句放在最后处理的。