nested while - how to go to the beginning of the first while?

I

invni

I have a nested while. How do I go from the inner while to the
beginning of the outer while? Can this be done without using goto?

while_1()
{
some codes here
while_2()
{
if true go to the beginning of while_1
}
some codes here
}
 
S

Suman

invni said:
I have a nested while. How do I go from the inner while to the
beginning of the outer while?
I would hate to tell you how.
Can this be done without using goto?

What do you mean? Are you kidding? I have never come across a dialect
of
C that gives you while_# sort of keywords.Better post some real,
compile-able code, and we can bargain.Most often code that craves for a
goto,
needs a serious surgery.

[the garbage van just took your code away...]

You might find the following article handy:
http://groups.google.co.in/group/comp.lang.c/browse_frm/

thread/1f70380413394ff7/09a791583ae54898?q=goto&rnum=1&hl=en#09a791583ae54898

Suman.
 
R

Robert W Hand

I have a nested while. How do I go from the inner while to the
beginning of the outer while? Can this be done without using goto?

while_1()
{
some codes here
while_2()
{
if true go to the beginning of while_1
}
some codes here
}

Assuming the above is pseudocode, I suspect that you could use a
combination of break and continue. Here is a trivial sample that
makes decisions based on the value of a char variable named ch and a
counter.

int main(void)
{
char ch = 'Y';
int counter = 0;
while(ch == 'Y')
{
puts("Beginning of outer loop");
while(true)
{
puts("Beginning of inner loop");
if(ch == 'N')
break;
else
ch = 'N';
puts("End of inner loop");
}
if(ch == 'N')
{
if(counter++ == 0)
ch = 'Y';
continue;
}
puts("End of outer loop");

}
printf("Good-bye\n");
}

Output:
Beginning of outer loop
Beginning of inner loop
End of inner loop
Beginning of inner loop
Beginning of outer loop
Beginning of inner loop
End of inner loop
Beginning of inner loop
Good-bye

Note that it skips from beginning of the inner loop to the beginning
of the outer loop. HTH.
 
I

invni

Robert said:
Assuming the above is pseudocode, I suspect that you could use a
combination of break and continue. Here is a trivial sample that
makes decisions based on the value of a char variable named ch and a
counter.

int main(void)
{
char ch = 'Y';
int counter = 0;
while(ch == 'Y')
{
puts("Beginning of outer loop");
while(true)
{
puts("Beginning of inner loop");
if(ch == 'N')
break;
else
ch = 'N';
puts("End of inner loop");
}
if(ch == 'N')
{
if(counter++ == 0)
ch = 'Y';
continue;
}
puts("End of outer loop");

}
printf("Good-bye\n");
}

Output:
Beginning of outer loop
Beginning of inner loop
End of inner loop
Beginning of inner loop
Beginning of outer loop
Beginning of inner loop
End of inner loop
Beginning of inner loop
Good-bye

Note that it skips from beginning of the inner loop to the beginning
of the outer loop. HTH.

I got the idea. Thanks.
 
C

CBFalconer

invni said:
I have a nested while. How do I go from the inner while to the
beginning of the outer while? Can this be done without using goto?

while_1()
{
some codes here
while_2()
{
if true go to the beginning of while_1
}
some codes here
}

I think it is instructive that you need labels and a precise
definition to describe what you want. The above is not at all
precise.

lb1: while (c1) {
....
while (c2) {
....
if (c3) goto lb1;
....
}
....
}

can be replaced with:

int flag;

while (c1) {
....
flag = 0;
while (c2) {
....
if (c3) {
flag = 1; break;
}
....
}
if (flag) continue;
....
}

which lacks the clarity and simplicity of the goto version. When
appropriate, just use goto.
 
N

Netocrat

invni said:
I have a nested while. How do I go from the inner while to the beginning
of the outer while? Can this be done without using goto?
[snip]
I think it is instructive that you need labels and a precise definition
to describe what you want. The above is not at all precise.

lb1: while (c1) {
....
while (c2) {
....
if (c3) goto lb1;
....
}
....
}
}
can be replaced with:

int flag;

while (c1) {
....
flag = 0;
while (c2) {
....
if (c3) {
flag = 1; break;
}
....
}
if (flag) continue;
....
}
}
which lacks the clarity and simplicity of the goto version. When
appropriate, just use goto.

I second that opinion. Goto is justly maligned as often creating horrible
complexity, however its ability in certain circumstances to reduce
complexity is often overlooked.

This is one example of entirely appropriate and effective goto usage;
another is providing a common exit point to a function with nested loops:

int some_func(void)
{
while (c1) {
...
if (fatal1)
goto common_exit;
...
while (c2) {
...
if (fatal2)
goto common_exit;
...
}
}
return 0;
common_exit:
do_cleanup();
return 1;
}
 
M

Malcolm

CBFalconer said:
which lacks the clarity and simplicity of the goto version. When
appropriate, just use goto.
You're right, except that some people have got the idea into their heads
that goto is the root of all evil. (It can make over-long functions messier
still.)
Often its easier just to write a slightly worse function without goto than
enage in religious wars with someone who might be intent on stirring up
trouble.
 
L

Lawrence Kirby

I think it is instructive that you need labels and a precise
definition to describe what you want. The above is not at all
precise.

lb1: while (c1) {
....
while (c2) {
....
if (c3) goto lb1;
....
}
....
}

A good rule for using goto is use them when they are the best tool for the
job. It turns out that that is fairly rare but it is sometimes the case.

A good secondary rule is that if you use goto don't jump backwards, and in
effect create loops without explicit loop constructs. The old "spaghetti
code" syndrome uis much more difficult to create if you don't jump
backwards. I've only encountered one useful exception to this rule, and
that is implementing finite state machines. That works because FSMs
provides their own type of code structure (and hence a framework for
readability) but one that is different to the normal structured
programming block model. The code above is better written as

while (c1) {
....
while (c2) {
....
if (c3) goto lb1;
....
}
....

lbl1: ;
}
can be replaced with:

int flag;

while (c1) {
....
flag = 0;
while (c2) {
....
if (c3) {
flag = 1; break;
}
....
}
if (flag) continue;
....
}

which lacks the clarity and simplicity of the goto version. When
appropriate, just use goto.

It can be written without gotos or flag variables:

while (c1) {
....
for (;;) {
if (!c2) {
....
break;
}
....
if (c3) break;
....
}
}

although I don't claim this is better.

Lawrence
 
A

akarl

invni said:
I have a nested while. How do I go from the inner while to the
beginning of the outer while? Can this be done without using goto?

while_1()
{
some codes here
while_2()
{
if true go to the beginning of while_1
}
some codes here
}

You can probably restructure your code to make it simpler. Give a more
detailed example of what you're trying to do.
 
K

Kenny McCormack

You can probably restructure your code to make it simpler. Give a more
detailed example of what you're trying to do.

There was a discussion here (started by yours truly) of the merits of
"break n" (which exists in Bourne and Bourne-like shells). The concensus
was that it was a bad idea and that a (well timed and well placed) goto
should be used instead.

The problem, however, is if your organization forbids goto.

<OT>
Or, if you are not programming in C, but in some similar language, such as
AWK or Pascal (*) or whatever that doesn't have gotos at all.

(*) I know some versions of Pascal do have goto, but my understanding is
that the pure form (of a language that was specifically invented to argue
the case that goto [like drugs, mmkay] is bad) does not.
 
R

Richard Harter

I have a nested while. How do I go from the inner while to the
beginning of the outer while? Can this be done without using goto?

while_1()
{
some codes here
while_2()
{
if true go to the beginning of while_1
}
some codes here
}

The question I have is whether you want to do it in a sane way or in
an insane way. If the latter, look up Duff's device.


Richard Harter, (e-mail address removed)
http://home.tiac.net/~cri, http://www.varinoma.com
Save the Earth now!!
It's the only planet with chocolate.
 
O

osmium

Or, if you are not programming in C, but in some similar language, such as
AWK or Pascal (*) or whatever that doesn't have gotos at all.

(*) I know some versions of Pascal do have goto, but my understanding is
that the pure form (of a language that was specifically invented to argue
the case that goto [like drugs, mmkay] is bad) does not.

Your understanding of Pascal is seriously flawed, standard Pascal does
indeed have a goto statement.

Similarly, I have read in some publication or other that C does not have a
goto. One side effect of the information explosion is the concurrent
disinformation explosion.

Standard Pascal does not have, however, break, continue and the premature
return of C which all serve to minimize the use of goto..
 
K

Kenny McCormack

Or, if you are not programming in C, but in some similar language, such as
AWK or Pascal (*) or whatever that doesn't have gotos at all.

(*) I know some versions of Pascal do have goto, but my understanding is
that the pure form (of a language that was specifically invented to argue
the case that goto [like drugs, mmkay] is bad) does not.

Your understanding of Pascal is seriously flawed, standard Pascal does
indeed have a goto statement.

Your ability to comprehend conversational English is "seriously flawed",
since otherwise you'd realize how dumb your post sounds.
 
O

osmium

Kenny McCormack said:
Or, if you are not programming in C, but in some similar language, such
as
AWK or Pascal (*) or whatever that doesn't have gotos at all.

(*) I know some versions of Pascal do have goto, but my understanding is
that the pure form (of a language that was specifically invented to
argue
the case that goto [like drugs, mmkay] is bad) does not.

Your understanding of Pascal is seriously flawed, standard Pascal does
indeed have a goto statement.

Your ability to comprehend conversational English is "seriously flawed",
since otherwise you'd realize how dumb your post sounds.

"Some versions" and "does not" sounded to me like you were discussing a real
language. I see now that you were addressing the subject of a language that
someone could conceivably propose, or even write, some time. Would you
agree that this sentence, which doesn't mention Pascal, was a better
representation of what you meant?

"My understanding is that the pure form of a language specifically invented
to argue that goto was bad would not have a goto?"
 
K

Kenny McCormack

osmium said:
"Some versions" and "does not" sounded to me like you were discussing
a real language. I see now that you were addressing the subject of
a language that someone could conceivably propose, or even write, some
time. Would you agree that this sentence, which doesn't mention Pascal,
was a better representation of what you meant?

"My understanding is that the pure form of a language specifically
invented to argue that goto was bad would not have a goto?"

I'm OK with this.
 
R

Robert Maas, see http://tinyurl.com/uh3t

From: CBFalconer said:
lb1: while (c1) {
....
while (c2) {
....
if (c3) goto lb1;
....
}
....
}
From: Lawrence Kirby <[email protected]>
while (c1) {
....
while (c2) {
....
if (c3) goto lb1;
....
}
....

lbl1: ;
}
Note that both samples of code jump from inside a block to somewhere
outside that block. (One jumps out from two blocks, while the other
jumps out from the inner block while remaining in the outer block.)
Neither is *really* jumping backwards. The one that jumps out two
levels is really re-starting the outer block. A restart is not
*exactly* the same thing as a backwards jump, although I'm probably
shaving closely to note any difference here.

There's an advantage to the second method, of never jumping even
seemingly backwards. Consider the following *wrong* code:
while (c1) {
lbl1: ;
....
while (c2) {
....
if (c3) goto lb1;
....
}
....

}
Note that the outer loop is re-started except that the condition for it
is not re-tested here. This is not the same semantics as the first
examples where it's always re-tested after the jump, and horrible bugs
can happen this bad way.

Note: The one thing you should *never* do, not *ever* *ever*, is jump
from outside a loop to inside a loop, or even into a block.
(If anyone can think of a valid example of such, please post now!)

Note that at the machine level, jumping from inside one block to inside
an unrelated block is done all the time, namely when returning from a
function that was called. And if you're working on a really primitive
CPU that doesn't even have a return instruction, so you have to emulate
it by explicitly popping the return address off a stack and using it to
perform an indirect-address jump, then the jump into the calling block
is quite explicit. So my statement above does not apply to
machine-language returns, whether via return instruction or via
emulation of such, OK?

I was thinking a little earlier about how my Distributed Java
instructor said we need to learn how to drive a stick shift to
understand what's really happening before we drive an automatic, so we
needed to manually write SQL via JDBC/ODBC, and manually call servlets,
and manually do RMI, before we could finally drive the J2EE EJB
automatic! If this philosophy were carried to the extreme, we should
all be required to write machine-language code, then assembly-language
code for a machine that doesn't even have a return instruction so we
understand what's really happening, and then write assembly language
code for a regular machine with a fine return instruction, and finally
we can use C or other ordinary programming language. I was thinking how
much fun it'd be to write such a machine/assembly-language emulator for
beginning students to play with. Having it totally interactive with
nice GUI instead of physical toggle switches on front panel would make
it more edudational and less of a pain to use. Any comments from the
rest of you-all? Knuth had something like this in his books, except
there wasn't a Web-accessible emulator to play with, so you can think
of this as a modern version of Knuth's "Mix machine". Hmm, actually
there should be a wider range of options, all the way down below
machine language to state machines that emulate a computer, to logic
gates that build a state machine, to transistor circuits that build a
logic gate. The student could select which level of abstration to work
on at any given time. At the high end of the scale, above
function-calling would be lexical closures which are used to build OOP.
Hmm, should I copy this to comp.programming?
 
M

Michael Mair

Robert said:
Note: The one thing you should *never* do, not *ever* *ever*, is jump
from outside a loop to inside a loop, or even into a block.
(If anyone can think of a valid example of such, please post now!)

Partial loop unrolling or jumping into a do....while loop might
give you justifyable examples. No, I do not advocate it.
BTW: See Duff's device for some (not-goto) inspiration on that matter.

Cheers
Mihcael
 
L

Lawrence Kirby

Note that both samples of code jump from inside a block to somewhere
outside that block. (One jumps out from two blocks, while the other
jumps out from the inner block while remaining in the outer block.)
Neither is *really* jumping backwards.

One is precisely jumping backwards because it is jumping to a label
earlier on in the source code.
The one that jumps out two
levels is really re-starting the outer block.

In effect by creating an extra loop without an explicit looping construct.
This is almost always a bad idea.
A restart is not
*exactly* the same thing as a backwards jump, although I'm probably
shaving closely to note any difference here.

It doesn't have to do anything different, the forward jump I suggested has
the same overall effect. The important thing is how it is presented.
Structured programming constructs don't do anything you can't do with
conditional gotos, it is simply a better means of presentation and
conceptualisation.
There's an advantage to the second method, of never jumping even
seemingly backwards. Consider the following *wrong* code:
Note that the outer loop is re-started except that the condition for it
is not re-tested here. This is not the same semantics as the first
examples where it's always re-tested after the jump, and horrible bugs
can happen this bad way.

Yes, that's another example of why backwards jumps are a bad idea.
Note: The one thing you should *never* do, not *ever* *ever*, is jump
from outside a loop to inside a loop, or even into a block.
(If anyone can think of a valid example of such, please post now!)

Yes, that's evil too.
Note that at the machine level, jumping from inside one block to inside
an unrelated block is done all the time, namely when returning from a
function that was called. And if you're working on a really primitive
CPU that doesn't even have a return instruction, so you have to emulate
it by explicitly popping the return address off a stack and using it to
perform an indirect-address jump, then the jump into the calling block
is quite explicit. So my statement above does not apply to
machine-language returns, whether via return instruction or via
emulation of such, OK?

It is a matter of the readability of the code. For compiler generated code
that doesn't have to be readable it isn't important. For hand written
assembly which may have to be read and maintained it is certainly an issue.

Lawrence
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top