嘁,都2020了,你咋还在单纯的使用if-else

在高级语言中,基本上都提供了像if-elseswitch-case 这样的条件语句,方便大伙进行判断——引导程序走向。我们在写程序时,常常需要指明两条或者更多的执行路径,使得程序执行时,能够选择其中一条路径,去执行相应的语句,产生对应的结果 —— 这也是条件语句在程序中的作用。


if-else的例子

各位在初学C语言时,应该都写过这样一个程序:输出每个月的天数

//C语言代码片段
int Days(int months, int years){
	int days;
	if(months==1 || months==3 || months==5 || months==7 || months==8 || months==10 || months==12){
		days=31;
	}else if(months==2){
		if((years%4==0 && years%100!=0) || years%400==0){
			days=29;
		}else{
			days=28;
		}
	}else if(months==4 || months==6 || months==9 || months==11){
		days=30;
	}else{
		printf("输入错误!请重新输入:\n");
		Days(months,years);
	}
	return days;
}

这个程序虽是“耳熟能详”的,但后来看着未免感觉有些【繁琐】,多层if-else的嵌套不仅使得可读性降低,还会大大影响程序运行的效率。。。


if-else的问题

从上面就可以看出,if-else判断语句使用起来非常简单,但是在稍微复杂的逻辑场景下,对if-else的频繁使用(或说:滥用)就会容易导致整个项目的可读性和可维护性大大降低。

我们可以试想一下,如果项目中出现了一种新的情况,那么我们要在原有的代码基础上继续增加if-else。但是需求是不会减少的。这样恶性循环下去,原本的几个if-else可能在更新了几个版本后变成了几十个,这可真是令人哭笑不得的事。
(当然,现在也许你的公司会有硬性要求,或者开发模板,那就恭喜你了…)

从设计模式的角度考虑,if-else简直具有了“坏”代码具有的一切:

  • 数据和实现逻辑强耦合
  • 扩展麻烦,维护性低

改善if-else

if-else并非是需要全部被代替的,确切的说,我们现在只能去不断的改善它,使他运行的更为【流畅】。

短路符号和三元表达式
前几天笔者还在群里说这两个:短路符号,又叫“逻辑运算符”,在一些简单的场景下,我们完全可以用它来代替if-else(尤其是那些需要“几个条件同时满足”的场景下):
比如这个——判断一个数是不是2的幂

//c++代码片段
class Solution {
public:
  bool isPowerOfTwo(int n) {
  	//如果一个数是 2 的次方数的话,那么它的二进数必然是最高位为1,其它都为 0 ,
  	//那么如果此时我们减 1 的话,则最高位会降一位,其余为 0 的位现在都为变为 1,
  	//那么我们把两数相与,就会得到 0
    return (n > 0) && (!(n & (n - 1)));
  } 
};

我们也可以用三元符号来代替if-else,它是几乎最合适的计算机判断符号(笔者自认为!),尤其适用于多条件复合判断(一层嵌套一层)。不过需要注意的是,大量的三元运算符却容易影响代码的可读性:

比如——判断 n! 结果尾数中零的数量

//java代码片段
public class Solution {
  public int trailingZeroes(int n) {
  	//不断递归
    return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
  }
}

当然,我们还有一种改进方法:如果每种条件下代码逻辑比较多,也可以考虑提前跳出来结束函数——这是借鉴了for循环。

说说switch-case

switch-case是语言自身提供的另一种条件语句,它和if在本质上并没有什么区别,只是代码看上去会更简洁。比如——判断年龄:

goodswitch(age){
	case 10:
		break;
	case 20:
		break;
	case 30:
		break;
	//...
}

但是switch-case无法从根本上解决多个相似条件下需要多次重复的问题。


表驱动法

这个是笔者最为推崇的一种写法,它几乎在大数据量判断、范围区别处理等问题上都有解决方案!

现在让我们再来看文章开头那道题:输出每个月有多少天
我们不妨转换一下思路,每个月份对应一个数字,而月份都是按顺序排列的,所以我们是否可以用一个数组来存储天数,然后用下标来访问?

嘁,都2020了,你咋还在单纯的使用if-else

扫一扫手机访问