Как я могу переписать это (чисто) без gotos? - PullRequest
4 голосов
/ 03 апреля 2010

Как я могу сделать это чисто без gotos?

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

Я бы предпочел также не использовать перерывы. Кроме того, ожидается, что он будет зациклен несколько раз (до 40), прежде чем делать что-то еще, так что часть mostOfTheWork, скорее всего, будет как можно выше, даже если только для удобства чтения. Заранее спасибо.

РЕДАКТИРОВАТЬ: Это было опубликовано в заблуждение, что оптимизатор компилятора плохо работал с перерывами, что, хотя, как правило, с самого начала глупо, я для себя оказался неверным с помощью экспериментов (производительности). С другой стороны, спасибо за ваши ответы; они были интересны, читают разные стили.

Ответы [ 8 ]

10 голосов
/ 03 апреля 2010

Очевидно, что вы выйдете из цикла, если произойдет любое из условий.

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

Итак, сделайте цикл, пока ни одно из условий не сработало, а затем посмотрите, какое из них вас заполучило.

Теперь кто-то закричит, что я оценил условия больше, чем мне нужно к. В их пользу модифицированная версия:

{
  bool t1, t2;
  while ((!(t1 = condition1)) && (!(t2 =condition2))) {
    MostOfTheWork();
  }
  if (t1) {
    something();
  } else if (t2) {
    somethingDifferent();
  }
}
10 голосов
/ 03 апреля 2010
bool done = false ;

while( !done ) {
  if(condition1){
    something();
    done = true ;
  } else if (condition2) {
    somethingDifferent();
    done = true ;
  } else {
    mostOfTheWork();
  }
} 
2 голосов
/ 03 апреля 2010

без перерывов?

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

Тем не менее, существуют перерывы для управления потоком, они гораздо яснее относительно того, что они делают, чем goto, поэтому я бы рекомендовал их использовать. Однако в этом случае я бы рекомендовал @ John's answer как правильный способ сделать это.

1 голос
/ 03 апреля 2010

Профессоры CS, вероятно, просунули вам в голову, что это плохо и может нанести ущерб вашему коду. Gotos на самом деле довольно эффективны при правильном и целенаправленном использовании. Вот почему большинство языков программирования не отказались от него.

В вашем конкретном случае с goto все в порядке, потому что блок кода небольшой, и вы легко можете увидеть ход программы. Вы можете написать код спагетти и с другими структурами управления, хотя это немного сложнее.

1 голос
/ 03 апреля 2010

Нет gotos или клювы. Чистота как всегда, субъективно

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

Это, конечно, невероятно глупо. Просто используйте перерыв.

0 голосов
/ 02 июля 2014

По моему мнению, эта версия кода наиболее четко передает поток программы потомкам и является наиболее легко расширяемой. Да, я использую break. Я не могу придумать ни одной настоящей причины, чтобы этого не делать.

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

Если вы действительно не хотите использовать break, вы можете использовать goto, чтобы выйти из цикла, или return, чтобы выйти из функции (если этот цикл является частью более крупной функции вам придется провести рефакторинг).

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

Или

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

И если вы отказываетесь использовать какой-либо элемент управления потоком, кроме if и while, как насчет этого:

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

Также, пожалуйста, см. мой канонический ответ для такого рода вопроса (и проголосуйте за него!)

0 голосов
/ 03 апреля 2010
do
{
  if(condition1){
    something();
  } else if (condition2) {
    somethingDifferent();
  } else {
    mostOfTheWork();
  }
} while (!condition1 && !condition2)
0 голосов
/ 03 апреля 2010

Поскольку вы не указали язык, в некоторых языках есть continue, next или skip, которые вы можете использовать вместо goto.

...