关于C语言switch这个奇葩的东东。
很多C语言习题中都会有输入考试成绩,判断等级(90-100优,80-89良……0-59不及格)的题目。
首先,刚开始学到分支结构会用if … else if … else if …… else这样的结构,例如:
if (0 = g)
GP[n] = 0;
else if (60 = g)
GP[n] = 1;
else if (70 = g)
GP[n] = 2;
else if (80 = g)
GP[n] = 3;
else GP[n] = 4;
然后呢,又学到switch,则会变成,先除以10,利用趋零截尾的性质,然后把0-5直接合并了……例如:
ch = (int)(g / 10);
if (ch < 6)
{
ch = 5;
}
switch(ch)
{
case 5 : GP[n] = 0;break;
case 6 : GP[n] = 1;break;
case 7 : GP[n] = 2;break;
case 8 : GP[n] = 3;break;
case 9 : GP[n] = 4;break;
case 10 : GP[n] = 4;break;
}
但是呢,其实呢,这个if再把0-5合并 是可以去掉的,利用switch的特性,结果是这样子:
switch(grade/10)
{
case 0 :
case 1 :
case 2 :
case 3 :
case 4 :
case 5 : rank = 'E';
break;
case 6 : rank = 'D';
break;
case 7 : rank = 'C';
break;
case 8 : rank = 'B';
break;
case 9 :
case 10: rank = 'A';
break;
default: puts("Invalid grade");
exit (1);
}
记得在expert C programing中,作者就很BS当初C语言把switch中,每个分支都要加上break;跳出才不致于执行完所有语句。根据作者统计,97%的使用了switch判断分支的代码都是要用上break;的,也是就是说“完全的选择”,而只有剩下的少得可怜的switch会出现不带break;的情况,所以当时sun的编译器会对switch case不带上break;作waning。但是这里或许正是switch不带break;时的用途所在吧。
其实个人看来,使用switch时加上break;已是非常自然的,不加上break;反而觉得有点怪怪的。正如文中所述,前面两种想法是3月的时候做ACM OJ的模拟题时想到的,而第三种方法还是这两天逛论坛时无意才想起来……
不过,话说回来,这个例子是特例,其实在绝大多数时候,我严重地支持expert C programing的作者的。
至于第三种方法效率是否有所提高,我也不得而知。第一种我个人是比较反对的,原因是多重if else判断让人眼花。通常遇到多重分支判断都会使用switch。其实在本文中,第二第三种应该是不相上下的。