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

У меня есть два для вложенных циклов, как это:

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

    }
}

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

Ответы [ 13 ]

106 голосов
/ 14 мая 2009

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

for (;;) 
{
    for (;;) 
    {
        break; /* breaks inner loop */
    } 
    for (;;) 
    {
        goto outer; /* breaks outer loop */
    }
} 
outer:;
92 голосов
/ 14 мая 2009

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

bool dobreak = false;
for ( ..; !dobreak && ..; .. ) {
   for ( ... ) {
      if (...) {
         dobreak = true;
         break;
      }
   }
}
14 голосов
/ 14 мая 2009

Оператор 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. */
    }
  }
}
9 голосов
/ 15 мая 2009

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

@try {
  for() {
    for() {
       @throw ...
    }
  }
}
@catch{
  ...
}
7 голосов
/ 14 мая 2009

Другие упоминали, как вы можете установить флаг или использовать 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;
}

Псевдокод, не проверен, но вы поняли.

2 голосов
/ 02 сентября 2010

Другое решение - выделить второй цикл в функции:

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;
        }
    }
}
2 голосов
/ 14 мая 2009

Изменить счетчик верхней петли перед разрывом

for(i=0; i<10 ; i++)
  for(j=0;j< 10; j++){
     ..
     ..
     i = 10; 
     break;
  }
2 голосов
/ 14 мая 2009

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

for(i=0; i<10 && (done==false); i++)
  for(j=0;j< 10; j++){
     ..
     ..
     if(...){done=true; break;}
  }
2 голосов
/ 14 мая 2009

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

bool isTerminated = false;

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

            isTerminated = true;
            break;
        }
    }
    else
    {
        break;
    }
}
1 голос
/ 14 мая 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...