tun*_*nuz 7 c++ label loops nested-loops
我想知道当验证结束条件(不同于正确的迭代次数)时是否可以在C++中结束for循环.例如:
for (int i = 0; i < maxi; ++i)
for (int j = 0; j < maxj; ++j)
// But if i == 4 < maxi AND j == 3 < maxj,
// then jump out of the two nested loops.
Run Code Online (Sandbox Code Playgroud)
我知道这可能在Perl中使用下一个LABEL或最后一个LABEL调用和标记的块,是否可以在C++中执行它或者我应该使用while循环?
谢谢.
Chr*_*isW 51
您可以使用以下return关键字:将嵌套循环移动到子例程中,调用子例程以运行嵌套循环,并从子例程中"返回"以退出[all]循环.
D.S*_*ley 47
尽管有" goto被认为有害"的论点,但这似乎是一个完美的地方goto.这基本上就是你在Perl中所做的.认真地......考虑替代方案:
额外状态变量
for (int i=0; i<maxi; ++i) {
bool leaveLoop = false;
for (int j=0; j<maxj; ++j) {
if (i == 4 && j == 3) {
leaveLoop = true;
break; // leave the inner loop
}
}
if (leaveLoop) {
break; // leave the outside loop
}
}
Run Code Online (Sandbox Code Playgroud)
离开例外
try {
for (int i=0; i<maxi; ++i) {
for (int j=0; j<maxj; ++j) {
if (i == 4 && j == 3) {
throw leave_loop();
}
}
}
} catch (leave_loop const&) {
}
Run Code Online (Sandbox Code Playgroud)
复杂的逻辑
int j = 0;
for (int i=0; i<maxi && !(i==4 && j==3); ++i) {
for (j=0; j<maxj && !(i==4 && j==3); ++j) {
// inner loop
}
}
Run Code Online (Sandbox Code Playgroud)
goto
for (int i=0; i<maxi; ++i) {
for (int j=0; j<maxj; ++j) {
if (i==4 && j==3) {
goto leave_loop;
}
}
}
leave_loop:
Run Code Online (Sandbox Code Playgroud)
最后一个不太明确吗?我不相信它.它更脆弱了吗?恕我直言,其他人相比goto版本更容易出错和脆弱.很抱歉在这里站在肥皂盒上但是这件事困扰了我一段时间;)
你必须要承认的唯一事情是,goto异常非常相似.它们都为泄漏资源提供了机会,并且不小心对待它们.
joe*_*ely 13
让我为重点(但礼貌地说,这;-),我可以:将for在类似C语言的结构是不是计数.
确定是否继续的测试表达式可以是与循环目的相关的任何事物; 更新表达式不必是"向计数器添加一个".
for (int i = 0, j = 0; i < maxi && j < maxj && i != 4 && j != 3;) {
if (j < maxj) {
++j;
} else {
j = 0;
++i;
}
}
Run Code Online (Sandbox Code Playgroud)
将是一种(相当随意的)重写方式.
关键是如果建立一些条件是一个交互的点,通常可以以更明确地陈述继续/终止条件的方式编写一个循环(使用while或者for).
(如果你可以发布实际发生的事情的描述,它可能会写出一些看起来不像上面任意的东西.)
你不能用一个中断指令跳出两个循环,但是你可以使用goto从内部循环跳到外面.
如果goto是本地化的,并且意味着逻辑少于其他我认为它是完全可接受的代码.有额外的标志变量,或者从内循环中提取迭代器变量,这样你就可以在外循环中对它进行比较,这样就不会更容易理解代码恕我直言.
从上面的所有建议中我将避免使用try/catch机制,因为异常应该保留用于特殊情况,而不是正常的控制流.
如果您可以适当地创建第二个条件,则使用两个中断是正常的.为此目的使用布尔值也很好,你甚至可以将它连接到每个for循环的条件.例如:
bool exit_loops = false;
for (int a = 0; a < A && !exit_loops; ++a)
{
for (int b = 0; b < B && !exit_loops; ++b)
{
if (some_condition) exit_loops = true;
}
}
Run Code Online (Sandbox Code Playgroud)
虽然如果你使用两个以上的循环,将它们包装在一个函数中可能更合适,只需使用return退出函数(以及所有的循环).然后,您可以通过调用函数执行内部循环代码等方式来重构代码,从而可以消除除一个循环之外的所有循环.
最后不要害怕在这种情况下使用goto,通常goto是非常糟糕的非结构化编程,但在某些情况下(像这样)它们非常有用.
你不能在C/C++中跳出这样的:
for (...)
{
for (...)
{
// from here...
}
}
// ...to here
Run Code Online (Sandbox Code Playgroud)
没有使用goto.你需要一个像这样的结构:
for (...)
{
bool
exit = false;
for (...)
{
if (do_exit)
{
exit = true; // or set outer loop counter to end value
break;
}
}
if (exit)
{
break;
}
}
Run Code Online (Sandbox Code Playgroud)
或者,使用throw和catch - 但这并不好,因为throw应该用于异常而不是流控制.
一个干净的方法是使内循环成为一个函数:
bool F ()
{
if inner loop terminates, return false else return true
}
void G ()
{
for (...)
{
if (!F ())
{
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
bool done = false;
for (int i = 0; i < maxi && !done; ++i)
for (int j = 0; j < maxj && !done; ++j)
if (i == 4 && i < maxi && j == 3 && j < maxj )
done = true;
else {
}
Run Code Online (Sandbox Code Playgroud)
或者你可以转到.或不 :-)