From: Nick on 25 Apr 2010 14:21 "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 25 Apr 2010 14:50 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 26 Apr 2010 00:31 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 26 Apr 2010 02:46 "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 26 Apr 2010 03:03
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 |