rompiendo romper rompe quien piñatas piñata original niña juego fiesta feliz cumpleaños con como canta c for-loop break

c - romper - rompe la piñata video original



¿Cuál es una forma ordenada de romper muchos bucles a la vez? (14)

Supongamos que necesito separarme de tres o cuatro anidados para bucles a la vez al ocurrir algún evento dentro del bucle más interno. ¿Cuál es una forma limpia de hacer eso?

Lo que hago es usar banderas como esta:

int i, j, k; int flag1 = 0; int flag2 = 0; for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { for (k = 0; k < 100; k++) { if (k == 50) { flag1 = 1; flag2 = 1; break; } } if (flag1 == 1)break; } if (flag2 == 1)break; }

No creo que esto sea particularmente limpio.

¿Cómo lograrías lo mismo? (sin usar saltos)


¿Cómo lograrías lo mismo? (sin usar saltos)

¿Por qué? Nada es universalmente malo, y cada herramienta de aplicación tiene sus usos (excepto gets() ). Usar goto aquí hace que su código se vea más limpio, y es una de las únicas opciones que tenemos (asumiendo que C). Mira:

int i, j, k; for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { for (k = 0; k < 100; k++) { if (k == 50) { goto END; } } } } END:

Mucho más limpio que todas esas variables de bandera, e incluso muestra más claramente lo que está haciendo su código.


A veces puedes usar truco como este:

for (i = 0; i < 100 && !flag2; i++) { for (j = 0; j < 100 && !flag1; j++) { for (k = 0; k < 100; k++) { if (k == 50) { k = 100; i = 100; j = 100; } } }

}

o declarar bandera de adición en su bucle:

bool end = false; for(int i =0; i < 1000 && !end; i++) { //do thing end = true; }

Sólo cuesta una línea pero limpia, creo.

justin


Dividir por 0 es el método más seguro que conozco que lo sacará de cualquier número de bucles. Esto funciona porque a la instrucción de montaje DIV no le gustan estas tonterías.

Entonces, puedes probar esto:

int i, j, k; int flag1 = 0; int flag2 = 0; for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { for (k = 0; k < 100; k++) { if (k == 50) { flag1 = 1; flag2 = 1; int z = 1 / 0; // we''re outta here!!! } } if (flag1 == 1)break; } if (flag2 == 1)break; }

Volviendo de la trap que sucede en tales eventos, queda como un ejercicio para el lector (es trivial).


Haría algo como:

int i, j, k; for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { for (k = 0; k < 100; k++) { if (k == 50) { return; } } } }


Ponga todos los bucles en una función y simplemente regrese en lugar de romper.


Sólo un poquito mejor.

int i, j, k; int flag1 = 0; int flag2 = 0; for (i = 0; i < 100 && !flag2; i++) { for (j = 0; j < 100 && !flag1; j++) { for (k = 0; k < 100; k++) { if (k == 50) { flag1 = 1; flag2 = 1; break; } } } }

Pero si realmente necesita tener esos bucles, entonces tiene sentido declarar explícitamente en cada bucle las condiciones que deben cumplirse para que continúe, para facilitar la lectura.


Si está utilizando GCC y esta biblioteca , la break puede aceptar el número de bucles anidados que desea salir:

int i, j, k; for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { for (k = 0; k < 100; k++) { if (k == 50) { break(3); } } } }


Si está utilizando Java, puede asociar etiquetas con cada bloque y luego hacer referencia a la etiqueta después de una declaración de continuación. Por ejemplo:

outerfor: for (int i=0; i<5; i++) { innerfor: for (int j=0; j<5; j++) { if (i == 1 && j == 2) { continue outerfor; } } }


Si la finalización prematura de cualquier ciclo siempre significa que también tiene que romper el ciclo de cierre, no necesita ningún indicador adicional. Todo el asunto podría verse como sigue

int i, j, k; for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { for (k = 0; k < 100; k++) { if (k == 50) break; } if (k < 100) break; } if (j < 100) break; }

En mi experiencia, esto es lo que se necesita en la mayoría de los casos.


Si no quieres usar goto, configura todas las condiciones del bucle como falsas:

int i, j, k; for (i = 0; i < 100; i++) { for (j = 0; j < 100; j++) { for (k = 0; k < 100; k++) { if (k == 50) { i = j = k = INT_MAX; break; } } } }

nota: un compilador de optimización inteligente cambiará el contenido de si en un salto al final del bucle más exterior


Una forma de hacerlo es una máquina de estados. Pero todavía usaría goto. Es mucho más simple. :)

state = 0; while( state >= 0){ switch(state){ case 0: i = 0; state = 1; // for i = 0 case 1: i++; if (i < 100) // if for i < 100 not finished state = 2; // do the inner j loop else state = -1; // finish loop case 2: j = 0; state = 3; // for j = 0 case 3: j++; if (j < 100) // if j < 100 not finished state = 4 // do the inner k loop else state = 1; // go backt to loop i break; case 4: k = 0; state = 5; case 5: k++; if (k == 50){ state = -1; break; } if (k < 100) // if k loop not finished state = 5; // do this loop else state = 3; // go back to upper loop break; default : state = -1; } }


un poco de auto-documentación tonta:

int i, j, k; int done = 0; for (i = 0; i < 100 && ! done; i++) { for (j = 0; j < 100 && ! done; j++) { for (k = 0; k < 100 && ! done; k++) { if (k == 50) we_are(done); } } } //... void we_are(int *done) { *done = 1; }

Pero en realidad, no deberías tener tres bucles forados anidados. Debería considerar refactorizar en diferentes funciones y mejorar la lógica de su programa en lugar de hacerlo.

Si bien estoy de acuerdo en que a veces goto es realmente la mejor solución, creo que cualquier problema para el que goto es la solución es el resultado de un código deficiente.


utilizar goto. Es limpio y simple.


goto Este es uno de los pocos lugares donde goto es la herramienta adecuada, y generalmente es el argumento que se presenta por qué goto no es un completo mal.

A veces, sin embargo, hago esto:

void foo() { bar_t *b = make_bar(); foo_helper(bar); free_bar(b); } void foo_helper(bar_t *b) { int i,j; for (i=0; i < imax; i++) { for (j=0; j < jmax; j++) { if (uhoh(i, j) { return; } } } }

La idea es que obtengo una barra libre garantizada, y además obtengo una interrupción limpia del conmutador de dos niveles a través del retorno.