3.12、switch

By | 2016年1月17日

前面我们所学的if(-else)结构可以用于根据不同的条件有选择性的执行不同的语句

但是,如果遇到有较多分支的语句,仍用if-else来处理时

你就需要写一堆的if-else结构,这样写显然很麻烦

在这种情况下,就该switch上场了

我们先来写这样一个程序:让用户输入一个范围在1-7的整数,并且根据这些数字输出周一至周七,1对应周一,2对应周二,依此类推。

请你首先写出一个使用if-else的版本

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int input;
    printf("请输入一个范围在1~7的整数:");
    scanf("%d", &input);

    while(input > 7 || input < 1)
    {
        printf("输入无效,请重新输入:");
        scanf("%d", &input);
    }

    if(1 == input)
    {
        printf("星期一\n");
    }
    else if(2 == input)
    {
        printf("星期二\n");
    }
    else if(3 == input)
    {
        printf("星期三\n");
    }
    else if(4 == input)
    {
        printf("星期四\n");
    }
    else if(5 == input)
    {
        printf("星期五\n");
    }
    else if(6 == input)
    {
        printf("星期六\n");
    }
    else
    {
        printf("星期天\n");
    }

    return 0;
}

可以看出来,这样写真的很长……

当然,这个程序还有另一种写法

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int input;
    printf("请输入一个范围在1~7的整数:");
    scanf("%d", &input);

    while(input > 7 || input < 1)
    {
        printf("输入无效,请重新输入:");
        scanf("%d", &input);
    }

    if(1 == input)
    {
        printf("星期一\n");
    }
    else
    {
        if(2 == input)
        {
            printf("星期二\n");
        }
        else
        {
            if(3 == input)
            {
                printf("星期三\n");
            }
            else
            {
                if(4 == input)
                {
                    printf("星期四\n");
                }
                else
                {
                    if(5 == input)
                    {
                        printf("星期五\n");
                    }
                    else
                    {
                        if(6 == input)
                        {
                            printf("星期六\n");
                        }
                        else
                        {
                            printf("星期天\n");
                        }
                    }
                }
            }
        }
    }

    return 0;
}

这两种的写法本质是相同的

而且正常人都看得出来,使用if-else来进行跳转,写起来实在是麻烦

那么switch又怎么用呢?

switch(表达式)
{
    case 常量表达式1: //一些代码
    case 常量表达式2: //另一些代码
    default ://处理意外情况的代码
}

注意,一个表达式不一定要是一个式子,对于一个数字(如1)或者单独的一个变量foo,它们都是表达式

switch后的表达式的值便是你要判断的值,例如上面的程序中,我们可以写成

switch(input)

switch对于括号内的表达式有要求,它要求表达式的值是一个整型(或者其他能被转换为整型的类型)

对于浮点数,是不能够使用switch的!

这里的每一个case都是一个分支(case在英语中的意思有“情况”),其后面跟随的常量表达式的值便是其对应的值(我们称其为标号,label)

这里要求值是一个常量,例如1,2,3,当然’a’等字符也是可以的,因为它的实质也是数

但是你不能使用变量,甚至是const修饰的“常量”(如const int),类似于case foo的写法是不合法的

除case外,还有一个default,当switch里的值没有匹配与任何一个case时,将跳转到default。

一个switch中只允许有一个default

说了这么多,我们不如看一下代码

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int input;
    printf("请输入一个范围在1~7的整数:");
    scanf("%d", &input);

    while(input > 7 || input < 1)
    {
        printf("输入无效,请重新输入:");
        scanf("%d", &input);
    }

    switch(input)
    {
    case 1:
        {
            printf("星期一\\n");
            break;
        }
    case 2:
        {
            printf("星期二\n");
            break;
        }
    case 3:
        {
            printf("星期三\n");
            break;
        }
    case 4:
        {
            printf("星期四\n");
            break;
        }
    case 5:
        {
            printf("星期五\n");
            break;
        }
    case 6:
        {
            printf("星期六\n");
            break;
        }
    case 7:
        {
            printf("星期天\n");
            break;
        }
        default:break;
    }
    return 0;
}

是不是顿时觉得清晰很多呢?

和if等结构不同,switch中case后面的大括号不是必须的(不管它后面有多少个语句)

这是因为你可以通过下一个case标签很好的区分某一个语句属于哪一个case(即不会引起歧义,请思考if为何会有歧义)

接下来请看case内的代码,我们在每一个分支里都添加了一个break,这是多余的吗?

显然不是,这和switch的执行过程有关

假设上面的程序里我们输入了数字2;

那么switch会根据input(即2)的值跳转到case 2这个分支,然后执行内部的代码(这里是printf)

但是在执行完毕后,switch并不会跳出来执行switch结构后面的代码,而是顺着标号2所在的分支往下执行(即case 3内的代码)

倘若下面的分支都没有添加break,那么程序将会一直执行到标号为7的分支,接着是default内的代码,直到switch结束才会跳出

而加了break之后则会直接跳出switch,这才是我们(在这个程序中)需要的结果

请你删除break,再进行尝试

注意,没有break时执行的顺序和标号大小无关,和case和default也无关,而之和你程序的书写顺序有关

你可以任意的交换case(还有default)的顺序,但是通常我们都按照一定的顺序写,而且将default放在最后

default不是必须的,对于没有default的switch,在没有匹配到任何一个case时会直接跳到switch后面的代码执行

default通常是用于处理“非正常”情况的,在此程序中便是值不在1-7范围内的情况

因此,在这个程序中,我们可以删除default(因为在输入的地方我们便判断了输入值的大小)

但是,出于好习惯,你应该在任何一个switch中都写上default,哪怕你确定一定以及肯定它不会被执行(例如这个程序)

哪怕它确实无事可干!因为这样便说明你已经考虑过了其它的情况

最后,你可能会问,对于数值不是整数(如浮点数)时,又或者判断的是一个数是否在一个范围内又应该如何处理呢?

没有办法,对于复杂的判断,跳转,你只能使用if-else!

最后,请你做以下练习

  • 删除判断input值的循环代码,并在default内给出提示(如果数不在1-7的情况下)
  • 删除switch分支内的break,观察switch的执行
  • 在上一个实验的前提下,调整几个case的顺序,并观察程序的执行

ps:因为case执行了不会自动跳出这个特性,我们可以写出下面的代码

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int input;
    printf("请输入一个范围在1~7的整数:");
    scanf("%d", &input);

    while(input > 7 || input < 1)
    {
        printf("输入无效,请重新输入:");
        scanf("%d", &input);
    }

    switch(input)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        printf("工作日\n");
        break;
    case 6:
    case 7:
        printf("休息日\n");
        break;

    default:break;

    }
    return 0;
}

One thought on “3.12、switch

发表评论

电子邮件地址不会被公开。 必填项已用*标注