开发者

How can I rewrite this (cleanly) without gotos?

开发者 https://www.devze.com 2022-12-25 06:17 出处:网络
How can I do this cleanly without gotos? loop: if(condition1){ something(); } else if (condition2) { somethingDifferent();

How can I do this cleanly without gotos?

loop:
  if(condition1){
    something();
  } else if (condition2) {
    somethingDifferent();
  } else {
    mostOfTheWork();
    goto loop;
  }

I'd prefer not to use breaks as well. Furthermore, it is expected to loop several (adv 40) times before doing something else, so the mostOfTheWork part would most likely be as high up as possible, even if just for readability. Thanks in advance.

EDIT: This was posted under the misconception that the compiler optimizer worked poorly with breaks, which, while genera开发者_开发百科lly stupid to begin with, I have proven incorrect to myself through experimentation (of performance). On the other hand, thank you for your answers; they have been interesting reads on varying styles.


Clearly, you will break out of the loop if either condition fires.

    while ((!condition1) && (!condition2)) {
      MostOfTheWork();
    }
    if (condition1) {
      something();
    } else if (condition2) {
      somethingDifferent();
    }

So, loop while neither condition has fired, then see which one got you.

Now, someone will scream that I evaluated the conditions more than I needed to. For their benefit, a modified version:

{
  bool t1, t2;
  while ((!(t1 = condition1)) && (!(t2 =condition2))) {
    MostOfTheWork();
  }
  if (t1) {
    something();
  } else if (t2) {
    somethingDifferent();
  }
}


bool done = false ;

while( !done ) {
  if(condition1){
    something();
    done = true ;
  } else if (condition2) {
    somethingDifferent();
    done = true ;
  } else {
    mostOfTheWork();
  }
} 


Without breaks?

function foo(){
  if(condition1){
    something();
    return;
  } else if (condition2) {
    somethingDifferent();
    return;
  }
  mostOfTheWork();
  foo(); //(Tail recursive for those worried about stack overflows)
}

However, breaks are there for flow control, they are much clearer as to what they do than goto, so I would recommend using them. However in this case I would recommend @John's answer as the correct way to do it.


No gotos or beaks. Cleaniless as always, subjective

 do {
   if ( condition1 )
     something();
   else if( condition2 )
     somethingElse();
   else
     mostOfTheWork();
 } while( !(condition1 || condition2) );

This is of course, incredibly silly. Just use a break.


You've probably had it drilled into your head by CS professors that it's bad and will wreak havoc in your code. Gotos are actually quite efficient when used properly and purposely. This is why most programming languages haven't dropped it.

In your particular case, the goto is fine because the block of code is small and you can easily see the program flow. You can write spaghetti code with other control structures too, although it's a little harder to do.


Since you weren't specific about a language, some languages have continue, next or skip that you can use in place of that goto.


do
{
  if(condition1){
    something();
  } else if (condition2) {
    somethingDifferent();
  } else {
    mostOfTheWork();
  }
} while (!condition1 && !condition2)


In my opinion this version of the code most clearly communicates the program flow to posterity, and is the most easily extended. Yes, I'm using break. I can't think of any real reason not to.

while(true)
{
    if (condition1)
    {
        something();
        break;
    }
    if (condition2)
    {
        somethingDifferent();
        break;
    }
    mostOfTheWork();
}

If you really don't want to use break, you can use goto to get out of the loop, or use return to bail out of the function (if this loop is part of a larger function you'd have to refactor).

while(true)
{
    if (condition1)
    {
        something();
        goto exit;
    }
    if (condition2)
    {
        somethingDifferent();
        goto exit;
    }
    mostOfTheWork();
}
exit:

Or

while(true)
{
    if (condition1)
    {
        something();
        return;
    }
    if (condition2)
    {
        somethingDifferent();
        return;
    }
    mostOfTheWork();
}

And if you refuse to use any flow control other than if and while, how about this one:

bool ok = true;
while(ok)
{
    if (condition1)
    {
        something();
        ok = false;
    }
    if (ok && condition2)
    {
        somethingDifferent();
        ok = false;
    }
    if (ok)
    {
        mostOfTheWork();
    }
}

Also, please see my canonical answer for this sort of question (and vote for it!)

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号