How can I break out of two nested for loops in Objective-C?
CObjective CLoopsC Problem Overview
I have two for loops nested like this:
for(...) {
for(...) {
}
}
I know that there is a break
statement. But I am confused about if it breaks both loops or just the one in which it was called? I need to break both ones as soon as I see that it doesn't make sense to iterate more times over.
C Solutions
Solution 1 - C
If using goto simplifies the code, then it would be appropriate.
for (;;)
{
for (;;)
{
break; /* breaks inner loop */
}
for (;;)
{
goto outer; /* breaks outer loop */
}
}
outer:;
Solution 2 - C
break breaks out of one loop, but you can add a check to the outer loop which breaks when the inner breaks.
bool dobreak = false;
for ( ..; !dobreak && ..; .. ) {
for ( ... ) {
if (...) {
dobreak = true;
break;
}
}
}
Solution 3 - C
The break
statement only gets you out of the innermost loop. If you don't want the added overhead in code, memory and performance of a dedicated state variable, I recommend refactoring the code out into a function or method of its own, and using return
to get out of all the loops:
void do_lots_of_work(void)
{
int i, j;
for(i=0; i<10 ; i++)
{
for(j=0;j< 10; j++)
{
..
..
if(disaster_struck())
return; /* Gets us out of the loops, and the function too. */
}
}
}
Solution 4 - C
Other than the already mentioned flag variable or goto you could throw an Objective-C exception:
@try {
for() {
for() {
@throw ...
}
}
}
@catch{
...
}
Solution 5 - C
Others have mentioned how you can set a flag or use a goto
, but I'd recommend refactoring your code so that the inner loop is turned into a separate method. That method can then return some flag to indicate that the outer loop should break
. If you name your methods appropriately, this is much more readable.
for (int i = 0; i < 10; i++) {
if (timeToStop(i)) break;
}
-(bool) timeToStop: (int) i {
for (int j = 0; j < 10; j++) {
if (somethingBadHappens) return true;
}
return false;
}
Pseudocode, not tested, but you get the idea.
Solution 6 - C
The break statement will only break out of the loop in scope, which is the parent loop. If you want to break out of the second loop as well you could use a boolean variable which is in scope of both loops
bool isTerminated = false;
for (...)
{
if (!isTerminated)
{
for(...)
{
...
isTerminated = true;
break;
}
}
else
{
break;
}
}
Solution 7 - C
Probably the easiest way is to use a "flag" variable
for(i=0; i<10 && (done==false); i++)
for(j=0;j< 10; j++){
..
..
if(...){done=true; break;}
}
Solution 8 - C
Change top loop's counter before break
for(i=0; i<10 ; i++)
for(j=0;j< 10; j++){
..
..
i = 10;
break;
}
Solution 9 - C
Another solution is to factor out the second loop in a function:
int i;
for(i=0; i<10 ; i++){
if !innerLoop(i) {
break;
}
}
bool innerLoop(int i)
int j;
for(j=0;j< 10; j++){
doSomthing(i,j);
if(endcondtion){
return false;
}
}
}
Solution 10 - C
The break statement breaks out of the innermost loop. An additional test and break statement would be needed to break out of the outer loop.
Solution 11 - C
If a break is executed from within a set of nested loops, only the innermost loop in which the break is executed is terminated. (Just like standard C)
Solution 12 - C
Exactly like the last ones are, generally like this:
for(i=0;i<a;i++){
for(j=0;j<a;j++){
if(Something_goes_wrong){
i=a;
break;
}
}
}
Solution 13 - C
Just for grins, how about changing this true/false check into a method and using return
statements:
- (bool) checkTrueFalse: parameters{
for ( ...) {
for ( ... ) {
if (...) {
return true;
}
}
}
return false;
}