2009-11-24 11 views

Respuesta

28

Su ejemplo saldrá del bucle más interno solamente. Sin embargo, el uso de una declaración labeled break, usted puede hacer esto:

outer: 
    for(..) 
    for(..) 
     for(..){ 
     break outer; //this will break out from all three loops 
     } 
+6

no me gustan las etiquetas :( – ufukgun

+4

@ufukgun: esta es la única forma en que puedes salir de todos los bucles, te guste o no :) –

+1

@Raskesh puedes regresar de una función o lanzar una excepción para salir de un bucle . – TimW

3

Desde el bucle más interno :)

int i,j,k; 
    for(i = 0; i < 2; i++) 
      for(j = 0; j < 2; j++) 
        for(k = 0; k < 2; k++) 
        { 
          printf("%d %d %d\n", i, j, k); 
          break; 
        } 

va a producir:

0 0 0 
0 1 0 
1 0 0 
1 1 0 
11

Esto sólo se romperá a cabo desde el bucle interno. También puede definir un alcance desde el que partir. Más de la language specs:

Una declaración de ruptura con ninguna etiqueta intentos de transferir el control a la más interior interruptor que encierra, mientras que, hacer, o para la declaración del bloque de método o inicializador inmediatamente encierra; esta declaración, que se llama el objetivo de ruptura , luego inmediatamente se completa normalmente.

+1

+1 para buscar la documentación. – Heinzi

-2

se breake de la mayor parte de bucle interno,

si quiere romper con todo, puede mantener una variable y cambiar su valor cuando se quiere romper, entonces el control al comienzo de cada uno para bucle

+1

variables de gestión, aunque a muchos parece no gustarles las etiquetas, es mucho más complicado y muestra un malentendido general de las construcciones disponibles – pstanton

7

Piense un poco acerca de estas preguntas, puede que de esta manera usted aprenderá más de solos de conseguir la respuesta (que ya ha sido escritos por ahora, estoy seguro):

  • si fueras solo, ¿cómo decidirías? Invente un caso de prueba donde se haga evidente.
  • si inventara un lenguaje y agregara un constructo de ruptura, ¿cómo funcionaría? ¿Cuál sería el comportamiento más útil? ¿Cuál sería el que más esperaba la gente?
  • ¿cómo resolverías la ruptura de los bucles anidados en Java? En C o C++? En un idioma sin etiquetas de ningún tipo?

Se sorprenderá de lo mucho que puede aprender de estos simples ejercicios hechos a sí mismo.

+0

+1. ¡Más pensamiento, menos molestando a otras personas en internet! – Bombe

+0

+1: más de ambos. :-) –

3

Sí, sin etiquetas romperá solo el bucle más interno.
En lugar de utilizar etiquetas, puede colocar sus bucles en una función separada y regresar de la función.

class Loop { 
    public void loopForXx() { 
     untilXx(); 
    } 

    private void untilXx() { 
     for() 
      for() 
       for() 
        if(xx) 
         return; 
    } 
} 
+1

Sí, por favor, ¡sin pausas ni etiquetas! –

0

A muchas personas aquí no les gustan las etiquetas y las roturas. Esta técnica se puede comparar con el uso de una declaración 'goto', una declaración de control de flujo que permite saltar fuera de un bloque de código de una manera no estándar, eliminando el uso de las condiciones previas y posteriores. Edsger Dijkstra publicó un artículo famoso en Communications of the ACM, marzo de 1968, "Declaración de Goto considerada dañina" (es una lectura breve).

Usando el mismo razonamiento presentado en el artículo, regresar desde dentro de una iteración como lo sugiere TimW también es una mala práctica. Si uno es estricto, para crear código legible, con puntos predecibles de entrada y salida, uno debe inicializar la variable que contendrá el valor de retorno (si existe) al principio del método y devolver solo al final de un método.

Esto plantea un desafío cuando se usa una iteración para realizar una búsqueda. Para evitar el uso de descanso o devolver uno, inevitablemente, termina con un tiempo de ciclo con una condición de parada regular y alguna variable booleana para indicar que la búsqueda ha tenido éxito:

boolean targetFound = false; 
int i = 0; 
while (i < values.size() && ! targetFound) { 

    if (values.get(i).equals(targetValue)) { 
     targetFound = true; 
    } 
} 
if (!targetFound) { 
    // handle lookup failure 
} 

Ok, esto funciona, pero parece un poco torpe a mi. En primer lugar, tengo que introducir un valor booleano para detectar el éxito de la búsqueda. En segundo lugar, tengo que comprobar explícitamente targetFound después del bucle para manejar el error de búsqueda.

veces uso esta solución, que creo que es más concisa y fácil de leer:

lookup: { 

    for(Value value : values) { 

     if (value.equals(targetValue)) { 
      break lookup; 
     } 
    } 
    // handle lookup failure here 
} 

Creo que romper (sin doble sentido) de la regla aquí se traduce en un mejor código.

+0

¿Podría editar el primer ejemplo para que ambas soluciones usen el ciclo for mejorado? Esto ayudaría a comparar, qué solución es más fácil de entender (legibilidad). Ahora es una competencia desleal. –

+0

No, no puedo. Esa es una especie de mi punto. Sin sentencias break o return (o llamadas System.exit() etc.) siempre se completa un for-loop y estoy asumiendo que nadie aceptaría la sobrecarga de dejar que la iteración se complete después de que se haya encontrado el resultado. De modo que o bien trabaja alrededor de las pausas y retorna usando un ciclo while y una variable adicional, o acepta usar una sentencia break en combinación con un for-loop y obtiene un código mucho más conciso. –

1

como he mencionado a menudo no me gusta romper con una etiqueta eather. Así, mientras que en un bucle mayor parte del tiempo estoy añadiendo una varible booleano para salir del bucle sencillo .. (sólo si quiero romperlo de causa;))

boolean exit = false; 
for (int i = 0; i < 10 && !exit; i++) { 
    for (int j = 0; j < 10 && !exit; j++) { 
     exit = true; 
    } 
} 

esto es, en mi opinión más elegante que un descanso ...