顺序结构:一行一行往下写
选择结构(if else)
第一种写法:
expr为true的话,进入if语句
第二种写法:
expr为true的话,进入if语句中执行,如果expr为false的话,进入else语句中执行
要么进入if语句,要么进入else语句,是不可能同时进去的。
第三种写法:
expr1为true的话,进入if语句中执行
expr2为true的话,进入else if语句中执行
如果前两个都是false的话,进入else语句中执行
从上到下依次判断,哪个表达式为true就进入哪个
如果expr1和expr2都为true的话,从上到下判断,只进入第一个为true的if语句中,其他分枝就不判断了,直接跳出了。
if else的代码示例
写代码:
题目1:
思路:
题目2:
和字符比较或者和整数比较都可以,因为字符就是整数
题目3:
如果还有其他的要求,就增加else if,else if的个数可以好多个,实际上最好不要超过3个,转成表驱动
如果我们什么都不输入,直接回车, 也可以!
判断输入的年份是不是闰年
选择结构(switch case)
expr结果必须是整数
因为它要拿这个整数的结果和v1比较,如果比对成功,就进入,执行完,break直接跳出整个switch了。
如果这个结果和v1,v2,v3都不匹配的话,就执行default的语句,执行完,break直接跳出这个switch
我们可以这么写:
也可以写成字符,因为字符就是整数
但是不可以写成字符串!!!:
也不可以写成浮点数:况且浮点数也不能直接比较大小的
下面这么写,会把case1,case2,case3的语句都执行了,然后才break跳出整个switch语句,因为前面的case后面没有加break!!!:
代码应用:
统计年份和指定日期的总天数
我们看下面这题要求:
两种选择结构汇编指令比较
一个函数里如果使用if else的分枝或者switch分枝超过3次以上,我们就要转成相应的表驱动。
应用场景的区别:
switch只能做等值比较,有限集合的整数的等值比较,适用于菜单,月份
效率差别?
我们转到if else if的反汇编看看
我们从头开始分析
拿a和10(0Ah)比较,比较的结果放入cmp中
如果不相等的话,执行jne跳转,往04C43B3h跳转
如果相等的话,就不跳转了,就进入{}了,执行b++的3行指令
如果执行完了b++的三行指令,就跳转jmp,跳转到04C43DFh
04C43DFh在哪?在switch语句的头
也就是说,10==a了,进这个if语句,执行完b++后,直接无条件jump跳出整个if else语句了
这是符号我们的预期的
如果10!=a,是跳转到04C43B3h
04C43B3h在哪里?
在下一个分枝
拿20(14h)和a比较,结果的情况和刚才所述一样,以此类推下去。
我们看看switch的反汇编
我们从头开始看
switch在进行比较的时候,先把a的值放到寄存器,又把寄存器的值放到栈上的临时量,然后拿这个临时量的值和10比较,如果和10相等,执行je,跳转,就跳转到04C4405h,
如果和10不相等,也就是je在这里不跳转,继续和14h,也就是20比较了,如果相等,就跳转到04C4410h
如果继续不相等的话,就和1Eh,也就是30,比较,以此类推。
如果所有的都不相等,无条件跳转到04C4426h
break执行的是jmp。
直接跳出整个switch
也就是说,在进行元素等值比较的时候,if else和switch差别不大。
唯一的区别是:if else如果比较相等的话,不用做指令跳转,直接执行++的指令了。
而switch比较如果相等的话,要做指令的跳转,跳转到指定地址的指令上去执行。
如果比较不相等的话,if else 是跳转到下一个分枝的第一个指令的地址上继续判断。而在switch里面,如果不相等的话,不用做指令的跳转,进行向下判断,因为它把所有的case的判断都放在前面switch这里进行统一判断了。
从汇编上看,它们的差别不是很大,if else的每个分枝都要做一个cmp比较,有多少个分枝,就有多少个cmp。在switch中,case里面也是要拿当前switch里面的值和所有的case进行比较。有多少个case,就有多少个cmp
如果分枝过多的话,做的cmp和指令跳转的次数就非常多,这是比较慢的操作,而且是从上到下一个一个的比较,比较花费的时间复杂度是O(n)
如果我们转成哈希表的表驱动的方式进行分枝选择的话,哪怕这个分枝有1万个,时间复杂度是O(1),这是由哈希表决定的。