在上一篇的学习中,我们初步了解了C语言支持的三种结构和九种控制语句,这篇文章中我们将会详细学习分支循环语句。C语言是结构化的程序设计语言,我们可以通过使用不同的语句搭建不同的结构来达成自己的目的。
在C语言中,我们可以使用if、switch来实现分支结构,使用for、while、do while实现循环结构。
1.操作符
1.1 关系操作符
当我们需要比较一些数值的时候,需要用到关系表达式,其中使用的运算符通常称为关系运算符(关系操作符),主要有以下六个:
> 大于运算符
< 小于运算符
>= 大于等于运算符
<= 小于等于运算符
== 相等运算符
!= 不相等运算符
关系表达式的结果通常返回0或1表示真假,成立则返回1,不成立则返回0。
易错点:相等运算符==和赋值运算符=的效果截然不同,但是很容易被混为一谈,需要经常注意
例如一条if语句的条件是a等于5
if ( a == 5 ) ...
但是因为疏忽把相等运算符和赋值运算符弄混了
if ( a = 5 ) ...
此时a被赋值为5,它的返回值为5,由于5是非零值,所以if判断总是为真
简单提一下,C语言中0表示假,非零值表示真。
另一个需要避免的错误是不宜连用多个关系运算符
a < b < c
上面的这个例子中,如果我们运行代码是不会报错的,但是通常达不到我们想要的效果。原因在于关系运算符是从左到右计算的,所以事实上代码执行的时候是按下面的方式执行的:
( a < b ) < c
按照这样执行,首先判断a是否小于b,结果为真就返回1与c进行比较,结果为假就返回0进行比较
所以如果要实现我们想要的效果,应该这么写:
a < b && b < c
&&是与运算符,逻辑操作符在前面的文章中详细介绍过了,这里不过多赘述。
1.2 条件操作符
条件操作符也叫三目操作符,它是C语言中唯一的一个三目操作符,结构如下:
exp1 ? exp 2 : exp3
它的计算逻辑是,如果exp1为真,exp2计算,计算出的结果是整个表达式的结果;exp1为假,exp3计算,计算出的结果是整个表达式的结果。
2.if语句
2.1 if
if语句是一种很常见的控制语句,它的语法形式如下:
if ( 表达式 )
语句
表达式为真,则执行语句;表达式为假,则不执行语句
2.2 else
如果我们要判断一个数是奇数还是偶数,其中只有两种可能,此时我们需要用到双分支结构
if ( 表达式 )
语句1
else
语句2
在这里我们用if else语句写一段判断奇偶数的代码
#include <stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
if (a % 2 == 0)
printf("%d是偶数\n", a);
else
printf("%d是奇数\n", a);
return 0;
}
2.3 分支中包含多条语句
当条件成立时,我们往往需要程序执行不止一条语句,但if和else语句中默认只控制一条语句,此时需要我们用大括号把需要执行的语句包括起来,才能执行多条语句,如:
#include <stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
if (a % 2 == 0)
{
printf("%d是偶数\n", a);
printf("%d不是奇数\n", a);
}
else
{
printf("%d是奇数\n", a);
printf("%d不是偶数\n", a);
}
return 0;
}
2.4 else if
解决生活的实际问题中,可能出现的结果往往不止两种,此时需要用到多分支结构,例如我们要判断一个数是正数还是负数,再判断是奇数还是偶数时,就需要使用嵌套的if语句
#include <stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
if (a > 0)
{
printf("正数\n");
if (a % 2 == 0)
printf("偶数\n");
else
printf("奇数\n");
}
if (a < 0)
{
printf("负数\n");
if (a % 2 == 0)
printf("偶数\n");
else
printf("奇数\n");
}
if (a == 0)
printf("零\n");
return 0;
}
else还可以和if连用,形成多重判断
#include <stdio.h>
int main()
{
int a = 0;
scanf("%d", &a);
if (a > 0)
{
printf("正数\n");
if (a % 2 == 0)
printf("偶数\n");
else
printf("奇数\n");
}
else if (a < 0)
{
printf("负数\n");
if (a % 2 == 0)
printf("偶数\n");
else
printf("奇数\n");
}
else
printf("零\n");
return 0;
}
以上就是嵌套if语句的语法,使用以上语句我们可以完成更多复杂问题的结果判断
2.5 悬空else问题
如果程序中有多个if语句和else语句,每个else总是和最接近的if匹配
为了避免程序运行错乱达不到我们想要的效果,我推荐每个初学者在编写代码的时候养成良好的代码编写风格,合理运用大括号可以使代码逻辑更加清晰。
3.短路
C语言的逻辑运算符在初识C语言,你必须知道这几个最基础的知识-CSDN博客中已经详细介绍过了,这里我们介绍它的一个特点:逻辑运算符总是先求左侧表达式的值,再求右边表达式的值,这个顺序是固定的。
如果左侧表达式的值可以决定整个表达式的结果,就不再求右侧表达式的值,这种情况称为短路。
例如
if ( a < b && b < c )
当a < b 不成立时,就不再计算 b < c 的结果,整个表达式的结果为0
if ( a < b || b < c )
当 a < b 成立时,也不再计算 b < c 的结果,整个表达式的结果为1
这种仅根据左侧表达式的结果就可以判断整个表达式的真假,不对右侧表达式进行计算的运算称为短路求值。
4.switch语句
在C语言中除了if语句之外,还有switch语句可以实现分支结构。
switch语句适用于多分支中判断条件有多个结果的情况,可以理解为将多重的else if语句改成更清晰易懂的形式,它的结构如下:
switch ( 表达式 )
{
case 值1:
语句
break;
case 值2:
语句
break;
......
default:
语句
}
在switch语句中,根据表达式不同的值,执行对应的case分支,如果没有对应的分支,则执行default分支。
注意:switch后的括号中必须是整型表达式且case后的值必须是整型常量表达式。
每个case分支里的语句执行完毕之后都需要加上break才能跳出switch语句,但是,并不是所有case分支里都必须加上break,我们应该根据实际的情况和具体需求来选择是否使用break。
另外,在switch语句中case子句和default子句并没有顺序要求,但是习惯上我们通常把default子句放在最后。
5.while循环
5.1 if和while的对比
while语句是C语言的三种循环语句之一,它的语法结构和if语句很类似,我们可以作个对比:
if ( 表达式 )
语句;
while ( 表达式 )
语句;
虽然它们的结构十分相似,实际的效果却截然不同,我们可以用if语句和while语句分别写一段代码对比一下它们的效果。
#include <stdio.h>
int main()
{
if(1)
printf("我是if\n");
return 0;
}
执行代码后控制台的情况
把if替换成while后
#include <stdio.h>
int main()
{
while(1)
printf("我是while\n");
return 0;
}
再执行一次代码,控制台开始死循环打印“我是while”
这就是while语句和if语句的区别,while语句可以实现循环的效果。
5.2 while语句的执行流程
首先执行判断表达式判断真假,表达式为假则结果为0,循环直接结束;表达式为真则开始执行循环内的语句,所有语句执行完后再次判断表达式结果是否能够执行下一次循环。
6.for循环
6.1 for循环的语句执行流程
- 首先执行表达式1,初始化循环体中的变量
- 判断表达式2是否成立,不成立则循环结束
- 若表达式2成立,开始执行循环语句
- 语句执行完毕后,执行表达式3,调整循环变量
- 再次判断表达式2是否成立并重复后面的操作
循环过程中,表达式1即初始化循环变量只被执行一次。
6.2 while循环和for循环的对比
首先我们用while循环和for循环分别写出一段代码,完成打印0-10的操作。
while循环和for循环在执行的过程中都有初始化变量,判断表达式,执行语句和调整变量的步骤,但是for循环将步骤高度集成化,便于后期维护代码;while循环的步骤就较为分散。
7.do-while循环
7.1 do-while的语法格式
实际上,在实现循环效果的时候我们使用for循环和while循环较多,do while语句并不常使用,它的语法格式如下:
do
语句;
while ( 表达式 );
7.2 do-while循环的执行流程
while循环和for循环都是先判断,表达式为真才开始执行循环内语句,不满足则不执行循环。
而从图中可以看出do while循环则是先进入循环体执行一次语句,再判断表达式,表达式为真就执行下一次循环,表达式为假就结束循环。所以do while循环至少执行一次语句,这是它和for、while循环最大的区别。
8.break和continue语句
当我们在执行循环语句的时候,如果遇到一些突发状况,例如发生错误等,需要马上结束循环,这时候我们需要用到break语句来帮助我们跳出循环。break的作用是永久的结束循环,只要break被执行,就跳出循环继续执行循环后的语句。
分支或循环后常常不止一条语句,当我们需要在某些情况下只执行一部分语句,将剩下未执行的语句跳过的时候,我们需要用到continue。continue的作用是跳过本次循环中continue后面的所有代码,但是它在for循环中和while循环中有一些区别,这是因为for循环和while循环执行的时候调整变量的步骤位置不同,会导致结果的差异。
我们使用while循环来测试break语句和continue语句
此时break部分被注释掉了,对代码执行无影响,我们来看看输出结果
此时正常的输出了0-10,这时我们将注释去掉
输出结果变成了这样
这是因为循环进行中,当 i = 5 时if判断表达式为真,执行了break语句,直接跳出了while循环,就不会再打印i的内容了
我们继续使用while循环测试continue语句,这里直接将break替换成continue
执行程序后,我们会发现程序进入了死循环,无法结束
这就是上面提到的continue在for循环和while循环中的区别。如果这里使用for循环,则不会导致死循环,而是打印出0-4和6-10所有的数字(没有5)。这是因为while循环中调整变量部分(i++;)在continue之后,导致 i = 5 后无法继续加一,始终为5,就只能重复的执行if语句中的continue。
9.goto语句
当循环多次嵌套之后,因为break一次只能跳出一层循环,想要马上跳出所有的循环只能使用多次break语句,但是C语言中有一种特殊的语法可以帮助我们马上跳出所有的循环,这就是goto语句和跳转标号。goto语句可以帮助我们实现在同一个函数内跳转到设置好的标号处。它的格式如下:
for(...)
{
for(...)
{
for(...)
{
if(...)
goto xxx;
}
}
}
xxx:
像这样,我们只需要使用一条goto语句就可以直接跳出三层循环,十分的方便快捷。但是goto语句不能多用,否则容易导致代码运行错乱。
完