在switch语句中使用continue

130

我想要从以下代码中 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这种方式是否有效?switch语句会忽略continue吗?C和C ++在这里的行为有所不同吗?


你的想法很好,但是上面的循环永远不会执行“do_something()”。 - antik
7
即使控制情况达到A或B,也是这样吗? - Alexander Poluektov
29
我本来想说,Antik关于那个的说法是错误的。如果是A或B的情况,那么会执行do_something()函数。如果没有匹配到任何情况,则会退出。 - Antony Woods
3
@acron,这是预期的行为。 - Matt Joiner
1
我认为这看起来比“goto”更可疑、更令人困惑,因此更具有危害性。 - phoeagon
显示剩余2条评论
6个回答

72

没问题,continue语句与包含它的循环有关,你的代码应该等同于(避免使用跳转语句):

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

但是,如果你期望 break 能够退出循环,正如你的评论所表明的那样(它总是尝试着使用另一个条件,直到其结果为假),你将需要使用不同的结构。

例如:

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

2
“equivalent”只是在语义上等价。编译器生成的代码非常不同。使用switch语句,编译器可以生成跳转表,避免多次比较,因此比逐个元素进行比较要快得多。 - chacham15
@chacham15,为什么编译器不能为两者生成相同的代码? - avakar
@avakar 的 switch 语句会生成跳转表,而另一种表示方法则是一系列逻辑评估。请搜索 Google 跳转表以获取更多信息。 - chacham15
@chacham15,编译器为什么不生成两个if语句的跳转表或者一系列逻辑评估用于switch呢? - avakar
2
@avakar switch语句要求case是常量值,因为与if语句不同,它不能进行相同的优化(注意:我是在一般情况下说话,根据特定要求(例如仅限于const值,仅限于某些逻辑运算符等),可以进行优化,但高度依赖于编译器,结果可能会有所不同)。 - chacham15

36

是的,continue语句将被switch语句忽略,并继续执行循环条件的测试。 我想分享一下Ritchie的C编程语言参考书中的这个摘录:

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

continue语句仅适用于循环,而不适用于switch语句。在循环内部的switch中的continue导致下一次循环迭代。

我不确定C++是否适用。


21

没问题 - 就像在 if 语句中使用一样。当然,你不能在选项结构内部使用 break 跳出循环。


1
@Neil,好的,误解已消除。 - Matt Joiner
我认为这仍然很令人困惑。 - Tim Schaeffer
你可以使用 break 关键字从 switch 语句中跳出循环,就像你可以从内部循环中跳出外部循环一样,例如:break 2; 或者 break 3; 来跳出更高层级的循环等等... - Mouradif
1
@KiJéy,我找不到任何关于这个的参考资料,在多年的C编程中,我从未见过任何支持这个的编译器...你在哪里找到的? - arjunyg
2
哇,抱歉,我看到这个是在PHP中,以为这是个老的做法,结果原来就是PHP本身的... - Mouradif
显示剩余2条评论

9

这段文本在语法上是正确的,风格也不错。

良好的风格要求每个 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...
}

...没问题。


3
抱歉打扰了,但我想补充一点,在 switch case 结构中,使用 exit 函数来结束程序通常也是可行的。 - Vality
1
好的,我要像弗兰肯斯坦博士一样指出,default:并不一定要是最后/底部的条目 - 正如这个问题所指出的那样... - SlySven
1
@SlySven:从词法上讲,它并没有区别,但如果你没有不让它持续的好理由,那就让它持续下去。如果在其他地方使用,通常会令人困惑。 - SF.
2
@SF。嗯,我很容易想象出这种情况,即将default:案例放在最后而不是最前面更有意义。比如,“除非你得到以下不寻常的值,否则请执行此操作,并按照以下方式处理它们”。 - Ruslan

6

虽然从技术上讲这些跳转是有效的,但它们会掩盖控制流,特别是continue语句。

我会把这种技巧作为最后的手段,而不是首选。

那么怎么样呢?

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

它更短并以更清晰的方式执行其功能。

1
抱歉让你感到困惑,Alexander。这段代码仅用于演示,我相信我的实际代码结构有充分的理由。 - Matt Joiner
2
@Matt:这可能意味着一个更加混淆的结构... :) - visitor

-5

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


7
switch语句位于while循环内部,因此使用continue是完全合法的。 - Rick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接