0基础C语言自学教程——第三节 分支与循环
目录
什么是语句
语句的分类
分支语句(选择语句)
if语句
悬空else
关于if语句的几点代码书写的建议
switch语句
基本语法形式
break和default语句
注意事项
循环语句
while循环
基本构架
break与continue
for循环
基本语法构建
for循环里的break于continue
for循环书写建议
do....while循环
基本语法形式
特点
do....while循环里的continue与break
goto语句
什么是语句
语句实际上就相当于一个完整的指令。对计算机的指令。
语句的分类
C中的语句可以分为以下五大类:
表达式语句;
函数语句;
控制语句;
复合语句;
空语句。
我们今天就来介绍控制语句。
控制语句可以分为以下三类
分支语句(条件判断语句):if switch
循环语句: for while do.....while
转向语句:goto break return
分支语句(选择语句)
我们的生活中面临着很多选择,也叫不同的分支:
比如,我想做下面的一种选择,我在大学是谈个恋爱还是好好学习?(假如只能够二选一)
它的基本逻辑形式可以是这样的:
(图一)
这就是选择语句。那么我如果想在以代码的方式来实现,应当如何做呢?------答案就是应分支语句。
接下来,我们介绍常用的两种分支语句:if语句和switch语句
if语句
if语句的基本语法形式:
(图二)
需要注意的是,这里的表达式1为判断语句。
还可以是这样两种情况:
即
(图三)
和
(图四)
我们来用代码实现一下:
(图五)
按ctrl+(fn+)f5,让程序运行。
(图六)
现在如果我们输入1,那么将会输出(如图七):
(图七)
那我们输入2呢?(如图八)
(图八)
那有没有人想问了,如果我输入3呢?就是不输入1或者2,结果会怎样?
我们来试一下(如图九)
(图九)
我们发现,它仍然是打印else里面的部分。
原因很简单,就是因为代码执行到 if (a==1) 时,它会判断a是否为1,而它的判断逻辑是这样的:
a若为1,则为真,执行if里面的语句。
a若不为1,则为假,跳过if,直接进入else的部分中,执行else部分的语句。
我们提一嘴,何为真,何为假?
在C语言中,0表示假,非0表示真。
而在vs的环境中,如果条件判断为真,则返回1,如果条件判断为假,则返回0。
也就是说,
当执行到if(a==1)时,进行判断,若条件为真,则返回1,即变成 if(1) ;
否则,返回0,即if(0)。
当为真时,则执行if里的语句,当为假时,则跳过if语句里的内容,执行下面的内容。
我们还可以来看一下下面的代码,以加深理解。
(图十)
我们来分析一下,这个代码是怎么运行的(看图十一)。
(图十一)
那如果我输入20呢?(图十二给出答案)
(图十二)
好。我们下面来看看悬空else。
悬空else
主要意识是说,当有多个else时,else会最先与最近的未被匹配的 if 配对
比如,来看下面一段代码:
(图十三)
请问,它会输出什么?
我们来运行一下看看
(图十四)
发现它什么也没有输出
为啥?
很简单,就是刚刚的原因:else与上面离它最近的未比配的if匹配。
所以,当程序运行到if(a==1)上时,判断为假,跳过if。直接运行到return 0。
里面的if(b==2)和else的语句都是if(a==1)的内容。
也就是说,它等价于下面的代码:(图十五)
(图十五)
如果我们想让其打印出haha ,代码应该是这么写的。
(图十六)
这其实和我们的代码书写规范以及书写习惯有很大的关系。而我们接下来就会给大家讲讲这个东西。
好,我们有关if语句的语法到此为止全部介绍完毕。
关于if语句的几点代码书写的建议
1、每一句的 if 和 else 后面最好都跟上一个大括号,不论有几条语句(哪怕只有一条)。
说一下,这里的{}意为一个代码块,可以理解为一整个语句。
之所以这样建议,有如下几点理由:
1)看着舒服,看着整齐。
2)不会出现像上文说的那样else,if混搭的情况,而加上了{}则不会出现这种情况,并且这种情况正是在书写不规范的情况下产生的。
3)这是一种规范对仗的书写方式,如果再要增加语句的时候不用再去打括号了,极为方便。
4)大大增加可读性。如果不加,如果if或者else后面有语句跟着,很难一眼辨认是否执行(不要不信,这可是笔者亲自实验过,当代码量大、不停地看的时候,你真的会发现,带上大括号看着真的是舒服,哪怕只有一条语句)
5)在未来我们写一些其他的语句的时候,会发现阅读时哪怕是只有一条语句没有{}也看起来是一件很难受的事情,所以不值得提倡。
有这么多好处,为啥不养成好的习惯呢?
如果有人反对说反而看着凌乱,这笔者认为这种观点就跑远了。每一个if/else后面都跟着一个小弟(即{}),那么漂亮而又整齐的缩进,怎么会显得凌乱呢,不应该更显整齐么?
2、我们写出if后如果不跟else,看一下是否跟上else会更能增加代码的可读性。
我们举个例子来理解:
(图十七)
来对比一下,哪一种代码更好?或者说哪一种代码的可读性更高?(当然我们暂时不考虑其能否正常运行)
显然是第2种(即图十七右图)。
因为第一种你一眼看过去很难判断出来返回x还是y,但是如果采用第二种,看着便会舒服地多😀
总的来说,我们的代码写的越对仗、if-else用的越整齐,会显得代码看着越舒服,可读性更高,即我要思考代码下一步该执行哪行的时间减少了。
3、如果写判断是否相等,可以考虑把常数写在左边,变量写在右边。(建议)
if里条件判断是否相等一定要写 ==;
我们如果写if(a==5),如果写成if(a=5),会发现编译器也不会报错。
但是,我条件判断如果写成if(5==a),这个时候我如果写成if(5=a),就是把两个等号写成一个等号时,编译器就会报错,这样就不会自己坑自己了~~哈哈。
不过,我们以后写代码可能都会写成if(!a)这样的形式;不过当我们写成判断是否相等时,把常量写在左边、变量写在右边是避免出错的一种可以考虑采纳的方式。
switch语句
基本语法形式
(图十八)
它有什么用?
来看这样一个输入输出样例:
输入1,输出星期一
输入2,输出星期二
输入3,输出星期三
输入4,输出星期四
输入5,输出星期五
输入6,输出星期六
输入7,输出星期日
这怎么弄?
难不成我们需要一条一条的来用 if 写?
这不太挫了么......?
有没有什么其他更好的方法?
当然是有的,这就是switch语句
我们可以将上面的语句以这样的方式来写:
(图十九)
(注:上图中case2 的case和2中间应当有个空格,笔者图弄好才发现,懒得改了~~哈哈)
我们来运行看一下:
(图二十)
那我如果输入的不是7,而是3呢?
我们来看一下:(如图二十一)
(图二十一)
为啥会输出来的不是星期三,而是这么多一串?
这个就关系到了我们接下来要讲的break语句了。请往下看。
break和default语句
我们回到刚刚的那个话题:
为啥会这样?
因为,switch语句是这样执行的。(如图二十二)
(图二十二)
(呃...上面几个图的return 0应该在switch语句{}的外面,我也是写到这里才发现,读者注意即可,笔者不刻意改了,哈哈~~~~)
那我们要它只输出星期三,应该怎么办呢?
这个时候,break语句的作用就出现了:
(图二十三)
如上图,当遇到break的时候,就会直接跳出switch循环,这样,我们就能只打印 星期三 了。
总结来说,就是:break语句 的实际效果是把语句列表划分为不同的分支部分。
我们标题中还提到了一个关键字:default。这个是什么意思?
我们想一下,如果你所输入的数,当对所有的case都不满足情况的时候,怎么办?
这个时候,程序并不会报错,而是直接跳过所有的case。
但这时如果我们有default的时候,则执行default。
比如,还是上面的例子,我们加上一个default,这个时候,我们输入8,则会执行default里的语句(如图二十四)。
(图二十四)
注意事项
1、为养成好习惯,最好在每一条的case语句中的后面都加上一个break;以防止出现图二十一的那种情况。
2、多个case语句可以共用一条(或者多条)执行语句。
什么意思?比如,我现在需求变了:
我想让输入1~5的时候输出工作日;
在输入6、7的时候输出周末。
难道我每一个case的后面都要跟着一个printf么?
太繁琐,显然不用。
我们可以这样写(如图二十五):
(图二十五)
3、case和default没有强制的位置关系,就是说default不一定要放在最后,放在哪里都可以。
循环语句
说完了选择分支,我们再来说说循环语句。
循环语句包含while循环、do....while循环和for循环
while循环
基本构架
while循环我们之前介绍过,它的基本构架是这个样子的:
(图二十六)
同理,这里的exp1为条件判断语句
循环结构是这样的:
(图二十六)
我们来看这样一个例子:
我们来在屏幕上打印一下1-100的数字:(如图二十七)
(图二十七)
(住:右边的输出只截取了部分,截不下了)
break与continue
下面的图二十八还是借鉴刚刚上面那个图(图二十六)
(图二十八)
for循环
基本语法构建
(图二十九)
(图三十)
我们来简单的举一个例子:
(图三十一)
(图三十二)
所以,毫无疑问,它将会输出0 1 2
(图三十三)
for循环里的break于continue
在for循环里,break和continue的用法与在while循环里相同
我们来看下面一个例子:
(图三十四)
请问,左右两个代码分别会输出什么?
(图三十五)
我们可以看到,左边的正常输出了0-9,但是右边却进入了死循环。
相信通过前面的介绍,读者可以自行分析出原因所在了。
而这个例子,很好的对比了for和while循环的特点。
for循环书写建议
1、在循环体里不要轻易改变循环变量。
2、建议把条件判断写成前闭后开的形式。
具体的来说一下:
第一点的意思:比如,你这样写一个for循环:
for( int i = 0; i < 10; i ++) { if ( i > 5 ) { i = 5; } else { printf( "%d" , i ); } return 0; }
这显然是有bug的,显然是一个死循环。
所以笔者刚刚的意思就是说,在for循环的循环体的内部,不要轻易改变i 的值,因为这样弄不好就弄成了个死循环。
第二个,意思是说,比如我要循环5次,建议写成下面第一行的形式,而不是第二行的形式
for ( int i = 0; i < 5; i++) //建议 for ( int i = 1; i <= 5; i++) //不建议
为什么这样说?因为第一行我们可以一眼看出来就是5次,又或者说是一种标准吧。
需要指出的是,在这里,笔者只是建议,具体的如果写成第二种明显更好的或者有写第二种的需求的当然以更好的方式以及需求优先。
do....while循环
基本语法形式
(图三十六)
特点
这个循环的最大的特点就是循环体会至少执行一次
因使用场景有限,我们不常用。
我们最常用的是for循环。
do....while循环里的continue与break
这里的continue和break与上面我们说的for循环和while循环逻辑相同。
我们就举个例子吧:
(图三十七)
很明显,左边的是先打出10 9 8 7 6,然后接着一个死循环,而右边打印除10 9 8 7 6
goto语句
关于goto语句,我们简单提一下:
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
从理论上, goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环。多层循环这种情况使用break是达不到目的的。因为它只能从最内层循环退出到上一层的循环。
它的作用就是直接去跳转,理论上想到哪就到哪。
我们来举个栗子:
情景是这样的:
现在窗口有提示:您的电脑将在1分钟后关机,除非输入:我是一只猪
(我们这里仅展示关键部分,理解即可)
图(三十八)
那么我如果进入了else,就会goto(到)again那一行,然后继续执行printf里面的代码。
建议大家学完本节内容后可以再去联系联系代码能力,上牛客、洛谷等网站找一些入门的题做一做。比如二分法查找等等。