¿Es posible usar la breakfunción para salir de varios forbucles anidados ?
Si es así, ¿cómo harías para hacer esto? ¿Puedes controlar también cuántos bucles breaksalen?
¿Es posible usar la breakfunción para salir de varios forbucles anidados ?
Si es así, ¿cómo harías para hacer esto? ¿Puedes controlar también cuántos bucles breaksalen?
Respuestas:
AFAIK, C ++ no admite bucles de nombres, como lo hacen Java y otros lenguajes. Puede usar un goto o crear un valor de marca que use. Al final de cada ciclo, verifique el valor del indicador. Si se establece en verdadero, puede salir de esa iteración.
gotosi esa es la mejor opción.
goto: programadores malos y programadores pragmáticos. Los primeros se explican por sí mismos. Este último, en el que encajaría si elige usarlos bien, utiliza un concepto llamado "malvado" cuando es el menor de (dos) males. Lea esto para comprender mejor algunos conceptos de C ++ que puede necesitar usar de vez en cuando (macros, goto's, preprocesador, matrices): parashift.com/c++-faq-lite/big-picture.html#faq-6.15
gotoraramente es la mejor opción. ¿Por qué no poner los bucles en su propia función ( inlinesi te preocupa la velocidad) y returnde esto?
No, no lo estropees con un break. Este es el último bastión restante para el uso de goto.
Solo para agregar una respuesta explícita usando lambdas:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
Por supuesto, este patrón tiene ciertas limitaciones y obviamente solo C ++ 11, pero creo que es bastante útil.
Otro enfoque para salir de un bucle anidado es factorizar ambos bucles en una función separada, y returndesde esa función cuando desee salir.
Por supuesto, esto trae a colación el otro argumento de si alguna vez debería explícitamente returndesde una función en cualquier lugar que no sea al final.
continue_processing) que controlaban la ejecución de bloques de código más abajo en la función.
break saldrá solo del bucle más interno que lo contiene.
Puede usar goto para salir de cualquier número de bucles.
Por supuesto, ir a menudo se considera perjudicial .
¿Es apropiado usar la función de interrupción [...]?
Usar break y goto puede hacer que sea más difícil razonar sobre la corrección de un programa. Vea aquí para una discusión sobre esto: Dijkstra no estaba loco .
breako return.
breaky returntiene la ventaja de gotoque no necesita buscar una etiqueta para saber a dónde van. Sí, debajo hay algún tipo de goto, pero muy restringido. Son mucho más fáciles de descifrar por el cerebro de coincidencia de patrones de un programador que los no restringidos goto. Por lo tanto, son preferibles.
goto.
Aunque esta respuesta ya se presentó, creo que un buen enfoque es hacer lo siguiente:
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
gotoMainLoopse verifica cada ciclo
gotohace que el núcleo sea más legible y tenga un mejor rendimiento.
¿Qué tal esto?
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
Un ejemplo de código con gotouna etiqueta para salir de un bucle anidado:
for (;;)
for (;;)
goto theEnd;
theEnd:
Una buena manera de salir de varios bucles anidados es refactorizar su código en una función:
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
Goto puede ser muy útil para romper bucles anidados
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
Creo que un goto es válido en esta circunstancia:
Para simular un break/continue , querrías:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
i. Por lo tanto, i++antes del goto
Otros lenguajes, como PHP, aceptan un parámetro para la interrupción (es decir, la interrupción 2;) para especificar la cantidad de niveles de bucle anidados de los que desea salir, pero C ++ no lo hace. Tendrá que resolverlo usando un booleano que establezca en falso antes del ciclo, establezca en verdadero en el ciclo si desea romper, más un corte condicional después del ciclo anidado, verificando si el booleano se estableció en verdadero y romper si es así.
Sé que esta es una publicación antigua. Pero sugeriría una respuesta un poco lógica y más simple.
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
j = conditionjque no funcionará si tiene un predicado complejo en lugar de j < conditionj.
Divida cualquier número de bucles por una sola boolvariable, vea a continuación:
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
En este código tenemos break;todos los bucles.
No estoy seguro de si vale la pena, pero puede emular los bucles con nombre de Java con algunas macros simples:
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
Ejemplo de uso:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
Otro ejemplo:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
Puedes usar try ... catch.
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
Si tiene que salir de varios bucles a la vez, a menudo es una excepción.
Romper un bucle for es un poco extraño para mí, ya que la semántica de un bucle for generalmente indica que se ejecutará un número específico de veces. Sin embargo, no es malo en todos los casos; si está buscando algo en una colección y quiere romperlo después de encontrarlo, es útil. Sin embargo, la ruptura de bucles anidados no es posible en C ++; es en otros idiomas mediante el uso de un descanso etiquetado. Puede usar una etiqueta y un goto, pero eso podría provocarle acidez estomacal por la noche ... Sin embargo, parece la mejor opción.