16

最も内側のループ内で何らかのイベントが発生したときに、ネストされた 3 つまたは 4 つの for ループから一度に抜け出す必要があるとします。それを行うためのきちんとした方法は何ですか?

私がしているのは、次のようなフラグを使用することです:

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

これは特にきれいではないと思います。

同じことをどのように達成しますか?(ジャンプは使わない)

4

14 に答える 14

86

Gotoを使う。清潔でシンプルです。

于 2009-10-19T04:24:08.073 に答える
49

すべてのループを関数に入れて、ブレークの代わりに戻るだけです。

于 2009-10-19T04:26:20.703 に答える
18

Java を使用している場合は、各 for ブロックにラベルを関連付け、continue ステートメントの後でラベルを参照できます。例えば:

outerfor:
for (int i=0; i<5; i++) {
    innerfor:
    for (int j=0; j<5; j++) {
        if (i == 1 && j == 2) {
             continue outerfor;
        }
    }
}
于 2009-10-19T04:22:50.883 に答える
14

同じことをどのように達成しますか?(ジャンプを使用しない)

なんで?普遍的に悪なものはなく、すべての装着ツールには用途があります(を除くgets())。ここを使用gotoすると、コードがすっきりと見えます。これは、私たちが選択できる唯一の選択肢の1つです(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:

これらすべてのフラグ変数よりもはるかにクリーンであり、コードが何をしているかをより明確に示します

于 2009-10-19T04:30:17.997 に答える
5

少しだけ良くなります。

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

しかし、これらのループが本当に必要な場合は、読みやすくするために、ループを続行するために保持する必要がある条件を各ループで明示的に宣言することは理にかなっています。

于 2009-10-19T04:23:36.793 に答える
5

goto. これは、 が適切なツールである数少ない場所の 1 つであり、通常、完全な悪ではない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;
            }
        }
    }
}

アイデアは、バーのフリーを保証し、さらにリターンを介してスイッチからきれいな 2 レベルのブレークを得るというものです。

于 2009-10-19T06:10:43.257 に答える
4

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 の内容を最も外側のループの最後にジャンプします。

于 2011-08-18T10:01:58.660 に答える
3

時々、次のようなトリックを使用できます。

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

1行しかかかりませんが、きれいだと思います。

ジャスティン

于 2009-10-19T04:56:02.063 に答える
2

少しばかげた自己文書化:

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

しかし実際には、入れ子になった for ループを 3 つ持つべきではありません。これを行う代わりに、別の関数にリファクタリングしてプログラムのロジックを改善することを検討する必要があります。

が実際に最善の解決策である場合もあることに同意しますが、解決策である問題はすべて、コードの悪さの結果であるgotoと思います。goto

于 2009-10-19T18:20:01.257 に答える
0

私は次のようなことをします:

  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;
              }
          }
      }
  }
于 2009-10-19T18:50:31.353 に答える
0

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);
            }
        }
    }
}
于 2017-12-22T21:55:28.653 に答える
0

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ことは、読者の演習として残されています (簡単なことです)。

于 2009-10-19T06:20:35.997 に答える
-1

それを行う 1 つの方法は、ステート マシンです。しかし、私はまだ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;
    }
}
于 2009-10-19T06:00:12.467 に答える