在switch语句中使用Continue


88

我想从switch语句的中间跳到以下代码中的循环语句:

while (something = get_something())
{
    switch (something)
    {
    case A:
    case B:
        break;
    default:
        // get another something and try again
        continue;
    }
    // do something for a handled something
    do_something();
}

这是有效的使用方式continue吗?是continue通过忽略声明switch语句?C和C ++的行为是否有所不同?


您的想法很好,但是上面的循环将永远不会执行do_something()
antik 2010年

5
即使控制达到情况A或情况B?
亚历山大·波列科托夫

18
我要说的是,antik对此是错误的。对于A或B,则将执行do_something()。默认情况下它将保释。
安东尼·伍兹2010年

3
@acron,这是预期的行为
Matt Joiner 2010年

1
我认为这看起来比可疑性更令人困惑goto
phoeagon 2013年

Answers:


56

没关系,该continue语句与封闭循环相关,并且您的代码应等效于(避免使用此类跳转语句):

while (something = get_something()) {
    if (something == A || something == B)
        do_something();
}

但是,如果您希望break退出循环,如您的注释所建议的那样(它总是再次尝试其他操作,直到结果为false),您将需要其他结构。

例如:

do {
    something = get_something();
} while (!(something == A || something == B));
do_something();

2
“等效”仅在语义上。编译器生成的代码非常不同。与switch语句,编译器可以生成其避免多重比较,因此比对各元件1由1比较快得多跳转表
chacham15

@ chacham15,为什么编译器无法为两者生成相同的代码?
avakar

@avakar switch语句生成跳转表,而另一个表示形式是一系列逻辑求值。谷歌跳转表获取更多信息。
chacham15'2

@ chacham15,是什么阻止编译器为两个if语句或该开关的一系列逻辑求值生成跳转表?
avakar 2015年

1
@avakar switch语句要求大小写为常数,因为if语句不是这种情况,它不能进行相同的优化(注意:在一般情况下,有可能满足某些要求(例如,仅使用const值) ,仅某些逻辑运算符等)进行优化,但它高度依赖于编译器和YMMV。
chacham15

20

是的,没关系-就像在if语句中使用它一样。当然,您不能使用abreak从开关内部跳出循环。


ifcontinueor的行为没有影响break。你是什​​么意思?
马特·乔纳

@Matt我的意思是在两种情况下都将继续循环。

1
@Neil,好的,避免了混乱。
马特·乔纳

1
@KiJéy我为此找不到任何参考,在很多C语言编程中,我从未见过任何支持此功能的编译器……您究竟在哪里找到它?
arjunyg

2
哇,对不起,我在PHP中看到了它,以为这是一种古老的做法,原来只是PHP ...
KiJéy18年

15

是的,继续语句将被switch语句忽略,并进入要测试的循环条件。我想分享Ritchie的The C Programming Language参考中的摘录:

continue语句与关联break,但使用较少;它会导致封闭的下一次迭代forwhiledo循环开始。在while和中do,这意味着测试部分将立即执行;在中for,控制转到增量步骤。

Continue语句仅适用于循环,不适用于switch语句。一个continue内部的switch一个循环内导致下一个循环迭代。

对于C ++,我不确定。


8

从语法上讲是正确的,从样式上讲还可以。

好的样式要求每个case:语句都应以下列其中之一结尾:

 break;
 continue;
 return (x);
 exit (x);
 throw (x);
 //fallthrough

此外,请case (x):立即关注

 case (y):
 default:

是允许的-捆绑几个效果完全相同的案例。

还有什么怀疑是错误的,就像if(a=4){...} 你当然需要封闭环路(whilefordo...while)的continue工作。它不会循环回到case()一个人。但是一个类似的构造:

while(record = getNewRecord())
{
    switch(record.type)
    {
        case RECORD_TYPE_...;
            ...
        break;
        default: //unknown type
            continue; //skip processing this record altogether.
    }
    //...more processing...
}

...没关系。


2
非常抱歉,您可以进行死尸招募,但是我想补充一点,exit通常以结束切换案例为好。

1
好吧,我将把所有的弗兰肯斯坦医生都放在这里,并指出default:并不一定要是最后一个/底部的条目-正如这个问题所指出的那样……
SlySven

1
@SlySven:词汇上没有,但是如果您没有充分的理由不坚持下去,那就坚持下去。如果在其他地方使用,通常会造成混乱。
SF。

1
@SF。好吧,我可以轻松地想象在什么情况下将default:案例放在第一个而不是最后一个更有意义。就像“执行此操作,除非获得以下异常值,否则应按以下方式进行处理”。
Ruslan

5

尽管从技术上讲是有效的,但所有这些跳跃都模糊了控制流程-尤其是continue声明。

我会把这种技巧作为最后的手段,而不是第一个。

怎么样

while (something = get_something())
{
    switch (something)
    {
    case A:
    case B:
        do_something();
    }        
}

它更短,以更清晰的方式执行其任务。


1
很抱歉给您带来困惑,Alexander,该代码仅用于演示,我有充分的理由(我相信)我代码中的实际结构。
马特·乔纳

2
@Matt:那可能意味着一个更加混乱的结构... :)
访客

-2

这可能是个兆位,但您可以使用continue 2

一些php builds / configs将输出以下警告:

PHP警告:“继续”定位开关等效于“中断”。您是要使用“继续2”吗?

例如:

$i = 1;

while ($i <= 10) {
    $mod = $i % 4;
    echo "\r\n out $i";
    $i++;
    switch($mod)
    {
        case 0:
            break;
        case 2:
            continue;
            break;
        default:
            continue 2;
            break;
    }
    echo " is even";
}

这将输出:

out 1
out 2 is even
out 3
out 4 is even
out 5
out 6 is even
out 7
out 8 is even
out 9
out 10 is even

经过PHP 5.5及更高版本测试。


3
这不是PHP问题。
杰弗里

-4

Switch不被视为循环,因此您不能在switch中的case语句中使用Continue


3
switch语句在while循环内,因此continue完全有效。
瑞克
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.