Breaking out of several nested loops
Chris Miller
chris at hwcs.UUCP
Wed Oct 24 21:25:48 AEST 1984
In all the discussion on the merits and/or degree of structuredness of
constructs such as "break <unsigned integer>" or "break <label>" I have
not yet seen anyone observe that C ALREADY has a partial mechanism for
getting out of several nested loops without using a GOTO - it is
called "return"!
Example (using current C - translate ad lib. to your favourite syntax,
and make identifiers unique within 6 chars :-)):
level_1:
while (condition_1)
{
while (condition_2)
{
while (condition_3)
{
switch (condition_4)
{
case AGAIN:
goto Cont;
/* I.E. continue level_1 */
case FINISHED:
goto Done;
/* I.E. break level_1 */
default:
...
}
}
}
Cont:
}
Done:
Becomes:
level_1(/* Parameters from current environment */);
...
level_1(/* Parameters */)
{
while (condition_1)
if (level_2(/* Parameters */) == Done)
return;
}
level_2(/* Parameters */)
{
while (condition_2)
{
while (condition_3)
{
switch(condition_4)
{
case AGAIN:
return Cont;
case FINISHED:
return Done;
default:
...
}
}
}
return Done;
}
If you want multi-level breaks/continues, it is even possible to return
a count indicating how many levels of loop are to be exited.
Let me defend myself instantly from rising hackles and cries of
"Efficiency!". If you really have a collection of nested loops, then
in most cases, the cost of starting up the outer ones is small compared
with the cost of repeatedly executing the innermost one. It may
therefore not be altogether unreasonable to parcel the whole lot up as
a separate function; it is likely in most cases to be a great deal more
readable that way, as well.
Lest anyone still be inclined to flame, a few more points:
1. I am NOT saying that the above is "more" or "less" structured than
any other proposal. Simply wrapping things in procedures does not
automatically render them structured, modular, maintainable,
readable, or anything else!
2. I AM pointing out that if you want to write unstructured code in C,
you don't even need the existing "goto", "break", or "continue"
statements - "return" is quite sufficient (let alone "longjmp",
"exit", or, if you want to be truly obscene, "kill" to transfer
control to a routine which has been set up for signal trapping :-)).
3. I am NOT seriously advocating the above translation as a general
technique - often a solution with "goto" is perfectly appropriate
and comprehensible.
4. I do not believe that "goto" should be banned from C (on the principle
of not breaking existing software), and on the whole do not favour
introducing unnecessary further constructs - if there had never been
a "goto" in C to start with, things would be different, but there was
so they aren't.
5. The REAL problem with any construct, structured or otherwise is that it
becomes hard to read if applied to too large a physical scope (very large
loop bodies, distant targets of "break", etc.). On C compilers which
support multi-line macro definitions (i.e. V7 and most later ones) a
considerable gain in clarity, at no cost in efficiency, can be gained
by packaging loop bodies as macros, even if they only appear once in
the code.
6. I am a computational atheist.
--
Chris Miller
Department of Computer Science
Heriot-Watt University
...!ukc!{edcaad,west44}!hwcs
More information about the Comp.lang.c
mailing list