Как вырваться из вложенных циклов? - PullRequest
79 голосов
/ 14 марта 2012

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

Есть ли другой способ разорвать все петли? (Пожалуйста, не используйте goto stmt.)

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; j++) {
       if(condition) {
            // both of the loops need to break and control will go to stmt2
       }
   }

}

stmt2

Ответы [ 13 ]

154 голосов
/ 14 марта 2012

Нет, не портите веселье с break.Это последнее оставшееся допустимое использование goto;)

Если бы не это, вы могли бы использовать флаги для выхода из глубоких вложенных циклов.

Другой подход к разрыву вложенного цикла состоит в выделении обоих циклов в отдельную функцию и возвращении из этой функции, когда вы хотите выйти.

Суммировано - чтобы вырваться из вложенных циклов:

  1. использовать goto
  2. использовать флаги
  3. разбивать циклы на отдельные вызовы функций

Не смог устоять, включая xkcd здесь:)

enter image description here

source

Goto's areсчитается вредным , но как многие люди в комментариях предполагают, что это не должно быть.При разумном использовании это может быть отличным инструментом.Все, что используется в модерации, - это весело.

41 голосов
/ 14 марта 2012

А как же:

if(condition) {
i = j = 1000;break;
}
34 голосов
/ 14 марта 2012
bool stop = false;
for (int i = 0; (i < 1000) && !stop; i++)
{
    for (int j = 0; (j < 1000) && !stop; j++)
    {
        if (condition)
            stop = true;
    }
}
23 голосов
/ 14 марта 2012

Одним из способов является помещение всех вложенных циклов в функцию и возврат из самого внутреннего цикла в случае необходимости разрыва всех циклов.

function() 
{    
  for(int i=0; i<1000; i++)
  {
   for(int j=0; j<1000;j++)
   {
      if (condition)
        return;
   }
  }    
}
15 голосов
/ 14 марта 2012

Я думаю goto решит проблему

for(int i = 0; i < 1000; i++) {
    for(int j = 0; j < 1000; i++) {
        if (condition) {
            goto end;
        }
    }
}

end:
stmt2 
11 голосов
/ 14 марта 2012

Вам понадобится логическая переменная, если вы хотите, чтобы она читалась:

bool broke = false;
for(int i = 0; i < 1000; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
  if (broke)
    break;
}

Если вы хотите, чтобы он был менее читабельным, вы можете присоединиться к логической оценке:

bool broke = false;
for(int i = 0; i < 1000 && !broke; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
}

В качестве окончательного способа вы можете сделать недействительным начальный цикл:

for(int i = 0; i < size; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      i = size;
      break;
    }
  }
}
7 голосов
/ 14 марта 2012

Используйте этот мудрый совет от команды LLVM:

«Превратить циклы предиката в функции предиката»

См .:

http://llvm.org/docs/CodingStandards.html#turn-predicate-loops-into-predicate-functions

4 голосов
/ 03 июня 2015

Если вам нужны значения i и j, это должно работать, но с меньшей производительностью, чем другие

for(i;i< 1000; i++){    
    for(j; j< 1000; j++){
        if(condition)
            break;
    }
    if(condition) //the same condition
        break;
}
3 голосов
/ 23 декабря 2017

Осторожно: этот ответ показывает действительно неясную конструкцию.

Если вы используете GCC, посмотрите эту библиотеку .Как и в PHP, break может принимать количество вложенных циклов, которые вы хотите выйти.Вы можете написать что-то вроде этого:

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; j++) {
       if(condition) {
            // break two nested enclosing loops
            break(2);
       }
   }
}
2 голосов
/ 14 марта 2012
for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; i++) {
       if(condition) {
            goto end;
   }
} 

end:
...