Как я могу вырваться из двух вложенных циклов в Objective-C?

У меня есть два цикла, вложенные следующим образом:

for(...) {
    for(...) {

    }
}

Я знаю, что существует инструкция break. Но я смущен, если он сломает обе петли или просто ту, в которой она была вызвана? Мне нужно сломать оба, как только я увижу, что не имеет смысла повторять больше раз.

Ответ 1

break вырывается из одного цикла, но вы можете добавить проверку на внешний цикл, который прерывается, когда внутренний разрыв.

bool dobreak = false;
for ( ..; !dobreak && ..; .. ) {
   for ( ... ) {
      if (...) {
         dobreak = true;
         break;
      }
   }
}

Ответ 2

Если использование goto упрощает код, тогда это будет уместно.

for (;;) 
{
    for (;;) 
    {
        break; /* breaks inner loop */
    } 
    for (;;) 
    {
        goto outer; /* breaks outer loop */
    }
} 
outer:;

Ответ 3

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

void do_lots_of_work(void)
{
  int i, j;

  for(i=0; i<10 ; i++)
  {
    for(j=0;j< 10; j++)
    {
     ..
     ..
     if(disaster_struck())
      return; /* Gets us out of the loops, and the function too. */
    }
  }
}

Ответ 4

Помимо уже упомянутой переменной флага или goto вы можете throw исключение Objective-C:

@try {
  for() {
    for() {
       @throw ...
    }
  }
}
@catch{
  ...
}

Ответ 5

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

for (int i = 0; i < 10; i++) {
   if (timeToStop(i)) break;
}

-(bool) timeToStop: (int) i {
    for (int j = 0; j < 10; j++) {
        if (somethingBadHappens) return true;
    }

    return false;
}

Pseudocode, не тестировался, но вы поняли идею.

Ответ 6

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

bool isTerminated = false;

for (...)
{
    if (!isTerminated)
    {
        for(...)
        {
            ...

            isTerminated = true;
            break;
        }
    }
    else
    {
        break;
    }
}

Ответ 7

Вероятно, самый простой способ - использовать переменную "флаг"

for(i=0; i<10 && (done==false); i++)
  for(j=0;j< 10; j++){
     ..
     ..
     if(...){done=true; break;}
  }

Ответ 8

Сменить счетчик верхнего контура перед разрывом

for(i=0; i<10 ; i++)
  for(j=0;j< 10; j++){
     ..
     ..
     i = 10; 
     break;
  }

Ответ 9

Другим решением является фактор второго цикла в функции:

int i;

for(i=0; i<10 ; i++){
    if !innerLoop(i) {
        break;
    }
}

bool innerLoop(int i)
    int j;
    for(j=0;j< 10; j++){
        doSomthing(i,j);
        if(endcondtion){
            return false;
        }
    }
}

Ответ 10

Если разрыв выполняется из набора вложенных циклов, завершается только самый внутренний цикл, в котором выполняется разрыв. (Так же, как стандарт C)

Ответ 11

Оператор break вырывается из самого внутреннего цикла. Для выхода из внешнего цикла потребуется дополнительный тест и оператор break.

Ответ 12

Точно так же, как и последние, обычно такие:

for(i=0;i<a;i++){  
 for(j=0;j<a;j++){
  if(Something_goes_wrong){
   i=a;
   break;
   }
 }
}

Ответ 13

Просто для усмешек, как насчет изменения этой проверки true/false в методе и с помощью операторов return:

- (bool) checkTrueFalse: parameters{

   for ( ...) {
      for ( ... ) {

         if (...) {
            return true;
         }

      }
   }
   return false;
}