Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

breaking out of multiple nested loops

3 views
Skip to first unread message

Tagore

unread,
Nov 15, 2009, 12:05:33 PM11/15/09
to
Hi,
How can I break out of multiple nested loops?
i.e if i have a program structure like
for(;;)
{
for(;;){
....
,,,,
for(;;){
//How can I break out of here
break; //it only breaks only from last for loop.
}
}
}
//I want to reach here directly here after breaking

Nick

unread,
Nov 15, 2009, 12:14:19 PM11/15/09
to
Tagore <c.lang...@gmail.com> writes:

You can' do it directly (there isn't - as I've heard proposed - a "break
3" to jump out three levels).

There are a few ways to make it work. The most structured is to create
a separate flag variable that you check in each loop and either end
looping (add it to the middle clause of the if) or test-and-break at the
top of each loop.

Eg:
int flag = 0;
> for(;flag==0 && ;)
> {
> for(;flag==0 &&;){
> ....
> ,,,,
> for(;flag==0;){


> //How can I break out of here

flag = 1;
> }
> }
> }

or
int flag = 0;
> for(;;)
> {
if(flag == 1)
break;
> for(;;){
if(flag == 1)
break;


> ....
> ,,,,
> for(;;){
> //How can I break out of here

flag = 1;


> break; //it only breaks only from last for loop.
> }
> }
> }

My tendency is hated by many advocates of structured programming: I'd
put the whole thing in a function and return where you've got the
"break". You can even return a status code to say whether you finished
the nested loops or jumped out early. I still claim it's completely
obvious what it does and that's good enough for me.
--
Online waterways route planner: http://canalplan.org.uk
development version: http://canalplan.eu

Ben Bacarisse

unread,
Nov 15, 2009, 12:18:39 PM11/15/09
to
Tagore <c.lang...@gmail.com> writes:

(1) Put a label there and "goto" that label.

(2) Use a Boolean/int variable "more_work" and set it to 0 where you
break the inner loop. Change the loop conditions to include it:
condition C become more_work && C.

(3) Make each loop into a function. This needs more work (there is no
recipe for doing it with every time) but many triple-nested loops
should really be re-written as a loop calling a function.

If you give a real example, you might get more practical help. If you
really have three loops with no terminating conditions, a re-design is
almost certainly called for!

--
Ben.

Keith Thompson

unread,
Nov 15, 2009, 12:18:23 PM11/15/09
to

C has no multi-level break statement. Use a goto statement.

No, really.

It can also be argued (and undoubtedly will be) that if you find
yourself needing a multi-level break, your code is too complicated,
and you should restructure the code so it no longer needs it.
One alternative would be to put the outer for loop in a function and
use a return statement (though this might be difficult if the loop
shares local declarations with other code in the existing function).

Some people argue against the use of the break statement at all,
and say that each chunk of code should have a single entry point
and a single exit point. I don't feel very strongly about this,
but there are certainly advantages to that approach. In particular,
if you use break or goto, it's easy to accidentally skip over code
that needs to be executed at the end of the construct. I suspect
someone will be along shortly to make the argument more strongly.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Richard Harter

unread,
Nov 15, 2009, 12:31:50 PM11/15/09
to


Method 1: Put a label after the end of the outer loop and use a
goto. This, in my incredibly correct opinion, is the simplest
and cleanest way. Be warned that certain religious cultists will
want to tie you to a stake and burn you alive.

Method 2: Encapsulate the outer loop in a function and use a
return. In general this is cumbersome because you need to
propagate data across the caller/called boundary. However once
you get the hang of passing state through a handle you can do all
sorts of neat things.

Method 3: Convert your nested loops into a single loop. There
are several ways to do this, all of them unpleasant unless you
have a good reason for doing it anyway. One way is to make the
body of the loop a big switch.

Method 4: Use an extension of C that permits multi-level escapes.
Do not mention it in c.l.c. (See remark above about religious
cultists.)

Method 5: Use some other language. Discover its little gotchas
and ask about them in the newsgroup for that language.

Richard Harter, c...@tiac.net
http://home.tiac.net/~cri, http://www.varinoma.com
Infinity is one of those things that keep philosophers busy when they
could be more profitably spending their time weeding their garden.

Keith Thompson

unread,
Nov 15, 2009, 12:31:27 PM11/15/09
to
Nick <3-no...@temporary-address.org.uk> writes:
> Tagore <c.lang...@gmail.com> writes:
>
>> Hi,
>> How can I break out of multiple nested loops?
>> i.e if i have a program structure like
>> for(;;)
>> {
>> for(;;){
>> ....
>> ,,,,
>> for(;;){
>> //How can I break out of here
>> break; //it only breaks only from last for loop.
>> }
>> }
>> }
>> //I want to reach here directly here after breaking
>
> You can' do it directly (there isn't - as I've heard proposed - a "break
> 3" to jump out three levels).

I hope "break 3" hasn't been *seriously* proposed.

I'd like to see a multi-level break (and continue) in C, but the
argument should be the name of the loop to be terminated, not the
number of nested loops to terminate. The name of the loop could be
specified by a label on the loop. For example:

PROCESS_INPUT: while ((c = getchar()) != EOF) {
/* ... */
if (some_condition) {
break PROCESS_INPUT;
}
/* ... */
}

There's precedent for this in other languages.

The meaning of "break 3;" is insufficiently obvious to the reader
and difficult to maintain. If you write "break 2;" where you meant
"break 3;", the error won't be recognized by the compiler, and may
not be recognized by the programmer. Don't make the programmer or
the reader count things; computers are really good at that.

I'd replace each occurrence of "flag == 1" by "flag", and of
"flag == 0" by "!flag".

[...]

Nick

unread,
Nov 15, 2009, 12:38:09 PM11/15/09
to
Keith Thompson <ks...@mib.org> writes:

> I'd replace each occurrence of "flag == 1" by "flag", and of
> "flag == 0" by "!flag".

In truth, I'd use either the standard or my own boolean variables. But
because I use my own I've never bothered to learn the standards.

BGB / cr88192

unread,
Nov 15, 2009, 12:38:25 PM11/15/09
to

"Tagore" <c.lang...@gmail.com> wrote in message
news:b1fead14-256d-4b5b...@g22g2000prf.googlegroups.com...

strategy 1:
don't use multiply nested loops if avoidable (or if multi-level breaks are
needed);
strategy 2, re-check the loop condition from the prior loop, and if it is
still good, then re-break (if this strategy does not work, consider
reworking the code).

others like goto here, but myself and many others don't, and so my
preference is to either use continue/break, or restructure the code so that
a complex loop is unecessary (I generally like functions being atomic
operations, and complex loops with multi-level breaks often indicate
something which is not an atomic operation).

similarly, I don't normally like using a return within a loop, although in
some cases I have done so in performance-sensitive code.

personally, I prefer loops over the use of goto, since even an ugly loop
(with breaks and continues) is still usually cleaner that goto and labels,
and as well the block for the loop generally shows the region which is
within the loop, which may not be so clear with lots of gotos.

...

Nick

unread,
Nov 15, 2009, 12:45:19 PM11/15/09
to
Keith Thompson <ks...@mib.org> writes:

> Nick <3-no...@temporary-address.org.uk> writes:
>> Tagore <c.lang...@gmail.com> writes:
>>
>>> Hi,
>>> How can I break out of multiple nested loops?
>>> i.e if i have a program structure like
>>> for(;;)
>>> {
>>> for(;;){
>>> ....
>>> ,,,,
>>> for(;;){
>>> //How can I break out of here
>>> break; //it only breaks only from last for loop.
>>> }
>>> }
>>> }
>>> //I want to reach here directly here after breaking
>>
>> You can' do it directly (there isn't - as I've heard proposed - a "break
>> 3" to jump out three levels).
>
> I hope "break 3" hasn't been *seriously* proposed.

A quick google shows a fair few people discussing it - with lots of
others leaping in with your suggestions. As you say, numbering it is an
appalling idea - sooner or later someone is going to stick another loop
in the middle.

Here's a long discussion of it from 1996 no less:
<URL http://groups.google.co.uk/group/comp.lang.c/browse_thread/thread/50912ea35a454937/2212282f7b512a75?hl=en&ie=UTF-8&q=C+language+%22break+1%22#2212282f7b512a75>

Kenny McCormack

unread,
Nov 15, 2009, 12:46:27 PM11/15/09
to
In article <87y6m7y...@temporary-address.org.uk>,
Nick <3-no...@temporary-address.org.uk> wrote:
...

>A quick google shows a fair few people discussing it - with lots of
>others leaping in with your suggestions. As you say, numbering it is an
>appalling idea - sooner or later someone is going to stick another loop
>in the middle.

The precedent for that is the shell (sh and derivatives).

And C/Unix is all about preserving precedent (just like the law).

Saurav Bhasin

unread,
Nov 15, 2009, 1:12:56 PM11/15/09
to
On 15 Nov, 22:46, gaze...@shell.xmission.com (Kenny McCormack) wrote:

> In article <87y6m7y95c....@temporary-address.org.uk>,Nick  <3-nos...@temporary-address.org.uk> wrote:
>
> ...
>
> >A quick google shows a fair few people discussing it - with lots of
> >others leaping in with your suggestions.  As you say, numbering it is an
> >appalling idea - sooner or later someone is going to stick another loop
> >in the middle.
>
> The precedent for that is the shell (sh and derivatives).
>
> And C/Unix is all about preserving precedent (just like the law).

Sure we can try multiple loops, I think we can use Flags for this
purpose. Goto and Label can make code difficult also.

bartc

unread,
Nov 15, 2009, 1:36:21 PM11/15/09
to
"Keith Thompson" <ks...@mib.org> wrote in message
news:ln1vjzi...@nuthaus.mib.org...

> Nick <3-no...@temporary-address.org.uk> writes:
>> Tagore <c.lang...@gmail.com> writes:
>>
>>> Hi,
>>> How can I break out of multiple nested loops?

>> You can' do it directly (there isn't - as I've heard proposed - a "break


>> 3" to jump out three levels).
>
> I hope "break 3" hasn't been *seriously* proposed.
>
> I'd like to see a multi-level break (and continue) in C, but the
> argument should be the name of the loop to be terminated, not the
> number of nested loops to terminate. The name of the loop could be
> specified by a label on the loop. For example:
>
> PROCESS_INPUT: while ((c = getchar()) != EOF) {
> /* ... */
> if (some_condition) {
> break PROCESS_INPUT;
> }
> /* ... */
> }
>
> There's precedent for this in other languages.
>
> The meaning of "break 3;" is insufficiently obvious to the reader
> and difficult to maintain. If you write "break 2;" where you meant
> "break 3;", the error won't be recognized by the compiler, and may
> not be recognized by the programmer. Don't make the programmer or
> the reader count things; computers are really good at that.

I use break 2, 3 and so on in other languages I use (or exit 2, 3 as it
would be).

It is really not a big deal.

I've just quickly looked at 250K lines of my code, and "exit 2" is used 4
times, and "exit 3" just twice.

If an extra looping level is added, this is likely to be an extra outer
level; this doesn't affect the validity of the exit 2 or 3.

(And anyway C would have the same problem with it's break statement when
extra loop levels are added, but in that case, you can't just change a
digit, but have to completely restructure! Even changing a statement from an
if-then-else chain to a switch will cause a problem if there is a break
inside.)

So having numbered multi-level break is not the end of the world, provided
it's not abused, just like anything else. It's just nice having it available
to quickly get you out of trouble.

(And yes I also have a named exit statement on a newer design, but I haven't
got round to implementing it yet. Maybe I never will)

--
Bartc

Malcolm McLean

unread,
Nov 15, 2009, 3:06:01 PM11/15/09
to

"Tagore" <c.lang...@gmail.com> wrote in message news:
> How can I break out of multiple nested loops?

for(; condition(); )
for(; condition() && funnycondition();)
for(; condition(); )
if( needtobreak() )
makeconditionreturnfalse();


Keith Thompson

unread,
Nov 15, 2009, 4:48:21 PM11/15/09
to
"bartc" <ba...@freeuk.com> writes:
> "Keith Thompson" <ks...@mib.org> wrote in message
> news:ln1vjzi...@nuthaus.mib.org...
>> Nick <3-no...@temporary-address.org.uk> writes:
>>> Tagore <c.lang...@gmail.com> writes:
>>>> How can I break out of multiple nested loops?
>
>>> You can' do it directly (there isn't - as I've heard proposed - a "break
>>> 3" to jump out three levels).
>>
>> I hope "break 3" hasn't been *seriously* proposed.
[big snip]

>
> I use break 2, 3 and so on in other languages I use (or exit 2, 3 as it
> would be).
>
> It is really not a big deal.
>
> I've just quickly looked at 250K lines of my code, and "exit 2" is used 4
> times, and "exit 3" just twice.
>
> If an extra looping level is added, this is likely to be an extra outer
> level; this doesn't affect the validity of the exit 2 or 3.
>
> (And anyway C would have the same problem with it's break statement when
> extra loop levels are added, but in that case, you can't just change a
> digit, but have to completely restructure! Even changing a statement from an
> if-then-else chain to a switch will cause a problem if there is a break
> inside.)
>
> So having numbered multi-level break is not the end of the world, provided
> it's not abused, just like anything else. It's just nice having it available
> to quickly get you out of trouble.
>
> (And yes I also have a named exit statement on a newer design, but I haven't
> got round to implementing it yet. Maybe I never will)

It's probably unlikely that any kind of multi-level break will be
added to C.

If such a feature were to be added, yes, if it were defined to take a
numeric argument (presumably a constant expression), we could deal
with it. Any features can be used correctly if you're sufficiently
careful, or incorrectly if you're not. And if your code is so complex
that you're likely to use "break 3;" rather than "break 4;", or vice
versa, the answer is almost certainly to restructure the code.

But since neither "break <number>" nor "break <LABEL>" would, ahem,
break any existing code, I really can't think of any sane reason to
*prefer* the "break <number>" to "break <LABEL>".

Can you?

bartc

unread,
Nov 15, 2009, 7:22:57 PM11/15/09
to

"Keith Thompson" <ks...@mib.org> wrote in message
news:lnfx8fh...@nuthaus.mib.org...

> It's probably unlikely that any kind of multi-level break will be
> added to C.

No. Committees don't seem to like new syntax.

> If such a feature were to be added, yes, if it were defined to take a
> numeric argument (presumably a constant expression), we could deal
> with it. Any features can be used correctly if you're sufficiently
> careful, or incorrectly if you're not. And if your code is so complex
> that you're likely to use "break 3;" rather than "break 4;", or vice
> versa, the answer is almost certainly to restructure the code.

You might notice your code not working right if you get it wrong.

And any alternatives that don't involve goto are likely to be more
error-prone.

> But since neither "break <number>" nor "break <LABEL>" would, ahem,
> break any existing code, I really can't think of any sane reason to
> *prefer* the "break <number>" to "break <LABEL>".

I have preference for break <no>, even though it looks crude, as break
<label> is not actually much different from goto <label>, and it means
thinking up a label in the first place and then remembering to add it at one
end of the loop or the other.

But either (or both) will do the job.

At present C barely has an ordinary break statement, because of the problem
with using it inside switch.

--
Bartc

Richard Tobin

unread,
Nov 15, 2009, 8:48:03 PM11/15/09
to
In article <BX0Mm.5598$Ym4....@text.news.virginmedia.com>,
bartc <ba...@freeuk.com> wrote:

>I have preference for break <no>, even though it looks crude

This would be a really bad idea, since it would often have to be fixed
up when the program was changed, and there would be no way to detect
most errors. What's more, a good name lets you express what you
mean very directly; for "break customer_loop" expresses that you
are breaking out of the loop over customers, without the reader
having to look back or forward through the code.

>as break
><label> is not actually much different from goto <label>,

I cannot see any force in that argument. What is the bad thing about
"goto label" that makes "break label" be bad too?

>and it means
>thinking up a label in the first place and then remembering to add it at one
>end of the loop or the other.

Well, you *could* give up variable names and just use a single array.

-- Richard
--
Please remember to mention me / in tapes you leave behind.

Seebs

unread,
Nov 15, 2009, 9:03:25 PM11/15/09
to
On 2009-11-16, Richard Tobin <ric...@cogsci.ed.ac.uk> wrote:
>>as break
>><label> is not actually much different from goto <label>,

> I cannot see any force in that argument. What is the bad thing about
> "goto label" that makes "break label" be bad too?

I actually like break <label> much better. The thing about
goto <label> that I don't like is that label may be anywhere in
or out of a loop, etcetera.

By constrast, consider a hypothetical break/continue <label> such that:

foo: while(1) {
...
}

means that, inside the loop, "continue foo" jumps to the test at the
top of the loop, while "break foo" jumps immediately past the end of
the loop, regardless of the number of intervening levels -- I think
that's a lot more useful than break <n>, while much more predictable
and controlled than a goto.

-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!

James Dow Allen

unread,
Nov 15, 2009, 11:50:59 PM11/15/09
to
On Nov 16, 8:48 am, rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
> In article <BX0Mm.5598$Ym4.2...@text.news.virginmedia.com>,

> >as break
> ><label> is not actually much different from goto <label>,

It may be true that "break label" is so unbelievably similar
to "goto label" that even proposing the former suggests a
religious aversion to writing "goto" (perhaps much like the
Jewish aversion to pronouncing "Yahweh").

However I don't think the suggested form is eguivalent to "goto".
Rather than locating the label at the place where the break
would, err, go to, the user-friendly suggestion is to locate
the label at the place where "break" breaks out of!
And rather than allowing the coder to goto where and when he
wants, the user-friendly break would allow another user-friendly
diagnostic: "Error: breaking to a label that isn't breakable."

> I cannot see any force in that argument.  What is the bad thing about
> "goto label" that makes "break label" be bad too?

Richard, would you be willing to cast your vote on the
constructions as
http://james.fabpedigree.com/gotoalt.htm

James Dow Allen

Keith Thompson

unread,
Nov 16, 2009, 2:13:31 AM11/16/09
to
Seebs <usenet...@seebs.net> writes:
> On 2009-11-16, Richard Tobin <ric...@cogsci.ed.ac.uk> wrote:
>>>as break
>>><label> is not actually much different from goto <label>,
>
>> I cannot see any force in that argument. What is the bad thing about
>> "goto label" that makes "break label" be bad too?
>
> I actually like break <label> much better. The thing about
> goto <label> that I don't like is that label may be anywhere in
> or out of a loop, etcetera.
>
> By constrast, consider a hypothetical break/continue <label> such that:
>
> foo: while(1) {
> ...
> }
>
> means that, inside the loop, "continue foo" jumps to the test at the
> top of the loop, while "break foo" jumps immediately past the end of
> the loop, regardless of the number of intervening levels -- I think
> that's a lot more useful than break <n>, while much more predictable
> and controlled than a goto.

Right. The idea is that the label is the name of the loop as a
whole, not just the name of specific point in the code. I find this
vastly preferable to a construct that requires me to count things.

The proposal here is that, in the above, "foo:" can serve both
purposes; "goto foo;" uses it as the name of a point in the code,
whereas "break foo;" uses it as the name of the while statement
(and is illegal if there's no enclosing loop or switch statement
with the label "foo:").

Perl works this way, and it's very common to use Perl's equivalent
of "break" or "continue" (spelled "last" and "next") with a label.
The same label can be used as a goto target, but I don't remember
the last time I saw a goto statement in a Perl program (other than
the one I wrote a few minutes ago).

Ada, on the other hand, actually uses a different syntax for the
two kinds of label. "Name:" can be used to provide a name for a
loop, whereas a goto label looks like "<<LABEL>>" (the latter is
deliberately ugly to make it stand out, and probably to discourage
the use of gotos).

Richard Heathfield

unread,
Nov 16, 2009, 3:05:23 AM11/16/09
to
In <BX0Mm.5598$Ym4....@text.news.virginmedia.com>, bartc wrote:

<snip>



> At present C barely has an ordinary break statement, because of the
> problem with using it inside switch.

I have never had a problem using a break inside a switch.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
"Usenet is a strange place" - dmr 29 July 1999
Sig line vacant - apply within

Richard Tobin

unread,
Nov 16, 2009, 5:43:19 AM11/16/09
to
In article <cc6dndsk-v-Im5zW...@bt.com>,

Richard Heathfield <r...@see.sig.invalid> wrote:
>I have never had a problem using a break inside a switch.

You may never have had a problem with it, but I have more than once
taken code like this:

while(...)
{
if(...)
{
...;
continue;
}
else if(...)
break;
else
...
}

and changed the if-else chain to a switch. This has the annoying
result that the break no longer works. The non-orthogonality is
particularly clear from the fact that the continue does not need to be
changed.

Of course a "break label" construct would not remove this issue,
but it would at least mean that the fix did not require a change
to the structure of the code.

bartc

unread,
Nov 16, 2009, 6:26:29 AM11/16/09
to

"Richard Tobin" <ric...@cogsci.ed.ac.uk> wrote in message
news:hdqb0j$1k71$1...@pc-news.cogsci.ed.ac.uk...

> In article <BX0Mm.5598$Ym4....@text.news.virginmedia.com>,
> bartc <ba...@freeuk.com> wrote:
>
>>I have preference for break <no>, even though it looks crude
>
> This would be a really bad idea, since it would often have to be fixed
> up when the program was changed, and there would be no way to detect
> most errors.

Is that really true?

C has already has a break 1 (or break 0 if you prefer); what happens now
when this:

while (...) {
...
break;
...
}

turns into this:

while (...) {
...
while (...) {
...
break;
...
}
}

?

Either you only really wanted to break out of that inner loop, and nothing
changes (in which cases break 2 would be also stay the same), or or wanted
to break out of all loops, in which case you have to change the break to
something entirely different; break 2 on the other hand just becomes break
3...

The only difference might be if you started with 2 nested loops,
containing a break 2 in the inner one, decided to put an extra loop
in-between, and intended that break 2 to break out of all loops. Then and
only then, you might have to change a 2 to a three. But how often is that
going to happen?

And in most of those cases, you can use a 'break all' to break out of all
nested loops, if having a number really bothers you.

>>as break
>><label> is not actually much different from goto <label>,
>
> I cannot see any force in that argument. What is the bad thing about
> "goto label" that makes "break label" be bad too?

I didn't say goto was bad.

>>and it means
>>thinking up a label in the first place and then remembering to add it at
>>one
>>end of the loop or the other.
>
> Well, you *could* give up variable names and just use a single array.

Imagine *every* loop had to have it's own name, whether you'd intended to
break out of it or not. You might quickly get fed up.

--
Bartc

Eric Sosman

unread,
Nov 16, 2009, 8:08:00 AM11/16/09
to
bartc wrote:
>
> "Keith Thompson" <ks...@mib.org> wrote in message
> news:lnfx8fh...@nuthaus.mib.org...
>
>> It's probably unlikely that any kind of multi-level break will be
>> added to C.
>
> No. Committees don't seem to like new syntax.

A review of the differences between C90 and C99 suggests
that their distaste is not overpoweringly strong.

--
Eric Sosman
eso...@ieee-dot-org.invalid

Eric Sosman

unread,
Nov 16, 2009, 8:15:27 AM11/16/09
to
Seebs wrote:
> On 2009-11-16, Richard Tobin <ric...@cogsci.ed.ac.uk> wrote:
>>> as break
>>> <label> is not actually much different from goto <label>,
>
>> I cannot see any force in that argument. What is the bad thing about
>> "goto label" that makes "break label" be bad too?
>
> I actually like break <label> much better. The thing about
> goto <label> that I don't like is that label may be anywhere in
> or out of a loop, etcetera.
>
> By constrast, consider a hypothetical break/continue <label> such that:
>
> foo: while(1) {
> ...
> }
>
> means that, inside the loop, "continue foo" jumps to the test at the
> top of the loop, while "break foo" jumps immediately past the end of
> the loop, regardless of the number of intervening levels -- I think
> that's a lot more useful than break <n>, while much more predictable
> and controlled than a goto.

This is how Java does it, and I for one find it repugnant.
Although `continue foo;' reads reasonably well, `break foo;' is
just plain awful: It says "transfer control to somewhere *not*
close to the label foo." To discover where the destination is,
you've got to find the label and then search for the other end
of its block -- and we must assume that the block is non-trivial,
or a multi-level break wouldn't have been needed in the first
place ... (On a labelled do-while, `continue foo;' shares the
same problem of misdirected attention.)

But since there's precedent, somebody will probably follow
it, alas. Java adopted some of C's infelicities; why shouldn't
C incorporate the unpleasant features of Java?

--
Eric Sosman
eso...@ieee-dot-org.invalid

William Hughes

unread,
Nov 16, 2009, 8:53:05 AM11/16/09
to
On Nov 15, 1:18 pm, Keith Thompson <ks...@mib.org> wrote:

> Tagore <c.lang.mys...@gmail.com> writes:
> >     How can I break out of multiple nested loops?
> >  i.e if i have a program structure like
> >  for(;;)
> > {
> >    for(;;){
> >   ....
> >    ,,,,
> >        for(;;){
> >                //How can I break out of here
> >                  break;   //it only breaks only from last for loop.
> >            }
> >     }
> > }
> > //I want to reach here directly here after breaking
>
> C has no multi-level break statement.  Use a goto statement.
>
> No, really.
>
> It can also be argued (and undoubtedly will be) that if you find
> yourself needing a multi-level break, your code is too complicated,
> and you should restructure the code so it no longer needs it.

Well, it may be possible to restructure and
simplify the code, but there
are times when this type of structure is needed, e.g.
searching for an element is a three dimensional matrix.
You have to do three loops and end processing when
an element is found. Disguising what you are doing
will not make things magically simpler.

My own preference is a labeled break.
C does not have this construct so use a goto.
There is nothing wrong with branching.
(Programming would be very difficult without
a branch. It is unrestricted branching that
leads to trouble.)

Rules for goto

1. Use very sparingly

2. Never jump backward or into a loop

3 Only jump to the end of a loop

4. If you are optimizing code
ignore the rules [Recall the rules
of optimziation, 1. Dont do it
(for experts) 2. Don't do it yet]

(Note that rules 2 and 3 can be added to
a compiler as warnings, so a language change
is not needed.)

- William Hughes

Richard

unread,
Nov 16, 2009, 8:57:54 AM11/16/09
to
William Hughes <wpih...@hotmail.com> writes:

Not universally true of course since "optimising code" can also mean
totally altering the order of loops and the indexing method, the type of
structure packing done etc. Things which can and do have HUGE increases
in performance and should be considered at an early stage in any large
system design.

Ben Bacarisse

unread,
Nov 16, 2009, 9:59:34 AM11/16/09
to
William Hughes <wpih...@hotmail.com> writes:

Disguising? Maybe. Just to see how it comes out, this is how I'd do
it so as not to have a multi-level break:

bool array_1d_find(int what, size_t n, int array[n], size_t *where)
{
for (size_t i = 0; i < n; i++)
if (array[i] == what)
return *where = i, true;
return false;
}

bool array_2d_find(int what, size_t n, size_t m,
int array[n][m], size_t *where)
{
for (size_t i = 0; i < n; i++)
if (array_1d_find(what, m, array[i], where+1))
return *where = i, true;
return false;
}

bool array_3d_find(int what, size_t n, size_t m, size_t o,
int array[n][m][o], size_t *where)
{
for (size_t i = 0; i < n; i++)
if (array_2d_find(what, m, o, array[i], where+1))
return *where = i, true;
return false;
}

and a call looks like this:

size_t ind[3];
if (array_3d_find(99, 3, 4, 5, M, ind))
/* use M[ind[0]][ind[1]][ind[2]]
or set size_t i = idx[0], j = idx[1], k = idx[2]; if you
intend to use them a lot.
*/

I don't think this disguises anything very much. This nice thing is
that the auxiliary functions are independently useful.

> My own preference is a labeled break.
> C does not have this construct so use a goto.
> There is nothing wrong with branching.
> (Programming would be very difficult without
> a branch. It is unrestricted branching that
> leads to trouble.)
>
> Rules for goto
>
> 1. Use very sparingly
>
> 2. Never jump backward or into a loop
>
> 3 Only jump to the end of a loop

I'd say "Only jump to the end or to just after a loop". To my mind,
jumping to the end is like continue, and jumping to just after a loop
is like break.

> 4. If you are optimizing code
> ignore the rules [Recall the rules
> of optimziation, 1. Dont do it
> (for experts) 2. Don't do it yet]
>
> (Note that rules 2 and 3 can be added to
> a compiler as warnings, so a language change
> is not needed.)

--
Ben.

bartc

unread,
Nov 16, 2009, 10:38:36 AM11/16/09
to

"Ben Bacarisse" <ben.u...@bsb.me.uk> wrote in message
news:0.8618f087583a13f09a02.2009...@bsb.me.uk...
> William Hughes <wpih...@hotmail.com> writes:

You really think the above is simpler and clearer than this:

a=6;
found=0;

for (i=0; i<dx; ++i)
for (j=0; j<dy; ++j)
for (k=0; k<dz; ++k)
if (data[i][j][k]==a) {found=1; goto l;}
l:
if (found) printf("Found at [%d][%d][%d]\n",i,j,k);

?

Of course you might change 'goto l' to 'break 2' or 'break 3', or 'break
<label>'; since it's only only jumping to the very next line, trying to find
where it ends up can't be too taxing.

--
Bartc

Richard Heathfield

unread,
Nov 16, 2009, 11:56:50 AM11/16/09
to
In <hdrac7$1uhf$1...@pc-news.cogsci.ed.ac.uk>, Richard Tobin wrote:

> In article <cc6dndsk-v-Im5zW...@bt.com>,
> Richard Heathfield <r...@see.sig.invalid> wrote:
>>I have never had a problem using a break inside a switch.
>
> You may never have had a problem with it, but I have more than once
> taken code like this:
>
> while(...)
> {
> if(...)
> {
> ...;
> continue;
> }
> else if(...)
> break;
> else
> ...
> }
>
> and changed the if-else chain to a switch. This has the annoying
> result that the break no longer works.

<smug>
Yes. This is one of the many pay-offs I get from my excessively
strict self-imposed structuring rules - I consider break to be usable
*only* within a switch.

<snip>

> Of course a "break label" construct would not remove this issue,
> but it would at least mean that the fix did not require a change
> to the structure of the code.

And my approach requires neither a change to the structure of my
code nor any kind of fix whatsoever.
</smug>

Ben Bacarisse

unread,
Nov 16, 2009, 12:09:19 PM11/16/09
to
"bartc" <ba...@freeuk.com> writes:

No, and I did not say it was. I said that the above does not disguise
what is happening and even that had a "maybe" attached.

The advantage comes from the fact the components do a job of their
own. You may not get any benefit from that in the program you are
writing now, but I have rarely regretted writing a function instead of
a loop in the long run.

<snip>
--
Ben.

bartc

unread,
Nov 16, 2009, 12:22:50 PM11/16/09
to

"Richard Heathfield" <r...@see.sig.invalid> wrote in message
news:ZqSdnbc5I6w4H5zW...@bt.com...

> In <hdrac7$1uhf$1...@pc-news.cogsci.ed.ac.uk>, Richard Tobin wrote:

>> and changed the if-else chain to a switch. This has the annoying
>> result that the break no longer works.
>
> <smug>
> Yes. This is one of the many pay-offs I get from my excessively
> strict self-imposed structuring rules - I consider break to be usable
> *only* within a switch.
>
> <snip>
>
>> Of course a "break label" construct would not remove this issue,
>> but it would at least mean that the fix did not require a change
>> to the structure of the code.
>
> And my approach requires neither a change to the structure of my
> code nor any kind of fix whatsoever.
> </smug>

At a cost of having to write convoluted code in the first place..

BTW suppose you have a switch-break statement inside an if-else chain inside
a switch, and you change that if-else to a nested switch; how do you now
break out of two levels of switch?

--
Bartc

Richard

unread,
Nov 16, 2009, 12:31:23 PM11/16/09
to
"bartc" <ba...@freeuk.com> writes:

In my experience only real idiots objects to goto in all situations.

There can be no easier thing to read in a complex block of loops than

"OK, we reached this point lets get the hell out of here".

Do I use them? Rarely. But its rare to be in that kind of deep in most
projects. But the need can and does arise.

--
"Avoid hyperbole at all costs, its the most destructive argument on
the planet" - Mark McIntyre in comp.lang.c

John Kelly

unread,
Nov 16, 2009, 1:00:36 PM11/16/09
to
On Mon, 16 Nov 2009 18:31:23 +0100, Richard <rgr...@gmail.com> wrote:

>In my experience only real idiots objects to goto in all situations.

Maybe they're not idiots but just lack practical experience. People cut
off their hands with chainsaws, but that doesn't prove chainsaws should
never be used. You just have to be careful. And it helps to know what
you're doing.


--
Webmail for Dialup Users
http://www.isp2dial.com/freeaccounts.html

Richard

unread,
Nov 16, 2009, 1:46:07 PM11/16/09
to
John Kelly <j...@isp2dial.com> writes:

> On Mon, 16 Nov 2009 18:31:23 +0100, Richard <rgr...@gmail.com> wrote:
>
>>In my experience only real idiots objects to goto in all situations.
>
> Maybe they're not idiots but just lack practical experience. People cut
> off their hands with chainsaws, but that doesn't prove chainsaws should
> never be used. You just have to be careful. And it helps to know what
> you're doing.

No. Idiots. And I say idiots because they are unable to see past their
own self perceived perfection in structuring code.

"break" is not more than a glorified goto. Ditto for clause 2 in a for
loop.

It's a mental thing. Some people need to get over themselves.

But once more : no not to be used all the time when pefectly good
constructs like for(while etc will do. There are times they do not. And
certainly I would find following 4 breaks and the resultant "trickle
back" affect much more hard to read than a "GOTO DONE" type thing.

John Kelly

unread,
Nov 16, 2009, 2:07:21 PM11/16/09
to
On Mon, 16 Nov 2009 19:46:07 +0100, Richard <rgr...@gmail.com> wrote:

>>>In my experience only real idiots objects to goto in all situations.

>> Maybe they're not idiots but just lack practical experience. People cut
>> off their hands with chainsaws, but that doesn't prove chainsaws should
>> never be used. You just have to be careful. And it helps to know what
>> you're doing.
>
>No. Idiots. And I say idiots because they are unable to see past their
>own self perceived perfection in structuring code.

I have observed religious fervor here. I'm more inclined to live and
let live. I didn't expect the maniacal reaction of a few to dh and its
code. From my casual reading of this ng, it seems Jacob and I are the
only ones who talk about their own project code. He was the only one to
welcome me when I first posted mine.

More project code and less bombast would make this a better ng.

Richard Heathfield

unread,
Nov 16, 2009, 2:34:07 PM11/16/09
to
In <KTfMm.5771$Ym4....@text.news.virginmedia.com>, bartc wrote:

>
> "Richard Heathfield" <r...@see.sig.invalid> wrote in message
> news:ZqSdnbc5I6w4H5zW...@bt.com...

<snip>


>>
>> And my approach requires neither a change to the structure of my
>> code nor any kind of fix whatsoever.
>> </smug>
>
> At a cost of having to write convoluted code in the first place..

Well, clearly we disagree about "convoluted" - I see structured code
as pretty much the opposite of convoluted.

> BTW suppose you have a switch-break statement inside an if-else
> chain inside a switch, and you change that if-else to a nested
> switch; how do you now break out of two levels of switch?

Functional decomposition renders that problem academic.

John Kelly

unread,
Nov 16, 2009, 2:33:30 PM11/16/09
to
On Mon, 16 Nov 2009 19:34:07 +0000, Richard Heathfield
<r...@see.sig.invalid> wrote:

>In <KTfMm.5771$Ym4....@text.news.virginmedia.com>, bartc wrote:

>> BTW suppose you have a switch-break statement inside an if-else
>> chain inside a switch, and you change that if-else to a nested
>> switch; how do you now break out of two levels of switch?

>Functional decomposition renders that problem academic.

Now I know how you think. Functional decomposition to the extreme.

I don't think that way.

Kenny McCormack

unread,
Nov 16, 2009, 3:00:31 PM11/16/09
to
In article <as73g5dmj90no03fp...@4ax.com>,
John Kelly <j...@isp2dial.com> wrote:
...

>More project code and less bombast would make this a better ng.

(Semi-serious mode) "You would think..."

(Serious mode) "Yes, you are absolutely right that no one (other than
newbies) ever posts actual code here. It's just asking to be
clobbered. In fact, if you didn't get clobbered for it, it would be
proof positive that the regs weren't doing their jobs."

(Satirical, but serious mode) "Anything at all tangible is OT. There is
no mention of dh or lcc, or anything else that sensible people might
actually want to discuss, in the C standards documents."

Richard

unread,
Nov 16, 2009, 3:08:11 PM11/16/09
to
John Kelly <j...@isp2dial.com> writes:

You would need another group for that. Real world experiences and real
world C usage get put to the back in favour of platforms and scenarios
that people make up to impress the c.l.c clique. Using debuggers is also
a sign of incompetence apparently since debugging is twice as hard as
writing the code "right" in the first place. It must be true cos Brian
Kernighan said it. Long before decent debuggers existed ...

Indeed.

One person proudly explained how he once found a bug in 5000 lines just
by reading it. I was very impressed. Personally I would have run it in a
debugger and waited for the segfault to be caught and show me the right
line. But common sense and "general fair usage" are not what c.l.c is
about.

But then hyperbole is the raison d'etre of c.l.c.

As this wonderful .sig warns, be careful of using too much hyperbole
however ...

*ROTFLM*

John Kelly

unread,
Nov 16, 2009, 3:11:34 PM11/16/09
to
On Mon, 16 Nov 2009 20:00:31 +0000 (UTC), gaz...@shell.xmission.com
(Kenny McCormack) wrote:

>>More project code and less bombast would make this a better ng.

>(Serious mode) "Yes, you are absolutely right that no one (other than


>newbies) ever posts actual code here. It's just asking to be
>clobbered. In fact, if you didn't get clobbered for it, it would be
>proof positive that the regs weren't doing their jobs."

I can tolerate the clobbering. Though little, some good came from it.
But once they take their position and I take mine, there's no point in a
forever loop. That's where I break out. Or goto have fun. ;-)

Nick

unread,
Nov 16, 2009, 3:58:35 PM11/16/09
to
Eric Sosman <eso...@ieee-dot-org.invalid> writes:

> This is how Java does it, and I for one find it repugnant.
> Although `continue foo;' reads reasonably well, `break foo;' is
> just plain awful: It says "transfer control to somewhere *not*
> close to the label foo." To discover where the destination is,
> you've got to find the label and then search for the other end
> of its block -- and we must assume that the block is non-trivial,
> or a multi-level break wouldn't have been needed in the first
> place ... (On a labelled do-while, `continue foo;' shares the
> same problem of misdirected attention.)
>
> But since there's precedent, somebody will probably follow
> it, alas. Java adopted some of C's infelicities; why shouldn't
> C incorporate the unpleasant features of Java?

It certainly predates Java. I first came across it in "Superbasic" on
the Sinclair QL:

repeat foo
if a=y then exit foo
end repeat

OK, you could put the "foo" on the end of the repeat, but it wasn't
needed. I'm not even sure it was checked (ie, you might have been able
to get away with "end repeat bar" there).
--
Online waterways route planner: http://canalplan.org.uk
development version: http://canalplan.eu

Richard Tobin

unread,
Nov 16, 2009, 4:44:09 PM11/16/09
to
In article <hds6lg$gnp$1...@news.eternal-september.org>,
Richard <rgr...@gmail.com> wrote:

>"break" is not more than a glorified goto.

No, it's a *restricted* goto. One of the objections to goto is that
it can result in "spaghetti code". Of course, not all uses of goto
have that result. A goto used as a break doesn't, but break has
the advantage of making clear locally that it doesn't.

Phil Carmody

unread,
Nov 18, 2009, 5:03:13 AM11/18/09
to
Keith Thompson <ks...@mib.org> writes:
> "bartc" <ba...@freeuk.com> writes:
[SNIP - deep loop escapes]
> But since neither "break <number>" nor "break <LABEL>" would, ahem,
> break any existing code, I really can't think of any sane reason to
> *prefer* the "break <number>" to "break <LABEL>".
>
> Can you?

Yes. Simpler and clearer.

What if you try to break to a label which doesn't correspond to
a loop?

Phil
--
Any true emperor never needs to wear clothes. -- Devany on r.a.s.f1

Ike Naar

unread,
Nov 18, 2009, 5:14:38 AM11/18/09
to
In article <87k4xoq...@kilospaz.fatphil.org>,

Phil Carmody <thefatphi...@yahoo.co.uk> wrote:
>Keith Thompson <ks...@mib.org> writes:
>> "bartc" <ba...@freeuk.com> writes:
>[SNIP - deep loop escapes]
>> But since neither "break <number>" nor "break <LABEL>" would, ahem,
>> break any existing code, I really can't think of any sane reason to
>> *prefer* the "break <number>" to "break <LABEL>".
>>
>> Can you?
>
>Yes. Simpler and clearer.
>
>What if you try to break to a label which doesn't correspond to
>a loop?

What if you try to "break <number>" when the number of loops you're in
is less than "number"?

Keith Thompson

unread,
Nov 18, 2009, 11:15:54 AM11/18/09
to
Phil Carmody <thefatphi...@yahoo.co.uk> writes:
> Keith Thompson <ks...@mib.org> writes:
>> "bartc" <ba...@freeuk.com> writes:
> [SNIP - deep loop escapes]
>> But since neither "break <number>" nor "break <LABEL>" would, ahem,
>> break any existing code, I really can't think of any sane reason to
>> *prefer* the "break <number>" to "break <LABEL>".
>>
>> Can you?
>
> Yes. Simpler and clearer.

Really? I disagree completely on both counts.

Consider a loop within a switch statement within a loop. Suppose I
want to break out of the outer loop from within the inner loop;
do I use "break 2;" or "break 3;"? What if I just want to finish
the current iteration of the outer loop; is that "continue 2;"
or "continue 3;"? Sure, it might be poor style, but the language
would have to define it.

But even in ordinary usage, I find names clearer than numbers.

Perl has this feature, and I often use it even for non-nested loops,
just because it makes the code clearer. Perl's equivalent of
"break" is "last". It's not uncommon to have an outer loop that
iterates over files and an inner loop that iterates over lines.
I can write "last LINE;" or "last FILE;" to terminate either the
inner loop or the outer loop; I find that *much* clearer than
"last 1;" or "last 2;".

At least one other person has complained that "break LABEL;"
is unclear because it jumps, not to LABEL, but to some point
after LABEL. The trick is that, when it's the used with a break or
continue statement, a label doesn't name a single point in the code;
it's the name of the loop as a whole. Assigning a name to a loop,
to be used when you want to do something related to that loop, makes
just as much sense to me as assigning a name to a function or object.

> What if you try to break to a label which doesn't correspond to
> a loop?

It would be a constraint violation.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Phil Carmody

unread,
Nov 19, 2009, 1:46:28 PM11/19/09
to

What if you try to "goto <label>" when the function you're in does not
contain a label <label>?

Fortunately compilers are as good at counting as they are at doing
string comparison, so I think most should cope with all three equally.

Keith Thompson

unread,
Nov 19, 2009, 2:50:43 PM11/19/09
to

Certainly. Nobody (I think) is suggesting that the difficulty
of the compiler getting this right is an issue. However it's
defined, as long as it's defined rigorously (including the
loop-with-switch-within-loop break vs. continue case), implementing
it won't be a problem. There's ample precedent in other languages.

My point is that, as a programmer, I find "break LOOP_NAME;" to be
much clearer and easier to use and maintain than "break COUNT;".

Would you want a function call construct that makes you refer to the
Nth function in the current translation unit? Or a struct member
syntax that makes you refer to the Nth member?

Computers refer to things by number. Programmers use symbolic names.
It's the compiler's job to translate one to the other.

Phil Carmody

unread,
Nov 21, 2009, 10:42:19 AM11/21/09
to

I've used label-less languages with counted breaks, and it all seemed
perfectly natural, so perhaps my point of view is tainted with that
experience.

Richard Bos

unread,
Dec 4, 2009, 11:06:34 AM12/4/09
to
"bartc" <ba...@freeuk.com> wrote:

> "Keith Thompson" <ks...@mib.org> wrote in message

> > But since neither "break <number>" nor "break <LABEL>" would, ahem,
> > break any existing code, I really can't think of any sane reason to
> > *prefer* the "break <number>" to "break <LABEL>".
>

> I have preference for break <no>, even though it looks crude, as break
> <label> is not actually much different from goto <label>, and it means
> thinking up a label in the first place and then remembering to add it at one
> end of the loop or the other.

Yes, that's exactly why break <label> would be _better_. It forces you
to be explicit about what you want.

Richard

bartc

unread,
Dec 4, 2009, 6:05:14 PM12/4/09
to

"Richard Bos" <ral...@xs4all.nl> wrote in message
news:4b192ba0...@news.xs4all.nl...

I remember driving in Germany where the Autobahn exits are given names
related to the locality instead of being numbered sequentially.

Which means that you have no idea when approaching an exit whether you've
missed your exit, or there's still some way to go.

In the same way, the number in break <number> gives you information that a
labeled break doesn't: whether you are breaking out of an inner, outer or
middle loop (as indicated by the current indentation).

--
Bartc

Kaz Kylheku

unread,
Dec 4, 2009, 9:58:54 PM12/4/09
to
On 2009-12-04, bartc <ba...@freeuk.com> wrote:
> "Richard Bos" <ral...@xs4all.nl> wrote in message
>> Yes, that's exactly why break <label> would be _better_. It forces you
>> to be explicit about what you want.
>
> I remember driving in Germany where the Autobahn exits are given names
> related to the locality instead of being numbered sequentially.
>
> Which means that you have no idea when approaching an exit whether you've
> missed your exit, or there's still some way to go.

Now /there/ is an argument for using numbers instead of symbols!

We should use offsets into a stack instead of symbolic local variables,
too. You never know when you might blow past a variable, and then have
to take a u-turn at the next frame to return there.

If they are numbered, you know that if you're at offset 44,
you failed to get off at the variable at offset 40.

Not a week goes by that this newsgroup doesn't satisfy a craving for a
good analogy.

Nick Keighley

unread,
Dec 5, 2009, 6:48:17 AM12/5/09
to
On 4 Dec, 23:05, "bartc" <ba...@freeuk.com> wrote:
> "Richard Bos" <ralt...@xs4all.nl> wrote in message

>
> news:4b192ba0...@news.xs4all.nl...
>
>
>
>
>
> > "bartc" <ba...@freeuk.com> wrote:
>
> >> "Keith Thompson" <ks...@mib.org> wrote in message
>
> >> > But since neither "break <number>" nor "break <LABEL>" would, ahem,
> >> > break any existing code, I really can't think of any sane reason to
> >> > *prefer* the "break <number>" to "break <LABEL>".
>
> >> I have preference for break <no>, even though it looks crude, as break
> >> <label> is not actually much different from goto <label>, and it means
> >> thinking up a label in the first place and then remembering to add it at
> >> one
> >> end of the loop or the other.
>
> > Yes, that's exactly why break <label> would be _better_. It forces you
> > to be explicit about what you want.
>
> I remember driving in Germany where the Autobahn exits are given names
> related to the locality instead of being numbered sequentially.

and it was usually called Ausgang. Numbers are handy because you don't
often add new exits. "Exit 11(a)" "Exit 11.1"?

Gus Gassmann

unread,
Dec 5, 2009, 10:23:38 AM12/5/09
to
Nick Keighley wrote:
> On 4 Dec, 23:05, "bartc" <ba...@freeuk.com> wrote:

>> I remember driving in Germany where the Autobahn exits are given names
>> related to the locality instead of being numbered sequentially.
>
> and it was usually called Ausgang.

Ausfahrt. (Sorry; couldn't let that one slide.)

0 new messages