如何摆脱开关内的循环?

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

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

有没有直接的方法来做到这一点?

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

前提

以下代码应该被认为是不好的forms,不pipe语言或所需function如何:

 while( true ) { } 

支持参数

while( true )循环是不好的forms,因为它:

  • 打破一个while循环的隐含合约。
    • while循环声明应明确说明唯一的退出条件。
  • 意味着它永远循环。
    • 必须阅读循环中的代码才能理解终止子句。
    • 循环重复的循环将阻止用户从程序中终止程序。
  • 效率低下
    • 有多个循环终止条件,包括检查“真”。
  • 容易出错。
    • 无法轻松确定在哪个位置放置代码,这些代码将始终为每次迭代执行。
  • 导致不必要的复杂的代码。

替代“转到”

下面的代码是更好的forms:

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

优点

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

  1. 从循环本身中分离循环工作负载的知识。
  2. 允许维护代码的人轻松地扩展function。
  3. 允许在一个地方分配多个终止条件。
  4. 将终止子句从要执行的代码中分离出来。
  5. 对核电厂更安全。 😉

第二点很重要。 不知道代码是如何工作的,如果有人问我做主循环让其他线程(或进程)有一些CPU时间,那么有两个解决scheme:

选项1

快速插入暂停:

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

选项#2

覆盖执行:

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

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

Python示例

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

  1. 永远循环。
  2. 要求用户input他们的select。
  3. 如果用户的input是“重新启动”,则继续循环。
  4. 否则,永远停止循环。
  5. 结束。

 while True: choice = raw_input('What do you want? ') if choice == 'restart': continue else: break print 'Break!' 

与:

  1. 初始化用户的select。
  2. 循环,而用户的select是单词“重新启动”。
  3. 要求用户input他们的select。
  4. 结束。

 choice = 'restart'; while choice == 'restart': choice = raw_input('What do you want? ') print 'Break!' 

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

你可以使用goto

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

另一种解决方法是使用关键字continuebreak ,即:

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

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

当然这个解决scheme只有在switch语句后没有额外的代码才能执行。

一个干净利落的方法就是把这个function变成一个function:

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

可选地(但是“坏习惯”):如已经暗示的那样,你可以使用goto,或者在交换机内部抛出exception。

AFAIK在C ++中没有“双重中断”或类似的构造。 最接近的将是一个goto – 虽然它的名字有一个不好的内涵,但是它存在于语言中是有原因的 – 只要谨慎和谨慎地使用它,这是一个可行的select。

你可以把你的开关放到一个单独的函数中,像这样:

 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()) ; 

即使你不喜欢转到,也不要使用exception来退出循环。 下面的例子显示了它可能是多么的丑陋:

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

我会在这个答案中使用goto 。 在这种情况下, goto将使代码更清晰,然后再select其他选项。 我希望这个问题会有所帮助。

但我认为使用goto是唯一的select,因为stringwhile(true) 。 你应该考虑重构你的循环。 我会假设以下解决scheme:

 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 ... } 

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

要么使用一个标志来中断循环,要么(如果合适的话)将你的代码提取到一个函数中并使用return

你可能会使用goto,但是我宁愿设置一个停止循环的标志。 然后跳出开关。

为什么不修复你的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** } } 

我认为;

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

最简单的方法是在做SWITCH之前先做一个简单的IF,然后IFtesting你退出循环的条件……….尽可能简单

C ++中的break关键字只能终止最嵌套的迭代或switch语句。 因此,你不能在switch语句中直接跳出while (true)循环; 但是你可以使用下面的代码,我认为这是一个很好的模式,这种types的问题:

 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(); 

这令我感到惊讶,这是多么简单,这是考虑到解释的深度…这是所有你需要的…

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

大声笑!! 真! 这就是你所需要的! 一个额外的variables!

 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** } } 

我得到了同样的问题,并使用一个标志解决。

 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; } 

不,C ++没有这样的构造,因为关键字“break”已经保留用于退出切换块。 另外一个do..while()与退出标志可能就足够了。

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

如果我记得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 
  while(true) { switch(x) { case 1: { break; } break; case 2: //some code here break; default: //some code here } }