Как вырваться из двух вложенных циклов for в Objective-C?
У меня есть два для вложенных циклов, как это:
for(...) {
for(...) {
}
}
Я знаю, что есть break
заявление. Но меня смущает, сломает ли она обе петли или только ту, в которой она была вызвана? Мне нужно сломать оба, как только я увижу, что нет смысла повторять больше раз.
13 ответов
break прерывает один цикл, но вы можете добавить проверку к внешнему циклу, которая прерывается при разрыве внутреннего цикла.
bool dobreak = false;
for ( ..; !dobreak && ..; .. ) {
for ( ... ) {
if (...) {
dobreak = true;
break;
}
}
}
Если использование goto упрощает код, то это будет уместно.
for (;;)
{
for (;;)
{
break; /* breaks inner loop */
}
for (;;)
{
goto outer; /* breaks outer loop */
}
}
outer:;
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. */
}
}
}
Кроме уже упомянутой переменной flag или goto, вы можете выдать исключение Objective C:
@try {
for() {
for() {
@throw ...
}
}
}
@catch{
...
}
Другие упоминали, как вы можете установить флаг или использовать 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;
}
Псевдокод, не проверен, но вы поняли.
Оператор break будет выходить только из цикла в области видимости, который является родительским циклом. Если вы хотите выйти из второго цикла, вы можете использовать логическую переменную, которая находится в области действия обоих циклов
bool isTerminated = false;
for (...)
{
if (!isTerminated)
{
for(...)
{
...
isTerminated = true;
break;
}
}
else
{
break;
}
}
Другое решение состоит в том, чтобы выделить второй цикл в функции:
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;
}
}
}
Вероятно, самый простой способ - использовать переменную flag
for(i=0; i<10 && (done==false); i++)
for(j=0;j< 10; j++){
..
..
if(...){done=true; break;}
}
Изменить счетчик верхней петли до перерыва
for(i=0; i<10 ; i++)
for(j=0;j< 10; j++){
..
..
i = 10;
break;
}
Оператор break выходит из внутреннего цикла. Для выхода из внешнего цикла потребуется дополнительный оператор test и break.
Если разрыв выполняется из набора вложенных циклов, прерывается только самый внутренний цикл, в котором выполняется разрыв. (Так же, как стандартный C)
Точно так же, как последние, как правило, так:
for(i=0;i<a;i++){
for(j=0;j<a;j++){
if(Something_goes_wrong){
i=a;
break;
}
}
}
Просто ради ухмылки, как насчет того, чтобы изменить эту проверку на метод и использовать return
заявления:
- (bool) checkTrueFalse: parameters{
for ( ...) {
for ( ... ) {
if (...) {
return true;
}
}
}
return false;
}