¿Cómo puedo salir de dos bucles for anidados en Objective-C?

4 minutos de lectura

avatar de usuario
Gracias

Tengo dos bucles for anidados así:

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

    }
}

Sé que hay un break declaración. Pero estoy confundido acerca de si rompe ambos bucles o solo uno en el que se llamó. Necesito romper ambos tan pronto como vea que no tiene sentido iterar más veces.

avatar de usuario
Ori Pesaj

Si usar goto simplifica el código, entonces sería apropiado.

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

  • Para ampliar esto, for (;;) {for (;;) {break; /* breaks inner loop */} for (;;) {goto outer; /* breaks outer loop */}} outer:;

    – efímero

    14 de mayo de 2009 a las 13:46

  • (;;) parece una carita.

    – zakdanzas

    28 de marzo de 2013 a las 19:14

avatar de usuario
jbasko

break sale de un bucle, pero puede agregar una verificación al bucle exterior que se rompe cuando se rompe el interior.

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

  • En mi humilde opinión, usar goto es mucho más limpio.

    – jugo de sig

    14 mayo 2009 a las 19:03

  • !dobreak está en el lugar equivocado; debería ir en el condicional (la segunda parte de for) en lugar del paso incremental (la tercera parte de for); yo también usaría !dobreak && .., por lo que no es necesario evaluar las otras condiciones al romper. Estoy de acuerdo con sigjuice: goto no es malo cuando se usa apropiadamente, y este es un caso donde goto lo hace hacer un mejor código.

    – efímero

    15 de mayo de 2009 a las 16:45

  • Esto aún ejecutaría código posible en el ciclo externo que vendría después del ciclo interno

    – Martijn

    1 de septiembre de 2010 a las 20:04

  • @Martijn: esto se puede solucionar reemplazando el break con un continue declaración. Aún así, son solo más cosas no obvias de las que preocuparse.

    – Ori Pesach

    25/10/2011 a las 17:54


los break La declaración solo lo saca del bucle más interno. Si no desea la sobrecarga adicional en el código, la memoria y el rendimiento de una variable de estado dedicada, le recomiendo refactorizar el código en una función o método propio y usar return para salir de todos los bucles:

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. */
    }
  }
}

  • Me sorprendería mucho si una llamada de función en un bucle lograra funcionar tan bien como una variable de estado dedicada, especialmente si necesita pasar argumentos para tener acceso a las variables en la función externa. Tal vez si el compilador copia la función en línea…

    – efímero

    14 mayo 2009 a las 17:36

  • Lo que es peor, en mi opinión, es la pérdida de la capacidad de comprender el algoritmo al leerlo en un solo lugar. ¿Todo esto para evitar un goto?

    – Ori Pesach

    15 de mayo de 2009 a las 14:35

  • También me he encontrado con este problema de interrupción/continuación, a veces queriendo continuar el ciclo 2-3 niveles hacia arriba. Lo mejor que puede hacer en mi humilde opinión es refactorizar los bucles anidados en un método para que ese método pueda devolver si continúa con el bucle principal.

    – Jasón

    2 de febrero de 2010 a las 20:33

  • ¿Qué pasa si el usuario quiere salir solo del ciclo y no de la función?

    – Akshay J.

    29 de junio de 2011 a las 16:38

  • Esta es la mejor solución, en mi opinión. No es ambiguo lo que sucede, es fácil de controlar, es fácil de llamar, no asigna ni evalúa un booleano innecesario, y no utiliza prácticas antiguas peligrosas como goto. Las preocupaciones de rendimiento tampoco deberían ser notables en cualquier uso del mundo real.

    – Ky.

    27 de noviembre de 2017 a las 21:24

avatar de usuario
lothar

Además de la variable de bandera ya mencionada o goto, podría lanzar una excepción de Objective-C:

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

avatar de usuario
Jorge Armhold

Otros han mencionado cómo puede establecer una bandera o usar un goto, pero recomendaría refactorizar su código para que el ciclo interno se convierta en un método separado. Ese método puede devolver alguna bandera para indicar que el ciclo externo debería break. Si nombra sus métodos apropiadamente, esto es mucho más legible.

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

Pseudocódigo, no probado, pero entiendes la idea.

avatar de usuario
nick allen

La instrucción break solo saldrá del bucle en el ámbito, que es el bucle principal. Si también desea salir del segundo bucle, puede usar una variable booleana que esté dentro del alcance de ambos bucles.

bool isTerminated = false;

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

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

avatar de usuario
oxigeno

Cambiar el contador del bucle superior antes del descanso

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

  • No me gusta esto demasiado. El riesgo es que alguien cambie la condición de salida en un lugar y olvide el otro.

    – Johan Kotlinsky

    14 de mayo de 2009 a las 13:18

  • NSUInteger limit = 10; Luego: for(i=0; i<limit; i++) { for(j=0; j<10; j++) { .. .. i = limit; break; } }

    – Matt Mc

    15/10/2012 a las 20:02

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad