What is a neat way of breaking out of many for loops at once?

后端 未结 14 1424
既然无缘
既然无缘 2020-12-28 19:33

Suppose I need to break out of three or four nested for loops at once at the occurence of some event inside the innermost loop. What is a neat way of doing that?

相关标签:
14条回答
  • 2020-12-28 19:41

    If you're using Java, you can associate labels with each for block and then reference the label after a continue statement. For example:

    outerfor:
    for (int i=0; i<5; i++) {
        innerfor:
        for (int j=0; j<5; j++) {
            if (i == 1 && j == 2) {
                 continue outerfor;
            }
        }
    }
    0 讨论(0)
  • 2020-12-28 19:41

    If you absolutely don't want to use goto, set all loop conditions to 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;
                }
            }
        }
    }
    

    note: a smart optimizing compiler will turn the contents of the if in a jump to the end of the outer-most loop

    0 讨论(0)
  • 2020-12-28 19:44

    goto. This is one of the very few places where goto is the appropriate tool, and is usually the argument presented why goto isn't complete evil.

    Sometimes, though, I do this:

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

    The idea is that I get a guaranteed free of bar, plus I get a clean two-level break out of the switch via return.

    0 讨论(0)
  • 2020-12-28 19:44

    Dividing by 0 is the surest method I know that will break you out of any number of loops. This works because the DIV assembly instruction doesn't like such silliness.

    So, you can try this:

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

    Getting back from the trap that happens on such events left as an exercise for the reader (it's trivial).

    0 讨论(0)
  • 2020-12-28 19:45

    One way to do it is a state machine. But i would still use goto. It's much simpler. :)

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-28 19:47

    If you are using GCC and this library, the break can accept the number of nested loops you want to exit:

    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);
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题