题
假设我需要在最内向的循环中发生某些事件时立即脱离三个或四个嵌套的循环。 什么是整洁的方式?
我要做的就是使用 标志 像这样:
int i, j, k;
int flag1 = 0;
int flag2 = 0;
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
for (k = 0; k < 100; k++) {
if (k == 50) {
flag1 = 1;
flag2 = 1;
break;
}
}
if (flag1 == 1)break;
}
if (flag2 == 1)break;
}
我认为这不是特别整洁。
您将如何完成同一件事? (不使用跳跃)
解决方案
使用goto。干净简单。
其他提示
将所有循环放在功能中,然后返回而不是断裂。
如果您使用的是Java,则可以将标签与每个标签关联以进行块,然后在继续语句后引用标签。例如:
outerfor:
for (int i=0; i<5; i++) {
innerfor:
for (int j=0; j<5; j++) {
if (i == 1 && j == 2) {
continue outerfor;
}
}
}
您将如何完成同一件事? (不使用跳跃)
为什么?没有什么是普遍邪恶的,每个PutOn工具都有其用途(除了 gets()
)。使用 goto
这里使您的代码看起来更干净,并且是我们拥有的唯一选择之一(假设C)。看:
int i, j, k;
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
for (k = 0; k < 100; k++) {
if (k == 50) {
goto END;
}
}
}
}
END:
比所有这些标志变量要干净得多,甚至更清楚地显示了您的代码是什么 正在做.
只是一个好一点。
int i, j, k;
int flag1 = 0;
int flag2 = 0;
for (i = 0; i < 100 && !flag2; i++) {
for (j = 0; j < 100 && !flag1; j++) {
for (k = 0; k < 100; k++) {
if (k == 50) {
flag1 = 1;
flag2 = 1;
break;
}
}
}
}
但是,如果您确实需要有这些循环,那么在每个循环中明确声明哪种条件才能继续下去,以使其继续进行可读性。
goto
. 。这是几个地方之一 goto
是适当的工具,通常是介绍的论点 goto
不完全邪恶。
不过有时候,我这样做:
void foo() {
bar_t *b = make_bar();
foo_helper(bar);
free_bar(b);
}
void foo_helper(bar_t *b) {
int i,j;
for (i=0; i < imax; i++) {
for (j=0; j < jmax; j++) {
if (uhoh(i, j) {
return;
}
}
}
}
这个想法是我可以保证免费的酒吧,此外,我通过返回从开关中获得了干净的两级突破。
如果您绝对不想使用goto,请将所有循环条件设置为false:
int i, j, k;
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
for (k = 0; k < 100; k++) {
if (k == 50) {
i = j = k = INT_MAX;
break;
}
}
}
}
注意:智能优化编译器将在跳跃中将IF的内容转换为最外部循环的末端
有时您可以使用这样的技巧:
for (i = 0; i < 100 && !flag2; i++) {
for (j = 0; j < 100 && !flag1; j++) {
for (k = 0; k < 100; k++) {
if (k == 50) {
k = 100;
i = 100;
j = 100;
}
}
}
}
或在您的循环中声明附加标志:
bool end = false;
for(int i =0; i < 1000 && !end; i++) {
//do thing
end = true;
}
我认为它只花了一条线,但干净。
贾斯汀
如果任何周期的过早完成总是意味着您也必须打破封闭周期,那么您就不需要任何额外的标志。整个事情可能只是如下
int i, j, k;
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
for (k = 0; k < 100; k++) {
if (k == 50)
break;
}
if (k < 100) break;
}
if (j < 100) break;
}
以我的经验,这是大多数情况下需要的。
一点点愚蠢的自我记录:
int i, j, k;
int done = 0;
for (i = 0; i < 100 && ! done; i++) {
for (j = 0; j < 100 && ! done; j++) {
for (k = 0; k < 100 && ! done; k++) {
if (k == 50) we_are(done);
}
}
}
//...
void we_are(int *done) {
*done = 1;
}
但是,实际上,您不应该有三个嵌套的陆路。您应该考虑重构为不同的功能并改善程序的逻辑,而不是这样做。
虽然我同意有时候 goto
确实是最好的解决方案,我认为任何问题 goto
解决方案是代码差的结果。
除以0是我知道的最可靠的方法 任何 循环数。这是因为DIV组装指令不喜欢这种愚蠢。
因此,您可以尝试一下:
int i, j, k;
int flag1 = 0;
int flag2 = 0;
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
for (k = 0; k < 100; k++) {
if (k == 50) {
flag1 = 1;
flag2 = 1;
int z = 1 / 0; // we're outta here!!!
}
}
if (flag1 == 1)break;
}
if (flag2 == 1)break;
}
从 trap
发生在此类事件中,这是读者的练习(这很琐碎)。
我会做类似的事情:
int i, j, k;
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
for (k = 0; k < 100; k++) {
if (k == 50) {
return;
}
}
}
}
如果您正在使用GCC和 这个库, , 这 break
可以接受要退出的嵌套循环的数量:
int i, j, k;
for (i = 0; i < 100; i++) {
for (j = 0; j < 100; j++) {
for (k = 0; k < 100; k++) {
if (k == 50) {
break(3);
}
}
}
}
一种方法是状态机。但是我仍然会使用goto。这要简单得多。 :)
state = 0;
while( state >= 0){
switch(state){
case 0: i = 0; state = 1; // for i = 0
case 1:
i++;
if (i < 100) // if for i < 100 not finished
state = 2; // do the inner j loop
else
state = -1; // finish loop
case 2: j = 0; state = 3; // for j = 0
case 3:
j++;
if (j < 100) // if j < 100 not finished
state = 4 // do the inner k loop
else
state = 1; // go backt to loop i
break;
case 4: k = 0; state = 5;
case 5:
k++;
if (k == 50){
state = -1;
break;
}
if (k < 100) // if k loop not finished
state = 5; // do this loop
else
state = 3; // go back to upper loop
break;
default : state = -1;
}
}