Как вырваться из вложенных циклов?

Если я использую 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 ответов


о:

if(condition) {
i = j = 1000;break;
}

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

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

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

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

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

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

enter image description here

источник

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


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

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

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

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

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

end:
stmt2 

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

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;
    }
  }
}

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

"превратить циклы предикатов в функции предикатов"

посмотреть:

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


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

for(i;i< 1000; i++){    
    for(j; j< 1000; j++){
        if(condition)
            break;
    }
    if(condition) //the same condition
        break;
}

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

end:

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

Если вы используете 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);
       }
   }
}

i = 0;

do
{
  for (int j = 0; j < 1000; j++) // by the way, your code uses i++ here!
  {
     if (condition)
     {
       break;
     }
  }

  ++i;

} while ((i < 1000) && !condition);

int i = 0, j= 0;

for(i;i< 1000; i++){    
    for(j; j< 1000; j++){
        if(condition){
            i = j = 1001;
            break;
        }
    }
}

разорвет оба цикла.


for(int i = 0; i < 1000; i++) {
    for(int j = 0; j < 1000; i++) {
       if(condition) {
          func(para1, para2...);
          return;
       }
    }
}

func(para1, para2...) {
    stmt2;
}