如何从交换机内部打破循环?

时间:2009-09-14 06:51:09

标签: c++ loops syntax switch-statement break

我正在写一些看起来像这样的代码:

while(true) {
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        break; // **HERE, I want to break out of the loop itself**
    }
}

有没有直接的方法呢?

我知道我可以使用一个标志,并通过在切换之后放置条件中断来从循环中断。我只是想知道C ++是否已经有了一些构造。

19 个答案:

答案 0 :(得分:145)

您可以使用goto

while ( ... ) {
   switch( ... ) {
     case ...:
         goto exit_loop;

   }
}
exit_loop: ;

答案 1 :(得分:51)

前提

以下代码应被视为不良格式,无论语言或所需功能如何:

while( true ) {
}

支持参数

while( true )循环形式不佳,因为它:

  • 打破while循环的隐含合约。
    • while循环声明应明确说明 only 退出条件。
  • 意味着它永远循环。
    • 必须阅读循环中的代码才能理解终止条款。
    • 永久重复的循环会阻止用户从程序中终止程序。
  • 效率低下。
    • 有多个循环终止条件,包括检查“true”。
  • 容易出错。
    • 无法轻松确定将每次迭代始终执行的代码放在何处。
  • 导致不必要的复杂代码。
  • 自动源代码分析。
    • 要查找错误,程序复杂性分析,安全检查或在没有代码执行的情况下自动导出任何其他源代码行为,指定初始中断条件允许算法确定有用的不变量,从而改进自动源代码分析指标。 / LI>
  • 无限循环。
    • 如果每个人总是使用while(true)来表示非无限循环,那么当循环实际上没有终止条件时,我们就失去了简洁沟通的能力。 (可以说,这已经发生了,所以重点是没有意义。)

替代“转到”

以下代码是更好的形式:

while( isValidState() ) {
  execute();
}

bool isValidState() {
  return msg->state != DONE;
}

优点

没有国旗。没有goto。没有例外。容易改变。易于阅读。易于修复。另外代码:

  1. 将循环工作负载的知识与循环本身隔离开来。
  2. 允许维护代码的人轻松扩展功能。
  3. 允许在一个位置分配多个终止条件。
  4. 将终止子句与要执行的代码分开。
  5. 核电站更安全。 ; - )
  6. 第二点很重要。在不知道代码是如何工作的情况下,如果有人让我做主循环让其他线程(或进程)有一些CPU时间,我会想到两个解决方案:

    选项#1

    随便插入暂停:

    while( isValidState() ) {
      execute();
      sleep();
    }
    

    选项#2

    覆盖执行:

    void execute() {
      super->execute();
      sleep();
    }
    

    此代码比嵌入switch的循环更简单(因此更易于阅读)。 isValidState方法应该只确定循环是否应该继续。该方法的主力应该被抽象到execute方法中,该方法允许子类覆盖默认行为(使用嵌入式switchgoto的困难任务)。

    Python示例

    对比贴在StackOverflow上的以下答案(对于Python问题):

    1. 永远循环。
    2. 要求用户输入他们的选择。
    3. 如果用户的输入是“重启”,则继续循环。
    4. 否则,永远停止循环。
    5. 结束。
    6. while True: 
          choice = raw_input('What do you want? ')
      
          if choice == 'restart':
              continue
          else:
              break
      
      print 'Break!' 
      

      对战:

      1. 初始化用户的选择。
      2. 循环,而用户选择的单词是“重启”。
      3. 要求用户输入他们的选择。
      4. 结束。
      5. choice = 'restart';
        
        while choice == 'restart': 
            choice = raw_input('What do you want? ')
        
        print 'Break!'
        

        在这里,while True会导致误导和过于复杂的代码。

答案 2 :(得分:50)

另一种解决方案是将关键字continuebreak结合使用,即:

for (;;) {
    switch(msg->state) {
    case MSGTYPE
        // code
        continue; // continue with loop
    case DONE:
        break;
    }
    break;
}

使用continue语句完成您希望循环继续的每个案例标签,并使用break语句完成应该终止循环的案例标签。

当然,只有在switch语句之后没有其他代码要执行时,此解决方案才有效。

答案 3 :(得分:20)

这样做的一个简洁方法是将其放入函数中:

int yourfunc() {

    while(true) {

        switch(msg->state) {
        case MSGTYPE: // ... 
            break;
        // ... more stuff ...
        case DONE:
            return; 
        }

    }
}

可选(但'不良做法'):如前所述,您可以使用goto,或在交换机内抛出异常。

答案 4 :(得分:13)

AFAIK在C ++中没有“双重中断”或类似的构造。最接近的是goto - 虽然它的名称含义不好,但由于某种原因存在于语言中 - 只要它被谨慎使用,这是一个可行的选择。

答案 5 :(得分:8)

你可以把你的开关放到一个单独的功能中:

bool myswitchfunction()
{
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        return false; // **HERE, I want to break out of the loop itself**
    }
    return true;
}

while(myswitchfunction())
    ;

答案 6 :(得分:7)

即使你不喜欢goto,也不要使用异常来退出循环。以下示例显示了它有多丑:

try {
  while ( ... ) {
    switch( ... ) {
      case ...:
        throw 777; // I'm afraid of goto
     }
  }
}
catch ( int )
{
}

我会在this回答中使用goto。在这种情况下,goto将使代码比任何其他选项更清晰。我希望this问题会有所帮助。

但我认为由于字符串goto,使用while(true)是唯一的选择。你应该考虑重构你的循环。我想以下解决方案:

bool end_loop = false;
while ( !end_loop ) {
    switch( msg->state ) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        end_loop = true; break;
    }
}

甚至以下内容:

while ( msg->state != DONE ) {
    switch( msg->state ) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
}

答案 7 :(得分:5)

在这种情况下,没有用于打破循环的C ++构造。

使用标志来中断循环或(如果适用)将代码提取到函数中并使用return

答案 8 :(得分:2)

你可能会使用goto,但我更愿意设置一个停止循环的标志。然后突破开关。

答案 9 :(得分:2)

不,C ++没有这样的构造,因为关键字“break”已被保留用于退出switch块。或者,带有退出标志的do..while()就足够了。

do { 
    switch(option){
        case 1: ..; break;
        ...
        case n: .. ;break;
        default: flag = false; break;
    }
} while(flag);

答案 10 :(得分:2)

为什么不在你的while循环中修复条件,导致问题消失?

while(msg->state != DONE)
{
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        // We can't get here, but for completeness we list it.
        break; // **HERE, I want to break out of the loop itself**
    }
}

答案 11 :(得分:1)

我想;

while(msg->state != mExit) 
{
    switch(msg->state) 
    {
      case MSGTYPE: // ...
         break;
      case DONE:
      //  .. 
      //  ..
      msg->state =mExit;
      break;
    }
}
if (msg->state ==mExit)
     msg->state =DONE;

答案 12 :(得分:0)

C ++中的break关键字仅终止最嵌套的封闭迭代或switch语句。因此,您无法直接在while (true)语句中突破switch循环;但是你可以使用下面的代码,我认为这是这类问题的一个很好的模式:

for (; msg->state != DONE; msg = next_message()) {
    switch (msg->state) {
    case MSGTYPE:
        //...
        break;

    //...
    }
}

如果您需要在msg->state等于DONE时执行某些操作(例如运行清理例程),请在for循环后立即放置该代码;即如果你现在有:

while (true) {
    switch (msg->state) {
    case MSGTYPE:
        //... 
        break;

    //...

    case DONE:
        do_cleanup();
        break;
    }

    if (msg->state == DONE)
        break;

    msg = next_message();
}

然后改用:

for (; msg->state != DONE; msg = next_message()) {
    switch (msg->state) {
    case MSGTYPE:
        //...
        break;

    //...
    }
}

assert(msg->state == DONE);
do_cleanup();

答案 13 :(得分:0)

令人惊讶的是,考虑到解释的深度,这是多么简单......这就是你所需要的......

bool imLoopin = true;

while(imLoopin) {

    switch(msg->state) {

        case MSGTYPE: // ... 
            break;

        // ... more stuff ...

        case DONE:
            imLoopin = false;
            break;

    }

}

LOL !!真!这就是你所需要的!一个额外的变量!

答案 14 :(得分:0)

while(MyCondition) {
switch(msg->state) {
case MSGTYPE: // ... 
    break;
// ... more stuff ...
case DONE:
   MyCondition=false; // just add this code and you will be out of loop.
    break; // **HERE, you want to break out of the loop itself**
}
}

答案 15 :(得分:0)

最简单的方法是在执行SWITCH之前放一个简单的IF,并且IF测试你退出循环的条件..........就像它可以是

答案 16 :(得分:0)

我遇到了同样的问题并使用旗帜解决了。

bool flag = false;
while(true) {
    switch(msg->state) {
    case MSGTYPE: // ... 
        break;
    // ... more stuff ...
    case DONE:
        flag = true; // **HERE, I want to break out of the loop itself**
    }
    if(flag) break;
}

答案 17 :(得分:-2)

如果我记得很好的C ++语法,你可以为break语句添加标签,就像goto一样。所以你想要的东西很容易写出来:

while(true) {
    switch(msg->state) {
    case MSGTYPE: // ...
        break;
    // ... more stuff ...
    case DONE:
        break outofloop; // **HERE, I want to break out of the loop itself**
    }
}

outofloop:
// rest of your code here

答案 18 :(得分:-3)

  while(true)
  {
    switch(x)
    {
     case 1:
     {
      break;
     }
    break;
   case 2:
    //some code here
   break;
  default:
  //some code here
  }
}