How to break out of multi-level loops

  • Thread starter Thread starter Krish
  • Start date Start date
K

Krish

Hello,

This is an issue that I have encountered several times but have just
used a workaround to solve.
What is the accepted practice for breaking out of nested loops?

For example:
while( ... )
{
for( ... )
{
...

break;
}
}

When some condition is satisfied, how do you break out of the for and
the while loop (or however many nested loops you happen to have)?

Until now, I have just used a goto in place of the break statement to
jump to a label outside of the nested loops but this somehow doesn't
seem like good coding practice to me.

Thanks!
Krish
 
Krish said:
What is the accepted practice for breaking out of nested loops?

Either:

1. avoid writing code like that, it's often hard to read.

2. Write the loop so that the break-condition in expressed in the
invariant:

while ( something && i == -1 ) {
for ( ... ) {
...
i = 5;
break;
}
}

3. Use a helper function:

bool helper(int x, int y) {
for ( ... )
if ( ... )
return false;
return true;
}
while ( ... )
if ( !helper(x,y) )
break;

4. linearize the loop, by transforming the nested iteration into a
linear iteration on a combined iterator. This approach works really well
in many functional languages, where combining iterators is easy. You
should be able to do the same in C# with .NET2:

T iterate2dimensions(IList i) {
foreach ( IList sublist in l )
foreach ( object o sublist )
yield return o;
}
foreach (T t in iterate2dimensions(list) )
if ( predicate(t) )
break;

5. Accept that goto is actually OK in rare cases -- and *can* make
code more readable (although *very* rarely in C#)

6. Don't use a "local exception":

try {
while ( ... )
for ( ... ) {
...
throw new Break();
}
} catch ( Break ) {
...;
}

When some condition is satisfied, how do you break out of the for and
the while loop (or however many nested loops you happen to have)?

Ususally by stating "!some condition" as (at least part of) the while
loop invariant.

More than 2 loops inside eachother should be "smelled", to se if another
way of writing it could make it less smelly.
Until now, I have just used a goto in place of the break statement to
jump to a label outside of the nested loops but this somehow doesn't
seem like good coding practice to me.

In some cases it really is the most readable solution, but they are far
betweeen.

Remember, if it was hard to get loop written right, readers are going to
have a really tough time -- verbose names, or even comments may be in order.
 
Two patterns occur to me:

bool bDone = false;
while( bDone == false )
{
for( i = 0; i < limit && bDone == false; i++ )
{
if( breakCondition )
bDone = true;
}
}

and:

while( ... )
{
if( ProcessList() == false )
break;
}

bool ProcessList()
{
for(...)
{
if( breakCondition )
return false;
}
return true;
}
 
Thanks Helge & Tom for your suggestions.
As you suggested I think I'll try to refactor the code so it performs
the same function but is more manageable. I liked the ideas about the
helper functions.
Thanks again!
 
Back
Top