java for-loop while-loop break continue

java - ¿Cómo funciona?



for-loop while-loop (9)

i se incrementa cuando se verifica la condición de la próxima vez.

Si continue o break el ciclo, la condición no se volverá a verificar y nunca aumentará el valor de i .

para

LABEL1 : for(;i < 3; i++){ if (true) continue; }

cuando continúas estás nuevamente comprobando si el valor de i es menor que 3 en ese momento antes de verificar que el compilador de condiciones internamente incrementa el valor de i .

aquí

LABEL2 : for(;j <3;j++){ LABEL1 : for(;i < 3; i++){ if (true) continue LABEL2; } }

Cuando ejecuta la condición de continue para Label1 nunca se vuelve a verificar, y se dirige directamente a la declaración con Label2 para que nunca se incremente.

Lo mismo es con el descanso

LABEL1 : for(;i < 3; i++){ if (true) break; }

si ejecuta el valor de código anterior de i , será 0 y no 1 .

Estoy tratando de entender cómo funciona "continuar". Entendí el concepto de la palabra clave, pero cuando ejecuto diferentes programas, funciona de manera diferente: - / Déjame mostrarte algunos ejemplos:

Si ejecuto este programa:

int j = 0; int i = 0; LABEL1: for (; i < 3; i++) { if (true) continue; }

El valor de i va a ser 3. hasta ahora todo bien. Agreguemos un bucle externo:

int j = 0; int i = 0; LABEL2: for (; j < 3; j++) { LABEL1: for (; i < 3; i++) { if (true) continue LABEL2; } }

El valor de i va a ser ... 0 !! No entiendo por qué i no se incrementa si continue se usa con una etiqueta que va al bucle externo. ¿Alguien puede explicarlo por qué? ¿Tienes algunas cosas complicadas como esas con un descanso? o con un do {} mientras?

Realmente aprecio cualquier ayuda que pueda brindar.


Continuar simplemente hace lo que su nombre sugiere, inmediatamente continúa con la siguiente ejecución del ciclo sin ejecutar el resto del código en el ciclo.

Entonces, si tienes un ciclo como este:

int j=0; int i = 0; LABEL1 : for(;i < 3; i++){ if (true) { continue; } someOtherMethod(); }

La parte someOtherMethod nunca se ejecuta porque siempre presionarás continuar.

La razón por la que su contador nunca se incrementa tiene que ver con las etiquetas, puede marcar un bucle con una etiqueta (en su caso LABEL1 y LABEL2 y usar esa etiqueta para continuar uno de los bucles externos de su bucle interno.

Entonces, con su código, el ciclo de LABEL1 nunca tiene la posibilidad de incrementar su contador y, por lo tanto, i siendo 0 porque su instrucción continua continúa inmediatamente hasta la siguiente iteración del ciclo externo.


Esto es realmente normal. El flujo de ejecución es así:

  1. j = 0
  2. i = 0
  3. ETIQUETA 2 bucle entrado,
  4. ETIQUETA 1 bucle entrado,
  5. continuar a LABEL 2
  6. j ++
  7. ETIQUETA 1 bucle entrado,
  8. continuar a LABEL 2
  9. j ++
  10. ETIQUETA 1 bucle entrado,
  11. continúe con LABEL 2 ... hasta que j == 3

La estructura de declaración básica es la siguiente:

BasicForStatement: for ( [ForInit] ; [Expression] ; [ForUpdate] ) Statement

Ahora, de JLS §14.14.1.3. Terminación abrupta de la declaración de :

Si la ejecución del Statement se completa abruptamente debido a que continue sin etiqueta , los siguientes dos pasos se realizan en secuencia:

  1. Primero, si la parte ForUpdate está presente, las expresiones se evalúan en secuencia de izquierda a derecha; sus valores, si los hay, se descartan. Si la parte ForUpdate no está presente, no se realiza ninguna acción.

  2. En segundo lugar, se realiza otro for paso de iteración.

Si la ejecución de la Declaración se completa abruptamente debido a que se continue con la etiqueta L , entonces hay una opción:

  • Si la sentencia for tiene la etiqueta L , los siguientes dos pasos se realizan en secuencia:

    1. Primero, si la parte ForUpdate está presente, las expresiones se evalúan en secuencia de izquierda a derecha; sus valores, si los hay, se descartan. Si ForUpdate no está presente, no se realiza ninguna acción.

    2. En segundo lugar, se realiza otro for paso de iteración.

  • Si la instrucción for no tiene la etiqueta L , la instrucción for completa abruptamente debido a que continúa con la etiqueta L

(énfasis mío)

ForUpdate , en tu caso, es i++ . Basado en lo que está arriba:

  • Su primer fragmento cae bajo el primer caso, por lo que se incrementa.

  • Su segundo fragmento cae bajo el segundo caso, por lo que no se incrementa porque la instrucción for completa abruptamente.

Tenga en cuenta que si hubiera continue LABEL1 en su segundo fragmento, i habría incrementado como en su primer fragmento (de acuerdo con el JLS).

Como un consejo para el futuro, para obtener respuestas definitivas con respecto a las reglas / semántica del lenguaje, siempre debe consultar la especificación del idioma. Para Java, ese es el JLS .


Si ejecuta esto en modo de depuración, verá lo que sucede. En resumen, cada vez que ingrese al bucle interno para incrementar el i , en su lugar continue con LABEL2 lugar de incrementar i y pasar a la siguiente iteración del bucle interno.

Por lo tanto, estarás en el bucle externo 3 veces y nunca golpearás el i++ en el bucle interno.

Si es más fácil, piense en el ciclo for interno como un ciclo while:

int i = 0, j = 0; LABEL2: for (; j < 3; j++) { LABEL1: while (i < 3) { if (true) { continue LABEL2; } i++; } }


Si este es el código, por ejemplo:

int main (){ // Local variable declaration: int a = 10; // do loop execution do { if( a == 15) { // skip the iteration. a = a + 1; continue; } cout << "value of a: " << a << endl; a = a + 1; }while( a < 20 ); return 0; }

Entonces el resultado será

value of a: 10 value of a: 11 value of a: 12 value of a: 13 value of a: 14 value of a: 16 value of a: 17 value of a: 18 value of a: 19

PUNTO A TENER EN CUENTA: "valor de a: 15" no está en la salida. Continuar en el lenguaje de programación salta esa línea en un bucle, si se usa "break", entonces el break acaba de salir de esa línea después de "14" (en este caso).
Para su comprensión, consulte el siguiente diagrama de flujo:


Una instrucción continue sin una etiqueta se volverá a ejecutar desde la condición más interna while o do, o loop, y desde la expresión de actualización, el bucle for interno. A menudo se usa para finalizar de forma anticipada el procesamiento de un bucle y, por lo tanto, evitar declaraciones anidadas profundamente. En el siguiente ejemplo, continue obtendrá la siguiente línea, sin procesar la siguiente instrucción en el ciclo.

while (getNext(line)) { if (line.isEmpty() || line.isComment()) continue; // More code here }

Con una etiqueta continue se ejecutará de la misma forma el loop etiquetado de forma correspondiente. Esto se puede usar para escapar bucles profundamente anidados o simplemente para mayor claridad. Si eres realmente perverso, también puedes usarlo para simular una forma limitada de goto . En el siguiente ejemplo, continue repetirá el ciclo for (;;) .

aLoopName: for (;;) { // ... while (someCondition) // ... if (otherCondition) continue aLoopName;

Algunas veces, continue también se usa como marcador de posición para hacer que un cuerpo de bucle vacío sea más claro.

for (count = 0; foo.moreData(); count++) continue;

La misma instrucción sin una label también existe en C y C ++. En Perl se nombra next .

source


i aumentaría al final del ciclo interno. Pero continue LABEL2 salta del bucle interno, al final del bucle externo, por lo que no aumenta; en cambio, solo j se incrementa hasta que la condición del bucle externo ya no se cumple.

Quizás se vuelve más claro cuando reescribimos el código con while loops:

int j=0; int i = 0; while (j<3) { while(i<3) { if (true) goto END_OF_LOOP2; END_OF_LOOP1: i++; } END_OF_LOOP2: j++; }


continue LABEL2;

hace que solo el bucle fuera aumenta. si usted tiene

LABEL2 : for(;j <3;j++){ LABEL1 : for(;i < 3; i++){ if (true) continue LABEL1; } }

aumentaré