目录
文前声明:
接上回,我们初入c语言的大门,了解了最基础的预备知识,即便并不完整,但对于现在的我们来说也是足够的。在接下来,我们会继续讲解c语言中不可缺少的一个体系:流程控制。
我们都知道,c语言的基本组成单位是函数,而函数中包含着条条语句,这其中,就包含着流程控制中的三个重要语句类别:转向语句,循环语句和分支语句。在下面的文章中,我将以自己的理解揭开它们面庞萦绕的面纱。
一些基本运算符的了解
在了解判断语句前,我们需要先了解一些运算符:
比较运算符
写法 | 内涵 | 写法 | 内涵 |
== | 等于(低) | != | 不等于 (低) |
> | 大于(高) | >= | 大于等于(高) |
< | 小于(高) | <= | 小于等于(高) |
它们所呈现的意义都是数字,变量或是表达式间的大小关系的比较,所以这些判断符号也被叫做比较运算符。他们之间存在的优先级顺序也已经标入表中(低者优先级相同,高者优先级相同),以此便于分析一个语句中同时存在多个比较运算符时的窘境。(倘若多个运算符同为“高”或“低”,则从左到右依次计算)。
逻辑运算符
写法 | 描述 | 示例 | 内涵 |
&& | 与 | a&&b | ab同为true,结果为1;否则为false |
|| | 或 | a||b | a或b有一个为true,结果为1;否则为false |
! | 非 | !a | 若a为true,!a则为0;逆否同理 |
在理解逻辑运算符之前,我们需要先知道在逻辑运算中,“true”代替数字“1”,“false”代替数字“0”。
而我们逻辑运算符又是对逻辑量进行运算与判断,所以逻辑运算的结果自然而然也只有“0”和“1”。
当然,逻辑运算的运算符优先级各不相同:
!>&&>||
同时,我们还有一个需要注意的小知识点:逻辑运算是自左向右的,倘若左边已经可以决定该次运算的结果,那我们将不会在进行运算符右边的判断,举个例子:
if(3<7||8>5){
//需要执行的语句
}else
{
//需要执行的语句
}
我们先不看其他,只关注于“3<7||8>5”,大家注意到了其中的“||”是意为“或”的逻辑运算符,我们在前面已经知道在判断“a或b”逻辑值是否为true的最低符合条件是“a或b有一个为true”,与此同时我们的“3<7”也是成立的,所以计算机将不再判断8>5是否仍然为true。
很神奇对吧?我们计算速度如此之快的机器居然也会有偷懒的时候,但这其实也有一定的道理在其中:随着我们学到更深处的时候,我们的程序编译和运行速率会因为语句数量的庞大而缓慢下来,所以这个时候就需要我们进行更优化的算法,以此来让计算机进行更快速的演算。在之后我可能会讲到的算法案例中,这些都能一一体现出来。
那么,现在开始步入我们今天要讲的主题:
分支语句(条件判断语句)
1.if语句
相信大家都注意到了上面所举到的例子,在学习初期所接触到的不同的课程中,我们或多或少都会见到过if语句。他是让我们进行判断后所可以执行指令的语句,而if语句则是分支语句的一种,因为它可以通过判断的结果对接下来程序的走向起到一定的导向作用,使程序产生像树状一样的多重走向,故而被称为分支语句。而上面对逻辑运算符的解释所用到的语句,正是if语句的基本格式。其中的“3<7||8>5”是if语句的判断条件。
其中,if所携带的“块”后({}中所包含的这部分内容,就被称为是一个块),else语句是可以不写的,倘若想起到一定的分支效果,那么使用附加的else语句是一个很好的选择。
同时,if语句结束时不需要“;”,而且在if语句的大括号后只跟随一条语句的情况下,大括号是可以被省略的,此时后面紧随的语句就是if语句的一部分,例如:
if(判断条件)//内容
else //内容
通过Dev中的调试功能我们可以得知if语句的运行步骤:还用上面的例子做说明,倘若“3<7||8>5”成立,那么if语句就执行if后的内容,而略过了else语句的跟随;倘若“3<7||8>5”不成立,那么就会略过if语句后紧随的大括号中的内容,直接读取else语句后大括号的内容,执行命令。
所讲到的成立与否的条件,是在看到判断条件只是计算表达式时,表达式的结果为0时为真,非0则为假。
所以,现在的你是否已经理解到一部分if语句身为分支语句的“分支效果”呢?
if语句的神奇之处还不止于此,但我们先对if语句暂停讲解,不要着急,对if语句的阐述会在今天的这篇博客中叙述殆尽,在后来讲会更加加深你对分支语句的理解。
2.switch-case语句
如果说if语句的最基本用法是将一个树干上的一根枝条延续,难以更加体现出树上节节蔓枝的特点,那么switch-case可以完美的体现出多路分支的精髓。
基础的switch-case语句如下:
switch(控制表达式){
case常量:
语句1
case常量:
语句2
...
default:
语句n
}
一切都讲究优略得当,switch-case语句虽然有着多路分支的效果,但是却有很多被限制的地方:控制表达式的结果只能是整数型结果,且case语句后的常量是整型常量或整型常量的表达式,而不可以是const一类的只读常量(const是一个加在定义变量类型前的最前端的关键字,可比喻为一个锁定变量使其不可被二次更改的桎梏,作用是保护变量的值防止被更改)。
switch-case的运行步骤也一定程度的阐述了树状分支的理念:在常量表达式计算得值后,程序会跳转到匹配的case(分支标号)。分支标号只是switch的路标,在执行语句后就会顺序执行到下一条case去。倘若前面的分支标号后的常量没有与控制表达式相匹配的值,那么就会跳转到default语句中执行所谓的”不得值“的指令。
对switch语句的基本阐述就这么多,那么在了解switch的语句后,if语句的基础作用显得十分单薄,那么它还有什么更加有价值的利用么?
这就该谈到我们之前悄悄藏起来的if语句的知识点,if语句的级联结构,如下图:
if(条件){
//内容
}else{
if(条件){
//内容
}else{
...
}
}
if-else-if的级联结构相比于switch-case更像是一条树枝的蔓延,它的结构特点使得两者之间的区别更加鲜明,也使得c语言更加的多样化,这甚是神奇。
极限结构中的else,是和最近的if相匹配的。
我们若想从级联语句中的某一步中退出,可以在起始位置设立一个变量:exit,使得在这一步的末尾之前,if语句已经发挥完它的作用,我们便可以令exit等于某个值,使得我们的程序编译过程中退出接下来的级联结构,这是我们最常用的手段,如下:
if(exit = 值) {
break;
}
当然,我们还有别的方法:
转向语句
1.break
break只需要作为一个单列的关键字,在所需要退出结构后加一句
break;
即可,并不需要太过复杂的操作。
在switch-case语句中,我们倘若在读到所需的case语句后,希望停止接下来继续读下列case的情况,那我们就可以在case语句所作的语句结尾加一句break来终止操作。
break语句的作用,是直接跳出该循环系统。
有个小的特殊情况,在if-else-if级联结构中,break不一定是百试百灵的,有时候不可以直接break,因为有时候会因为没有满足循环体的体系就因为break而退出循环。
2.continue
continue的用法和break相同,也是在所需要退出结构后加一句
continue;
即可,但是作用却有着极小的差异:
continue是跳出该次循环而不同于break是直接跳出整个循环。continue 跳过这一轮的循环后不完全退出循环,回到循环体重新判断条件
这一小小的差异会造成完全不同的结果,在未来的算法中我们会更加深刻的感受到它的不同。
在转向语句中,还有一个不被人们所推崇的存在:
3.goto
若想要退出某个多重循环体系,需要在循环程序末输入goto 语句标号,然后将“语句标号”:打在退出后想要到达的位置即可,如下图所示:(合法的一串字符都可以被认定是语句标号)
if(条件){
//内容
}else{
if(条件){
//内容
}else{
//内容
goto 语句标号
}
}
语句标号:
//内容
goto语句的强大在于不仅仅可以向后腾挪程序的进行,还可以将语句标号放到goto之前的位置。
也正是因为goto语句的灵活性,它在一定程度上破坏了程序员编译程序时所遵循的层层递进的理念,使得程序的控制流难以跟踪,在将来制作庞大源文件时,难以寻找到问题的错误且难以让接手的程序员理解,所以goto语句是不被建议使用的。但它强大的实用性是任何人都无法否定的。
原本是定于一篇文章完成,但对于现在叙述能力有待提高的我来说可能难以完成太大程度的码字工作,所以为了确保质量,循环语句将留到下篇讲解,流程控制将分为两部分进行解读。
那么,我今天的博客到此为止,感谢您认真的看完了本篇小白编写的博客,以上均为本人理解,如有错误欢迎评论区指出。
虽然基础薄弱,但今天仍是在幻想成为大佬的一天。
人生无需仰望,自己亦是风景。