1

I want both loops to stop as soon as I find an object that has the same position in x.

Here is my C++ code:

for(int i = 0; i < sizeArray; ++i){
    for(int j = i; j > 0; --j){
        if (s[i].positionX == s[j-1].positionX){
            s[i].positionY = s[j-1].positionY; 
        }
    }
}

If I use break; it only breaks out of the inner for loop. What is the best way to stop both?

Options:

  1. Set the indexes of the loops to max value (or min value) to terminate the loop.
  2. Put all this inside a function and use return.
  3. Use a goto
  4. Use a Lambda
  5. Set a boolean stop code to true, break, then listen for break and break out of other loop?
  6. ?
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
user2775084
  • 95
  • 1
  • 4
  • 11

6 Answers6

4

To break out of the innermost for loop, use break.

To break out of the outermost one, either use goto or use a combination of break and a "should stop" flag.

JB.
  • 40,344
  • 12
  • 79
  • 106
  • 1
    Don't use goto: http://stackoverflow.com/questions/46586/goto-still-considered-harmful – Eric Leschinski Oct 14 '13 at 15:52
  • 1
    The `goto` debate is a semi-religious opinion-strewn minefield; I won't censor my answer just to favor One Right Way. The OP can decide for himself which variant he prefers: both are present. – JB. Oct 14 '13 at 16:55
3

I would suggest lambda:

auto do_work = [&] {
   for(int i = 0; i < sizeArray; ++i){
       for(int j = i; j > 0; --j){
           if (s[i].positionX == s[i-1].positionX){
               s[i].positionY = s[i-1].positionY; 
               return;
           }
       }
   }
};

do_work();  //you can call this multiple times if you need to!

No break, no goto. :-)

It serves the same purpose as break and goto in this case, but the technique seems to be clean, at least to me. Also, once you have the lambda with a name (a good name), you can use it multiple times if you need to — so this technique increases the code readability and encourages code-reuse.

Of course, if you don't need to call this multiple times, then probably you don't need a name. You just could do this:

[&]
{
   //your code with the added return statement.
}();

But as I said, name increases readability even if you don't call it multiple times.


If you cannot use lambda for some reason, then you could still avoid using an extra variable such as stop and the extra work involving it (as @ssantos's answer suggested):

for(int i = 0; i < sizeArray; ++i){
    for(int j = i; j > 0; --j){
        if (s[i].positionX == s[i-1].positionX){
            s[i].positionY = s[i-1].positionY; 
            i = sizeArray; //it will break the outer loop!
            break;
        }
    }
}

Hope that helps.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • While you're suggesting alternatives to `break`, what about throw/catch (*ducks*). (+1) – bitmask Oct 14 '13 at 15:50
  • But a `return;` which exactly serves the same purpose as `break` and `goto`. – glglgl Oct 14 '13 at 15:50
  • In fact, he doesn't even need to store it. (`([](){})()`) - That is, assuming he only wants to call it once. – user123 Oct 14 '13 at 15:50
  • @glglgl: It serves the same purpose, but seems to be clean, at least to me. Also, once you have the lambda with **a name** (a good one), you can use it multiple times if you need to. It is a technique which has other usages which is not possible with `break` and `goto` while keeping your code neat and clean. – Nawaz Oct 14 '13 at 15:51
2

I'm guessing you ask for stopping a for loop. The keyword you're looking for is break. However, if you want to exit both for loops, you'll need to add a variable to your code.-

bool stop = false;

for(int i = 0; i < sizeArray; ++i){
    for(int j = i; j > 0; --j){
        if (s[i].positionX == s[i-1].positionX){
            s[i].positionY = s[i-1].positionY; 
            stop = true;
            break;
        }
    }
    if (stop) {
        break;
    }
}
ssantos
  • 16,001
  • 7
  • 50
  • 70
2

Put the code you posted in its own function and return out of it after the assignment.

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
1

You can stop a for loop with break.

With nested for loops, things are not so easy. You can achieve your goal

  • either with setting a flag (done = 1; and use it with for(int j = i; j > 0 && !done; --j))
  • or with goto. Although goto is frowned upon by some people, it can, if used correctly and with care, be a legitimate solution for some problems, such as error handling, or in general, "finished handling".
glglgl
  • 89,107
  • 13
  • 149
  • 217
1

Try the following

bool match = false; 

for(int i = 0; i < sizeArray && !match; ++i){
    for(int j = i; j > 0 && !match; --j){
        if ( match = ( s[i].positionX == s[i-1].positionX ) ){
            s[i].positionY = s[i-1].positionY; 
        }
    }
}

Another way is the following

 for(int i = 0; i < sizeArray; ++i){
      int j = i;
      while ( j != 0 && s[i].positionX != s[i-1].positionX ) --j;
      if ( j != 0 ) {
           s[i].positionY = s[i-1].positionY; 
           break; 
      }
}
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335