Зацикливание лучших практик - PullRequest
1 голос
/ 26 марта 2009

У меня есть очень большой цикл, который повторяет 1000 строк. Я выхожу из цикла, если найдено магическое значение 1. Если магическое значение 1 не найдено, но магическое значение 2 найдено, то цикл необходимо перейти к началу. Прямо сейчас я использую переключатель, некоторые ifs и goto. Я читал, что Goto не лучший способ. Есть ли лучший способ сделать эту работу?

Ответы [ 7 ]

17 голосов
/ 26 марта 2009

Для выхода из цикла вы можете использовать оператор break , чтобы перейти к следующей записи, вы можете использовать оператор continue .

for(int i = 0; i < 1000; i++)
{
    if(magicValue1)
       break;
    if(magicValue2)
       continue;
}

Я не одобряю использование заявления GOTO. Я просто указал на возможный случай использования

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

for(int i = 0; i < 100; i++)
{ 
  start:

  for(int i = 0; i < 10; i++)
  {
     if(magicValue1)
       goto end;
    if(magicValue2)
       goto start;
  }
}
end : 
10 голосов
/ 26 марта 2009

Как насчет этого:

for(int i = 0; i < 1000; i++) {
    if(values[i] == MAGIC_VALUE_1) {
        break;
    } else if(values[i] == MAGIC_VALUE_2) {
        i = 0;
    }
}

Если под «переходом к началу» вы подразумеваете «пропустить эту запись и обработать следующую», замените i = 0 на continue.

3 голосов
/ 26 марта 2009

A while вариант без break:

bool continue = true; int i = 0;
while (i < 1000 && continue){
    if(values[i] == MAGIC_VALUE_1) {
        continue=false;
    } else if(values[i] == MAGIC_VALUE_2) {
        i = 0;
    }
    i++;
}
2 голосов
/ 26 марта 2009

Я пока не могу комментировать (1 реп.)

но не лучше ли это:

for (int i = 0; i < 1000; i++)
{
    if (magicValue1)
    {
       break;
    }
    else if (magicValue2)
    {
       dosomething();
       i=0;
    }
}

и я не уверен, что означает "перезапустить поиск".

1 голос
/ 26 марта 2009

Просто обратите внимание, что если вы установите счетчик обратно на 0, если MagicValue равно 2, и ваш код никогда не изменит значения, вы, вероятно, будете в бесконечном цикле.

1 голос
/ 26 марта 2009

Я использую случай # 2 для обозначения того, что вы хотите не выполнять (то есть пропускать) тело цикла в случае # 2, а не то, что вы хотите сбросить цикл на 0. (См. Комментарии к коду, если я ' Мы получили это назад.)

Это предложение может быть спорным, поскольку можно сказать, что менее условное условие в цикле for находится на низком уровне самодокументируемой шкалы, но если это вас не беспокоит, краткий способ написания того, что, как вам кажется, вам хочу это:

        for (int i= 0; i<values.Length && values[i]!= MAGIC_1; i++)
        {
            if (values[i] == MAGIC_2)
            {
                // Don't do the loop body for this case but continue on looping
                continue;
                // If you want to reset the loop to zero instead of skip the 2 case,
                // comment-out the continue; and un-comment the line below:
                // i=0;
            }
            // Do long loop body here
        }
0 голосов
/ 26 марта 2009

Более сложный может быть:

Мы определяем 2 метода расширения.

public static class Extensions
{
   public static bool isMagic_1(this int i)
   {
         return i == 1;
   }

   public static bool isMagic_2(this int i)
   {
         return i == 2;
   }
}

Теперь вы можете сделать это:

  for(int i = 0; i < 1000; i++)
  {
     if(i.isMagic_1())
       break;
     if(i.isMagic_2())
       continue;
  }

надеюсь, это поможет!

...