From: Nick on
"Alexei A. Frounze" <alexfrunews(a)gmail.com> writes:

> On Apr 25, 8:52 am, Nick <3-nos...(a)temporary-address.org.uk> wrote:
>>
>> Just today I found myself in such a situation where I had two such
>> blocks which, depending on a couple of conditions, I wanted to execute
>> one, the other, or both in both orders - right in the middle of a large
>> function.  So putting the code in functions several pages away from
>> where they were needed wasn't nice, and short of jumping around (either
>> with a loop even though there is only a single pass, or with goto) the
>> only other solution is to replicate the code.
>
> I don't know if this would work or not for your specific case, but if
> blocks are sufficiently large and it's exactly one or both in either
> order in the same place, then you could theoretically do something
> like this:
>
> #include <stdio.h>
> int main(void)
> {
> const int ss[4][2] =
> {
> { 1, 1 },
> { 2, 2 },
> { 1, 2 },
> { 2, 1 }
> };
> int i, cnt, start, stop, var;
>
> for (i = 0; i < 4; i++)
> {
> start = ss[i][0];
> stop = ss[i][1];
>
> for (var = start, cnt = 1 + (start != stop);
> cnt--;
> var += (stop >= start) ? 1 : -1)
> {
> if (var == 1) printf("block 1 ");
> else if (var == 2) printf("block 2 ");
> }
> printf("\n");
> }
>
> return 0;
> }

That's the sort of thing (the var loop) that I meant by playing around
with loops. That is just so much more confusing than:

/* framework that sets do_first, do_second and first_is_first from array */
if(do_first && first_is_first)
printf("block 1\n");
if(do_second)
printf("block 2\n");
if(do_first && !first_is_first)
printf("block 1\n");

Which is exactly the problem - this one is clear, but gets messy if
"block 1" is a few lines but not obviously a function. Yours avoids
that, but is far from clear at first sight why it's looping.

If I was going for a loop, I'd be far more likely to set those three
variables, as for the above code and then create another flag and do:

do_first_this_time = do_first && first_is_first;
for(;;) {
if(do_first_at_all)
printf("Block 1\n");
if(do_second) {
printf("Block 2\n");
do_second = false;
}
if(do_first && !first_is_first) {
do_first_this_time = true;
continue;
} else
break;
}

Yes, pretty hideous. I still prefer it to yours though!
--
Online waterways route planner | http://canalplan.eu
Plan trips, see photos, check facilities | http://canalplan.org.uk
From: Alexei A. Frounze on
On Apr 25, 11:21 am, Nick <3-nos...(a)temporary-address.org.uk> wrote:
> "Alexei A. Frounze" <alexfrun...(a)gmail.com> writes:
>
>
>
> > On Apr 25, 8:52 am, Nick <3-nos...(a)temporary-address.org.uk> wrote:
>
> >> Just today I found myself in such a situation where I had two such
> >> blocks which, depending on a couple of conditions, I wanted to execute
> >> one, the other, or both in both orders - right in the middle of a large
> >> function.  So putting the code in functions several pages away from
> >> where they were needed wasn't nice, and short of jumping around (either
> >> with a loop even though there is only a single pass, or with goto) the
> >> only other solution is to replicate the code.
>
> > I don't know if this would work or not for your specific case, but if
> > blocks are sufficiently large and it's exactly one or both in either
> > order in the same place, then you could theoretically do something
> > like this:
>
> > #include <stdio.h>
> > int main(void)
> > {
> >   const int ss[4][2] =
> >   {
> >     { 1, 1 },
> >     { 2, 2 },
> >     { 1, 2 },
> >     { 2, 1 }
> >   };
> >   int i, cnt, start, stop, var;
>
> >   for (i = 0; i < 4; i++)
> >   {
> >     start = ss[i][0];
> >     stop = ss[i][1];
>
> >     for (var = start, cnt = 1 + (start != stop);
> >          cnt--;
> >          var += (stop >= start) ? 1 : -1)
> >     {
> >       if (var == 1) printf("block 1 ");
> >       else if (var == 2) printf("block 2 ");
> >     }
> >     printf("\n");
> >   }
>
> >   return 0;
> > }
>
> That's the sort of thing (the var loop) that I meant by playing around
> with loops.  That is just so much more confusing than:
>
> /* framework that sets do_first, do_second and first_is_first from array */
> if(do_first && first_is_first)
>             printf("block 1\n");
> if(do_second)
>             printf("block 2\n");
> if(do_first && !first_is_first)
>             printf("block 1\n");
>
> Which is exactly the problem - this one is clear, but gets messy if
> "block 1" is a few lines but not obviously a function.  Yours avoids
> that, but is far from clear at first sight why it's looping.
>
> If I was going for a loop, I'd be far more likely to set those three
> variables, as for the above code and then create another flag and do:
>
> do_first_this_time = do_first && first_is_first;
> for(;;) {
>         if(do_first_at_all)
>                 printf("Block 1\n");
>         if(do_second) {
>                 printf("Block 2\n");
>                 do_second = false;
>         }
>         if(do_first && !first_is_first) {
>                 do_first_this_time = true;
>                 continue;
>         } else
>                 break;
>
> }
>
> Yes, pretty hideous.  I still prefer it to yours though!
> --
> Online waterways route planner            |http://canalplan.eu
> Plan trips, see photos, check facilities  |http://canalplan.org.uk

:)

Actually, there was some left-over from the previous attempt, so this
one is a tad more simple:
....
for (var = start, cnt = 1 + (start != stop);
cnt--;
var += stop - start)
{
if (var == 1) printf("block 1 ");
else if (var == 2) printf("block 2 ");
}
....

Alex
From: James Dow Allen on
On Apr 25, 10:03 pm, "Daniel T." <danie...(a)earthlink.net> wrote:
> James Dow Allen <jdallen2...(a)yahoo.com> wrote:
>> > understood: Edsger W. Dijkstra wrote:
> > > The unbridled use of the go to statement has an immediate
> > > consequence that it becomes terribly hard to find a meaningful set
> > > of coordinates in which to describe the process progress.
> .
> > (Hmmm.  Dijkstra *does* write "UNBRIDLED use of goto".  Funny how that
> > disappears from the pedants' sound-bite summaries.)
> .
> Agreed, and many also fail to notice that it is rather hard to use goto
> in an "unbridled" fashion in C and C++.

Did you mean "bridled"? ... Since you were arguing against goto.
> .
> > One of my own goto's appears horrendous...
> >http://fabpedigree.com/james/dbldum.htm
> .
> It looks as though you have implemented a depth first search.

Yes. Or rather backtracking, which is DFS with a smidgen
of extra control logic. The problem specifics mean there's
3 or 4 "smidgens" of extra control logic here. And in my
comments I admit that there are better ways to deal with *simpler*
backtracking problems, and better ways to deal with *harder*
backtracking applications.

> ... I fully agree that your code is better than the psudo-code you
> present in comparison ...

Well, thanks for that! The side-by-side comparison clearly shows
that I use 1 goto and 1 for-loop to avoid 2 break's, 4 if's,
2 else's and 2 other minor defects. I'm not arguing that goto's
aren't bad, just that other things (break's, too many variables,
etc.) are also bad and one seeks compromise.

> there are better ways of implementing depth first searches
> than either of the two you present.

If you submit working code that runs slower than mine by no more
than 20%, I will show it at the website as "Daniel's structured
improvement." (Speed *is* important of course for the target
application.)

James
From: io_x on

"wolfgang kern" <nowhere(a)never.at> ha scritto nel messaggio
news:hr1a9j$4qf$1(a)newsreader2.utanet.at...
>
> "io_x" wrote:
>> [Xpost to: alt.comp.programming, alt.lang.asm,
>> comp.lang.c, comp.lang.c++, comp.programming]
>
>> the people that speak not good about "goto"
>> are uttled wrong; their code bug full etc
>
>> more distant is your code from goto
>> more your code is bug full and incompresible
>
>> the "goto" is the key word for programming;
>> all the remain, other than goto or jmp or jc or jz,
>> and the easy cpu layout
>> is the wrong way for programming
>
> Except that GOTO is a HLL keyword and I'm Asmist and
> more machine-code oriented than concerned about needs
> within abstract structured HLL-compilers, I see nothing
> wrong with GOTO as long it does what a programmer want.

you see all jmp, je, jc etc etc for me they are all gotos

> I once checked PowerBasic's GOTO and found it always
> compiled a long (16:16) jump, even rare required.
> But its syntax checker cried aloud if you tried to
> jump out of a [FOR/IF/...]-struct with GOTO.

i used when i were 12-13, Basic too the Basic for vic-20
i think it was not the way for programming well

> I don't know C/C+-, but what I see by disassembling their
> resulting output seem to end up in heavy bloated code,
> perhaps from using BREAK and GOTO within nested blocks,
> which the compiler may grant with copying all required
> code-trails (stack recover/cleanup) to every added path.
> So in this aspect GOTO may be really not the best choice.

if you see the asm, without the .c or .cpp line of the traslation
could be difficult to understand

> see me happy for I don't need to care this in my world :)

it is not possible that i wrote some functions easily
than in C or in C++, with not big time,
without the "gotos==very good"

> __
> wolfgang (ALA)



From: Stuart Redmann on


Richard wrote:
[snip]
> There is nothing whatsoever wrong with a break statement - it frequently
> helps against overly convoluted loop conditions.

Nicely put. If I will ever be tempted enough to actually start a
"poesiealbum" for little pieces of wisdom, this little gem would be
among the ten first entries (why, it would probably the first).

Just to add my 2 cents:
Your statement says that break-statements (I really like the term
"goto in disguise", thank you, James) can keep the loop condition
short and sweet. I think that this is probably not the most convincing
argument for the usage of break-statements, but the readability of
code should not be underestimated. That's why I'd suggest that also
the use of continue-statements can increase the readability a lot. If
you have a look at the following piece of code (from actual production
environment):

// Iterate through all interfaces from the type library.
UINT uiNumberOfTypes = spTypeLib->GetTypeInfoCount ();
for (int i = 0; i < uiNumberOfTypes; i++)
{
ITypeInfoPtr spCurrTypeInfo;
spTypeLib->GetTypeInfo (i, &spCurrTypeInfo);
if (!(bool) spCurrTypeInfo)
return false;

// We only want to process interface definitions, so if we encounter
anything
// else (for example enums), we skip the rest of the loop.
TYPEATTR* pCurrentTypeAttr;
VERIFY (SUCCEEDED (spCurrTypeInfo->GetTypeAttr
(&pCurrentTypeAttr)));
if (pCurrentTypeAttr->typekind != TKIND_DISPATCH &&
pCurrentTypeAttr->typekind != TKIND_INTERFACE)
continue;

: // here comes a quite lengthy loop rest of the loop body (about
130 lines)
}

The same code without a continue-statement would add an if-statement,
which would indent the quite lengthy loop body one more time. Most
people would probably ask "So what?" In my opinion too much indented
code is almost as unreadable as a goto-ridden spaghetti code. When you
have a quite lengthy loop/if body, it's quite easy to forget under
which which conditions the code will actually run (which is why many
people repeat the condition of an if-statement as comment in the else-
part). Keeping this information as small as possible (in above case
the user has only to remember: "we are iterating through the type
library" instead of "we are iterating through all elements of the type
library that are actually interfaces") is, in my eyes, one of the
keypoints of writing readable code: it kind of better matches the
"information flow" of the human brain (I'm probably sticking my neck
out with this thesis, it'd be really interesting to find out whether
this can be backed up scientifically).

As you can see, I couldn't put it as short as you could.

Regards,
Stuart