C++ 如何从交换机内部跳出循环?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1420029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to break out of a loop from inside a switch?
提问by jrharshath
I'm writing some code that looks like this:
我正在写一些看起来像这样的代码:
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
break; // **HERE, I want to break out of the loop itself**
}
}
Is there any direct way to do that?
有没有直接的方法可以做到这一点?
I know I can use a flag, and break from the loop by putting a conditional break just after the switch. I just want to know if C++ has some construct for this already.
我知道我可以使用一个标志,并通过在 switch 之后放置一个条件中断来中断循环。我只想知道 C++ 是否已经有一些构造。
采纳答案by Dave Jarvis
Premise
前提
The following code should be considered bad form, regardless of language or desired functionality:
无论语言或所需功能如何,以下代码都应被视为不良形式:
while( true ) {
}
Supporting Arguments
支持论据
The while( true )
loop is poor form because it:
该while( true )
循环是拙劣的形式,因为它:
- Breaks the implied contract of a while loop.
- The while loop declaration should explicitly state the onlyexit condition.
- Implies that it loops forever.
- Code within the loop must be read to understand the terminating clause.
- Loops that repeat forever prevent the user from terminating the program from within the program.
- Is inefficient.
- There are multiple loop termination conditions, including checking for "true".
- Is prone to bugs.
- Cannot easily determine where to put code that will always execute for each iteration.
- Leads to unnecessarily complex code.
- Automatic source code analysis.
- To find bugs, program complexity analysis, security checks, or automatically derive any other source code behaviour without code execution, specifying the initial breaking condition(s) allows algorithms to determine useful invariants, thereby improving automatic source code analysis metrics.
- Infinite loops.
- If everyone always uses
while(true)
for loops that are not infinite, we lose the ability to concisely communicate when loops actually have no terminating condition. (Arguably, this has already happened, so the point is moot.)
- If everyone always uses
- 打破 while 循环的隐含契约。
- while 循环声明应明确说明唯一的退出条件。
- 意味着它永远循环。
- 必须阅读循环内的代码才能理解终止子句。
- 永远重复的循环会阻止用户从程序内部终止程序。
- 效率低下。
- 有多个循环终止条件,包括检查“true”。
- 容易出现错误。
- 无法轻松确定将始终为每次迭代执行的代码放在哪里。
- 导致不必要的复杂代码。
- 自动源代码分析。
- 为了发现错误、程序复杂性分析、安全检查,或在没有代码执行的情况下自动导出任何其他源代码行为,指定初始破坏条件允许算法确定有用的不变量,从而改进自动源代码分析指标。
- 无限循环。
- 如果每个人都总是使用
while(true)
非无限循环,当循环实际上没有终止条件时,我们就失去了简洁交流的能力。(可以说,这已经发生了,所以这一点没有实际意义。)
- 如果每个人都总是使用
Alternative to "Go To"
“前往”的替代方法
The following code is better form:
以下代码是更好的形式:
while( isValidState() ) {
execute();
}
bool isValidState() {
return msg->state != DONE;
}
Advantages
好处
No flag. No goto
. No exception. Easy to change. Easy to read. Easy to fix. Additionally the code:
没有国旗。没有goto
。没有例外。容易改变。易于阅读。易于修复。另外代码:
- Isolates the knowledge of the loop's workload from the loop itself.
- Allows someone maintaining the code to easily extend the functionality.
- Allows multiple terminating conditions to be assigned in one place.
- Separates the terminating clause from the code to execute.
- Is safer for Nuclear Power plants. ;-)
- 将循环工作负载的知识与循环本身隔离开来。
- 允许维护代码的人轻松扩展功能。
- 允许在一处分配多个终止条件。
- 将终止子句与要执行的代码分开。
- 对核电站更安全。;-)
The second point is important. Without knowing how the code works, if someone asked me to make the main loop let other threads (or processes) have some CPU time, two solutions come to mind:
第二点很重要。在不知道代码如何工作的情况下,如果有人让我让主循环让其他线程(或进程)有一些 CPU 时间,我会想到两种解决方案:
Option #1
选项1
Readily insert the pause:
随时插入暂停:
while( isValidState() ) {
execute();
sleep();
}
Option #2
选项#2
Override execute:
覆盖执行:
void execute() {
super->execute();
sleep();
}
This code is simpler (thus easier to read) than a loop with an embedded switch
. The isValidState
method should only determine if the loop should continue. The workhorse of the method should be abstracted into the execute
method, which allows subclasses to override the default behaviour (a difficult task using an embedded switch
and goto
).
这段代码比带有嵌入的循环更简单(因此更容易阅读)switch
。该isValidState
方法应该只确定循环是否应该继续。方法的主力应该被抽象到execute
方法中,这允许子类覆盖默认行为(使用嵌入式switch
和 的一项艰巨任务goto
)。
Python Example
Python 示例
Contrast the following answer (to a Python question) that was posted on StackOverflow:
对比 StackOverflow 上发布的以下答案(针对 Python 问题):
- Loop forever.
- Ask the user to input their choice.
- If the user's input is 'restart', continue looping forever.
- Otherwise, stop looping forever.
- End.
- 永远循环。
- 要求用户输入他们的选择。
- 如果用户的输入是“重新启动”,则永远继续循环。
- 否则,永远停止循环。
- 结尾。
while True:
choice = raw_input('What do you want? ')
if choice == 'restart':
continue
else:
break
print 'Break!'
Versus:
相对:
- Initialize the user's choice.
- Loop while the user's choice is the word 'restart'.
- Ask the user to input their choice.
- End.
- 初始化用户的选择。
- 循环而用户的选择是“重新启动”这个词。
- 要求用户输入他们的选择。
- 结尾。
choice = 'restart';
while choice == 'restart':
choice = raw_input('What do you want? ')
print 'Break!'
Here, while True
results in misleading and overly complex code.
在这里,会while True
导致误导和过于复杂的代码。
回答by Mehrdad Afshari
You can use goto
.
您可以使用goto
.
while ( ... ) {
switch( ... ) {
case ...:
goto exit_loop;
}
}
exit_loop: ;
回答by sakra
An alternate solution is to use the keyword continue
in combination with break
, i.e.:
另一种解决方案是将关键字continue
与 结合使用break
,即:
for (;;) {
switch(msg->state) {
case MSGTYPE
// code
continue; // continue with loop
case DONE:
break;
}
break;
}
Use the continue
statement to finish each case label where you want the loop to continue and use the break
statement to finish case labels that should terminate the loop.
使用该continue
语句完成您希望循环继续的每个 case 标签,并使用该break
语句完成应终止循环的 case 标签。
Of course this solution only works if there is no additional code to execute after the switch statement.
当然,只有在 switch 语句之后没有要执行的额外代码时,此解决方案才有效。
回答by Alterlife
A neatish way to do this would be to put this into a function:
一种巧妙的方法是将其放入一个函数中:
int yourfunc() {
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
return;
}
}
}
Optionally (but 'bad practices'): as already suggested you could use a goto, or throw an exception inside the switch.
可选(但“不好的做法”):正如已经建议的那样,您可以使用 goto,或在 switch 内抛出异常。
回答by Amber
AFAIK there is no "double break" or similar construct in C++. The closest would be a goto
- which, while it has a bad connotation to its name, exists in the language for a reason - as long as it's used carefully and sparingly, it's a viable option.
AFAIK 在 C++ 中没有“双重中断”或类似的构造。最接近的是 a goto
- 虽然它的名字有不好的含义,但它存在于语言中是有原因的 - 只要小心谨慎地使用它,它就是一个可行的选择。
回答by Adam Pierce
You could put your switch into a separate function like this:
你可以把你的开关放到一个单独的函数中,如下所示:
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())
;
回答by Kirill V. Lyadvinsky
Even if you don't like goto, do not use an exception to exit a loop. The following sample shows how ugly it could be:
即使您不喜欢 goto,也不要使用异常退出循环。以下示例显示了它的丑陋程度:
try {
while ( ... ) {
switch( ... ) {
case ...:
throw 777; // I'm afraid of goto
}
}
}
catch ( int )
{
}
I would use goto
as in thisanswer. In this case goto
will make code more clear then any other option. I hope that thisquestion will be helpful.
我会goto
在这个答案中使用as 。在这种情况下,goto
将使代码比任何其他选项更清晰。我希望这个问题会有所帮助。
But I think that using goto
is the only option here because of the string while(true)
. You should consider refactoring of your loop. I'd suppose the following solution:
但我认为 usinggoto
是这里唯一的选择,因为 string while(true)
。您应该考虑重构您的循环。我想以下解决方案:
bool end_loop = false;
while ( !end_loop ) {
switch( msg->state ) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
end_loop = true; break;
}
}
Or even the following:
甚至以下内容:
while ( msg->state != DONE ) {
switch( msg->state ) {
case MSGTYPE: // ...
break;
// ... more stuff ...
}
回答by sharptooth
There's no C++ construct for breaking out of the loop in this case.
在这种情况下,没有用于跳出循环的 C++ 构造。
Either use a flag to interrupt the loop or (if appropriate) extract your code into a function and use return
.
要么使用标志中断循环,要么(如果合适)将代码提取到函数中并使用return
.
回答by Martin York
You could potentially use goto, but I would prefer to set a flag that stops the loop. Then break out of the switch.
您可能会使用 goto,但我更愿意设置一个停止循环的标志。然后断开开关。
回答by Mark B
Why not just fix the condition in your while loop, causing the problem to disappear?
为什么不修复 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**
}
}