精华内容
下载资源
问答
  • switch语句

    万次阅读 多人点赞 2019-02-17 19:36:16
    switch语句从字面上讲,可以称为开关语句,当然理解上不要以为就只有开和关,可以想象它是一个多路开关。它是一种多分支结构。 switch语句的语法形式为: switch(整型表达式) { case 常量表达式1:语句1 case ...

    1. 语句结构

    语法形式

    switch语句从字面上讲,可以称为开关语句,当然理解上不要以为就只有开和关,可以想象它是一个多路开关。它是一种多分支结构。

    switch语句的语法形式为:

    switch(整型表达式)
    {
        case 常量表达式1:语句1
        case 常量表达式2:语句2
        //……
        case 常量表达式n-1:语句n-1
        default:语句n
    }

    解读整型表达式

    switch后面的小括号是一个整型表达式,这与if不同。if条件表现的是相互对立的两种状态,而对于多分支结构的switch,是用多个整数值表现多种选择。if条件的对立性总是相对于0而言,所以只要某种数据类型的表达式能够表示0值,便可以充当if语句的条件,但是switch中的表达式的值需要对应到不同的处理入口,其相当于入口编号,所以限制以用整型数表示是明智的。

    例如,下面的代码错误地用浮点类型作switch的表达式,因而会引起编译错误:

    float f= 4.0;
    switch (f) {            //错误
        //……
    }

    处理入口

    “case常量表达式:”即处理入口(也称其为“标号”),常量表达式相当于入口编号,入口编号是不能重复的,所以每一个case的常量表达式的值必须互不相同。

    例如,下面的代码是某个switch语句的局部,其case处理入口出现相同常量值,导致了编译错误:

    case 'A' :cout<<"this is A\n";
    case 'B' : cout<<"this is 65\n"; //错误,A等于ASCII码的65

    处理入口编号不能重复,但可以颠倒。也就是说,入口编号的顺序不重要。各个case(包括default)的出现次序可任意。例如:

    swtich(a)
    {
        case 3: b=1; break;
        default: b=2; break;    //正确
        case 1: b=3; break;
    }

    default处理入口:如果switch后面的整型表达式不能匹配任何一个预定的处理入口,那么若有default处理入口,就转入该入口,否则就退出switch语句,什么也不做。

    2. switch嵌套

    switch语句可以嵌套,也就是在switch语句中的入口处理语句中又包含了switch语句。case与default标号是与包含它的最小的switch相联系的。例如:
     

    int i,j;
    //……
    switch(i)
    {
        case 1 ://
        case 2 :
        switch(j)
        {    //嵌套switch
        case 1:
        case 2:
        default:
        }
        case 3:
    }

    switch(j)中的标号(入口编号)虽然与外面的switch(i)中的标号相同,但编译器不会混淆。

    需要switch嵌套是基于switch中的入口语句可以是语句集合,而语句集合是可能需要开关语句作进一步编程处理的。

    3. 用好break

    全程顺序性

    在if语句中,if与else属下各自描述的语句是彼此独立的。但是在switch语句中,每个case只是标定处理入口,各个入口的语句并不排他。因此,switch语句中的全部处理入口描述的语句构成了一个顺序执行的动作序列。例如,下列代码描述一个五级计分的程序:

    switch(grade){
        case 'A': cout<<"Excellent\n";
        case 'B': cout<<"Very Good\n";
        case 'C': cout<<"Good\n";
        case 'D': cout<<"Satisfactory\n";
        case 'E': cout<<"Minimally Acceptable\n";
        default : cout<<"Error\n";
    }
    

    当变量grade取'D'值时,将输出:

    Satisfactory

    Minimally Acceptable

    Error

    而不是所想象的单一的Satisfactory字串。

    break的排他性

    为了让switch中处理入口的语句具有入口独立性,从而有更多的描述灵活性,语言中专为switch语句配备了break语句。在switch语句中遇上break便意味着终止switch语句的执行,这就自然地构成了各个入口语句的互斥。改写上述代码,在每个入口处理的最后填上break语句,便得到:

    switch(grade){
        case 'A': cout<<"Excellent\n";break;
        case 'B': cout<<"Very Good\n";break;
        case 'C': cout<<"Good\n";break;
        case 'D': cout<<"Satisfactory\n";break;
        case 'E': cout<<"Minimally Acceptable\n";break;
        default : cout<<"Error\n";
    }
    

    这时候,当变量grade取'D'时,将只输出对应的成绩描述字串:

    Satisfactory

    switch语句中的最后一条语句的下一句便是出口了,面对的是switch语句终止后的下一条语句,所以就没有必要再用break特地退出了。

    放弃使用的效果

    break语句是在switch语句中人为添加的,而不是默认的,这就多了一些编程操作而显得“笨拙”。一些评论家一次而攻击switch语句“太土”。但正由于加不加是可选的,给switch一些编程的灵活性。例如,频繁输入一个整数n以决定输出n个相同字串“Hello.”便可以有一种用switch语句的更好选择:

    //方法1
    for (int n; cin>>n;)//反复输入整数n
    {
        for(int i=1;  i<=n; i=i+1)//循环控制输出n个字串(1≤n≤3)
            cout<<"Hello."
        cout<<"\n";
    }
    
    //方法2
    for(int n; cin>>n;)
    {
        switch(n){
        case 3: cout<<"Hello."//都没有用break
        case 2: cout<<"Hello."
        case 1: cout<<"Hello."    
    }
        cout<<"\n";
    }

    按这两种方法,则输入:

    2 1 3 0 3 

    都能得到结果:

    Hello.Hello.

    Hello.

    Hello.Hello.Hello.

     

    Hello.Hello.Hello.

    方法1在循环语句中嵌套使用了1~n的for循环语句,以决定输出语句执行的次数。不管怎么说,针对每次输入的整数,都要做n次条件判断。

    方法2在循环语句中使用了开关语句,它通过直接转向执行,完成n次字串输出。

    显然在上述代码中,循环控制结构所付出的代价相对多分支转向结构要大,若数据量很大,则会带来明显的性能差别。

    由于n值很小,使用多分支语句时,通过安排处理的入口编号而使前后语句得到共享,语句简化且易懂。

    选择使用的效果

    break在switch语句中,对每个case分支都是可选的,也就是说,有些可以有,有些可以没有。因为有了这样的特性,编程变得更灵活。例如:

    switch(ch){
        case'-': b=-b;//无break
        case'+': a=a+b;break;
        case'*': a=a*b;break;
        case'/': a=a/b;
    }

    首先要明白,在C++中,并不是只有整型数才可以做加减的。代码中a、b实体如果是大对象,做负号操作可能远比减法操作的代价小,减法操作可能比加法操作还要耗费精力,或者根本没有该数据类型的减法操作。因此,做减法不如预先做反向操作,再做加法划算。

    break注解

    break是一个关键字,该关键字独立构成一条语句,其功能是在switch、for、while、do-while语句中,跳出结构而转向执行吓一条语句。或者说break语句强行终止上述语句的执行。对于if语句,其if-else结构中的语句块本身就是排他性的,所以没有必要用break去干预。

    展开全文
  • 技术大佬:我去,你写的 switch 语句也太老土了吧

    万次阅读 多人点赞 2020-03-01 09:02:53
    但当我看到他们当中有一个人写的 switch 语句时,还是忍不住破口大骂:“我擦,小王,你丫写的 switch 语句也太老土了吧!” 来看看小王写的代码吧,看完不要骂我装逼啊。 private static String createPlayer...

    昨天早上通过远程的方式 review 了两名新来同事的代码,大部分代码都写得很漂亮,严谨的同时注释也很到位,这令我非常满意。但当我看到他们当中有一个人写的 switch 语句时,还是忍不住破口大骂:“我擦,小王,你丫写的 switch 语句也太老土了吧!”

    来看看小王写的代码吧,看完不要骂我装逼啊。

    private static String createPlayer(PlayerTypes playerType) {
        switch (playerType) {
            case TENNIS:
                return "网球运动员费德勒";
            case FOOTBALL:
                return "足球运动员C罗";
            case BASKETBALL:
                return "篮球运动员詹姆斯";
            case UNKNOWN:
                throw new IllegalArgumentException("未知");
            default:
                throw new IllegalArgumentException(
                        "运动员类型: " + playerType);
    
        }
    }
    

    看完上述代码后,你是不是会发出这样的感慨——“代码写得很好,没有任何问题啊!”是不是觉得我在无事生非,错怪了小王!但此时我要送上《了不起的盖茨比》中的一句话:

    我年纪还轻,阅历不深的时候,我父亲教导过我一句话,我至今还念念不忘。 “每逢你想要批评任何人的时候, ”他对我说,“你就记住,这个世界上所有的人,并不是个个都有过你拥有的那些优越条件。”

    哈哈,这句话不光是让你看的,也是给我看的。是时候冷静下来谈谈上述 switch 语句的老土问题了。

    看到上图了吧,当不小心删掉 default 语句后,编译器就会报错,提示:“没有返回语句”,为了解决这个问题,我们可以新建一个 player 变量作为返回结果,就像下面这样:

    private static String createPlayer(PlayerTypes playerType) {
        String player = null;
        switch (playerType) {
            case TENNIS:
                player = "网球运动员费德勒";
                break;
            case FOOTBALL:
                player = "足球运动员C罗";
                break;
            case BASKETBALL:
                player = "篮球运动员詹姆斯";
                break;
            case UNKNOWN:
                throw new IllegalArgumentException("未知");
        }
    
        return player;
    }
    

    当添加了 player 变量后,case 语句中就需要添加上 break 关键字;另外在 switch 语句结束后,返回 player。这时候,编译器并不会提示任何错误,说明 default 语句在这种情况下是可以省略的。

    从 JDK 12 开始(本例使用的是 JDK 13),switch 语句升级了,不仅可以像传统的 switch 语句那样作为条件的判断,还可以直接作为一个返回结果。来对小王的代码进行改造,如下所示:

    private static String createPlayer(PlayerTypes playerType) {
       return switch (playerType) {
            case TENNIS -> "网球运动员费德勒";
            case FOOTBALL -> "足球运动员C罗";
            case BASKETBALL -> "篮球运动员詹姆斯";
            case UNKNOWN ->  throw new IllegalArgumentException("未知");
        };
    }
    

    够 fashion 吧?不仅 switch 关键字之前加了 return 关键字,case 中还见到了 Lambda 表达式的影子,中划线和箭头替代了冒号,意味着箭头右侧的代码只管执行无须 break。

    并且,default 语句变成了可选项,可有可无,不信?你也动手试试。

    新的 switch 语句足够的智能化,除了有上述的 3 个优势,还可以对枚举类型的条件进行校验。假如在 PlayerTypes 中增加了新的类型 PINGPANG(乒乓球):

    public enum PlayerTypes {
        TENNIS,
        FOOTBALL,
        BASKETBALL,
        PINGPANG,
        UNKNOWN
    }
    

    此时编译器会发出以下警告:

    意思就是 switch 中的 case 条件没有完全覆盖枚举中可能存在的值。好吧,那就把 PINGPANG 的条件加上吧。来看一下完整的代码:

    public class OldSwitchDemo {
        public enum PlayerTypes {
            TENNIS,
            FOOTBALL,
            BASKETBALL,
            PINGPANG,
            UNKNOWN
        }
    
        public static void main(String[] args) {
            System.out.println(createPlayer(PlayerTypes.BASKETBALL));
        }
    
        private static String createPlayer(PlayerTypes playerType) {
            return switch (playerType) {
                case TENNIS -> "网球运动员费德勒";
                case FOOTBALL -> "足球运动员C罗";
                case BASKETBALL -> "篮球运动员詹姆斯";
                case PINGPANG -> "乒乓球运动员马龙";
                case UNKNOWN -> throw new IllegalArgumentException("未知");
            };
        }
    }
    

    switch 语句变成了强大的 switch 表达式,美滋滋啊!那假如一个运动员既会打篮球又会打乒乓球呢?

    private static String createPlayer(PlayerTypes playerType) {
        return switch (playerType) {
            case TENNIS -> "网球运动员费德勒";
            case FOOTBALL -> "足球运动员C罗";
            case BASKETBALL,PINGPANG -> "牛逼运动员沉默王二";
            case UNKNOWN -> throw new IllegalArgumentException("未知");
        };
    }
    

    就像上述代码那样,使用英文逗号“,”把条件分割开就行了,666 啊!

    不服气?switch 表达式还有更厉害的,-> 右侧还可以是 {} 括起来的代码块,就像 Lambda 表达式那样。

    private static String createPlayer(PlayerTypes playerType) {
        return switch (playerType) {
            case TENNIS -> {
                System.out.println("网球");
                yield "网球运动员费德勒";
            }
            case FOOTBALL -> {
                System.out.println("足球");
                yield "足球运动员C罗";
            }
            case BASKETBALL -> {
                System.out.println("篮球");
                yield "篮球运动员詹姆斯";
            }
            case PINGPANG -> {
                System.out.println("乒乓球");
                yield "乒乓球运动员马龙";
            }
            case UNKNOWN -> throw new IllegalArgumentException("未知");
        };
    }
    

    细心的同学会发现一个之前素未谋面的关键字 yield,它和传统的 return、break 有什么区别呢?

    先来看官方的解释:

    A yield statement transfers control by causing an enclosing switch expression to produce a specified value.

    意思就是说 yield 语句通过使一个封闭的 switch 表达式产生一个指定值来转移控制权。为了进一步地了解 yield 关键字,我们可以反编译一下字节码:

    private static String createPlayer(NewSwitchDemo3.PlayerTypes playerType) {
        String var10000;
        switch(playerType) {
            case TENNIS:
                System.out.println("网球");
                var10000 = "网球运动员费德勒";
                break;
            case FOOTBALL:
                System.out.println("足球");
                var10000 = "足球运动员C罗";
                break;
            case BASKETBALL:
                System.out.println("篮球");
                var10000 = "篮球运动员詹姆斯";
                break;
            case PINGPANG:
                System.out.println("乒乓球");
                var10000 = "乒乓球运动员马龙";
                break;
            case UNKNOWN:
                throw new IllegalArgumentException("未知");
            default:
                throw new IncompatibleClassChangeError();
        }
    
        return var10000;
    }
    

    编译器在生成字节码的时候对 yield 关键字做了自动化转义,转成了传统的 break 语句。这下清楚了吧?

    但是,话又说出来,那些看似 fashion 的代码也不过是把部分秀技的工作交给了编译器,还可能存在对旧版本不兼容、对队友不友好的问题——代码土点就土点呗,没准是最实用的。

    “不好意思,我为昨天早上的嚣张向你道歉。。。。。。”我向小王发送了一条信息。

    好了,我亲爱的读者朋友,以上就是本文的全部内容了,希望能够博得你的欢心。

    最后,一定会有不少读者想要问我怎么学习 Java 的,那我干脆就把我看过的优质书籍贡献出来:

    1)入门版:《Head First Java》、《Java 核心技术卷》

    2)进阶版:《Java编程思想》、《Effective Java》、《Java网络编程》、《代码整洁之道》

    3)大牛版:《Java并发编程》、《深入理解Java虚拟机》、《Java性能权威指南》、《重构》、《算法》

    就先介绍这么多,希望对那些不知道看什么书的同学有所帮助。

    对了,我介绍的这些书籍,已经顺便帮你整理好了,你可以在我的原创微信公众号『沉默王二』回复『书籍』获取哦

    有收获?希望老铁们来个三连击,给更多的同学看到这篇文章

    展开全文
  • switch 语句

    2020-11-19 23:01:59
    switch 语句 switch 语句的使用场景,与前面学习的 if - else if - else 语句一致。但是从代码角度来看,switch 语句比 if - else if - else 语句更为优美,但是又有自身的限制,在判断时,没有 if - else if - else...

    switch 语句

    switch 语句的使用场景,与前面学习的 if - else if - else 语句一致。但是从代码角度来看,switch 语句比 if - else if - else 语句更为优美,但是又有自身的限制,在判断时,没有 if - else if - else 语句那么灵活。

    switch 语句,先是判断一个变量与一系列值中的某个值是否相等,每个值对应一个分支,如果相等,则进入这个分支。

    语法

    switch 语句的语法格式如下:

    switch(expression){
        case value :
           语句1
           break; //可选
        case value :
           语句2
           break; //可选
        // 你可以有任意数量的case语句
        default : //可选
           语句3
    }
    

    switch 语句有如下规则:

    1.switch 语句中的变量类型可以是: byte、short、int 或者 char。从 Java SE7 开始,switch 还支持字符串 String 类型,但是使用 String 类型时,case 标签必须为字符串常量或字面量;

    2.switch 语句可以拥有多个 case 语句,每个 case 后面跟一个要比较的值和冒号;

    3.case 语句中 value 的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量;

    4.当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句

    5.当遇到 break 语句时,switch 语句终止,继续执行 switch 语句后面的语句。case 语句不一定要包含 break 语句,如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句;

    6.switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。当 case 语句的值和所有变量值都不相等时,执行 default 分支。default 分支不需要 break 语句。

    注意:switch 语句执行时,一定会先进行匹配。如果匹配成功,则返回当前 case 的值,再根据是否有 break,判断是否继续进行匹配判断。

    案例:

     public static void main(String args[]) {
         char grade = 'B';
         switch (grade) {
             case 'A':
                 System.out.println("优秀");
                 break;
             case 'B':
                 System.out.println("良好");
                 break;
             case 'C':
                 System.out.println("中等");
                 break;
             case 'D':
                 System.out.println("及格");
                 break;
             case 'F':
                 System.out.println("你需要再努力努力");
                 break;
             default:
                 System.out.println("未知等级");
         }
         System.out.println("你的等级是 " + grade);
     }
    

    执行结果:

    良好
    你的等级是 B
    

    代码说明:变量 grade 的值为 B ,进入 case B 的分支,打印“良好”,然后遇见了 break 语句,结束 switch 语句。继续执行 switch 后的语句,最后打印“你的等级是 B”。

    展开全文
  • Switch语句

    2020-03-26 22:17:27
    相对于 if 语句而言,switch 语句可以更方便地应用于多个分支的控制流程。C89 指明,一个 switch 语句最少可以支持 257 个 case 语句,而 C99 则要求至少支持 1023 个 case 语句。然而,在实际开发环境中,为了程序...

    switch

    相对于 if 语句而言,switch 语句可以更方便地应用于多个分支的控制流程。C89 指明,一个 switch 语句最少可以支持 257 个 case 语句,而 C99 则要求至少支持 1023 个 case 语句。然而,在实际开发环境中,为了程序的可读性与执行效率,应该尽量减少 switch 语句中的 case 语句。
    除此之外,switch 语句与 if 语句不同的是,switch 语句只能够测试是否相等,因此,case 语句后面只能是整型或字符型的常量或常量表达式;而在 if 语句中还能够测试关系与逻辑表达式。
    不要忘记在 case 语句的结尾添加 break 语句
    在 switch 语句中,每个 case 语句的结尾不要忘记添加 break 语句,否则将导致多个分支重叠。当然,除非有意使多个分支重叠,这样可以免去 break 语句。下面我们来看一个实际示例。

    #include <stdio.h>
    void print_week(unsigned int day);
    void print_week(unsigned int day)
    {
        switch(day)
        {
            case 1:
                printf("Monday\n");
                break;
            case 2:
                printf("Tuesday\n");
                break;
            case 3:
                printf("Wednesday\n");
                break;
            case 4:
                printf("Thursday\n");
                break;
            case 5:
                printf("Friday\n");
                break;
            case 6:
                printf("Saturday\n");
                break;
            case 7:
                printf("Sunday\n");
                break;
            default:
                printf("error\n");
                break;
        }
    }
    int main (void)
    {
        print_week(3);
        return 0;
    
    

    不要忘记在 switch 语句的结尾添加 default 语句
    在 switch 语句中,default 语句主要用于检查默认情况,或者处理错误情况,如果在 switch 语句中去掉 default 语句,那么 switch 语句将失去对默认情况与错误情况的处理能力。所以,奉劝大家不要偷懒,老老实实把每一种情况都用 case 语句来完成,而把真正对默认情况的处理交给 default 语句来完成。即使程序真的不需要 default 处理,也应该保留此语句:
    不要为了使用 case 语句而刻意构造一个变量
    在实际编程应用中,switch 中的 case 语句应该只用于处理简单的、容易分类的数据。如果数据并不简单,却为了使用 case 语句而刻意构造一个变量,那么这种变量很容易令我们得不偿失。因此应该严格避免这种变量,并使用 if/else 结构来处理这类程序,如下面的示例代码所示:
    尽量将长的 switch 语句转换为嵌套的 switch 语句
    有时候,当一个 switch 语句中包括很多个 case 语句时,为了减少比较的次数,可以把这类长 switch 语句转为嵌套 switch 语句,即把发生频率高的 case 语句放在一个 switch 语句中,作为嵌套 switch 语句的最外层;把发生频率相对低的 case 语句放在另一个 switch 语句中,放置于嵌套 switch 语句的内层。

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,960
精华内容 10,784
关键字:

switch语句