Estoy escribiendo un código que se parece a esto:
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
break; // **HERE, I want to break out of the loop itself**
}
}
¿Hay alguna forma directa de hacerlo?
Sé que puedo usar una bandera y romper el ciclo poniendo un salto condicional justo después del cambio. Solo quiero saber si C ++ ya tiene alguna construcción para esto.
goto
atractiva y, a veces, la única salida limpia. Si tiende a organizar su código en pequeñas funciones que tienen solo unas pocas líneas y hacen una sola cosa cada una, nunca se encontrará con este problema. (Por cierto, su código también será más fácil de leer.):)
Respuestas:
Premisa
El siguiente código debe considerarse de mala forma, independientemente del idioma o la funcionalidad deseada:
Argumentos de apoyo
El
while( true )
bucle es de mala forma porque:while(true)
bucles for que no son infinitos, perdemos la capacidad de comunicarnos de manera concisa cuando los bucles en realidad no tienen una condición de terminación. (Podría decirse que esto ya sucedió, por lo que el punto es discutible).Alternativa a "Ir a"
El siguiente código es una mejor forma:
Ventajas
Sin bandera. No se
goto
. Sin excepción. Fácil de cambiar. Fácil de leer. Fácil de arreglar. Además el código:El segundo punto es importante. Sin saber cómo funciona el código, si alguien me pide que haga que el bucle principal deje que otros subprocesos (o procesos) tengan algo de tiempo de CPU, se me ocurren dos soluciones:
Opción 1
Inserte fácilmente la pausa:
Opcion 2
Anular ejecutar:
Este código es más simple (por lo tanto, más fácil de leer) que un bucle con un archivo
switch
. ElisValidState
método solo debe determinar si el ciclo debe continuar. El caballo de batalla del método debe abstraerse en elexecute
método, lo que permite que las subclases anulen el comportamiento predeterminado (una tarea difícil con unswitch
y incorporadogoto
).Ejemplo de Python
Compare la siguiente respuesta (a una pregunta de Python) que se publicó en StackOverflow:
Versus:
Aquí,
while True
resulta en un código engañoso y demasiado complejo.fuente
while(true)
debería ser dañina me parece extraña. Hay bucles que se comprueban antes de ejecutarse, hay los que se comprueban después y hay los que se comprueban en el medio. Dado que este último no tiene una construcción sintáctica en C y C ++, tendrá que usarwhile(true)
ofor(;;)
. Si considera que esto es incorrecto, todavía no ha pensado lo suficiente en los diferentes tipos de bucles.while(true) {string line; std::getline(is,line); if(!is) break; lines.push_back(line);}
supuesto, podría transformar esto en un bucle preacondicionado (usandostd::getline
como condición de bucle), pero esto tiene desventajas por sí solo (line
tendría que ser una variable fuera del alcance del bucle). Y si lo hiciera, tendría que preguntar: ¿Por qué tenemos tres bucles de todos modos? Siempre podríamos transformar todo en un bucle preacondicionado. Utilice lo que mejor se adapte. Siwhile(true)
encaja, úselo.Puede utilizar
goto
.fuente
goto
. El OP se menciona claramente sin usar banderas . ¿Puede sugerir una mejor manera, considerando la limitación del OP? :)Una solución alternativa es usar la palabra clave
continue
en combinación conbreak
, es decir:Use la
continue
declaración para terminar cada etiqueta de caso donde desea que continúe el ciclo y use labreak
declaración para terminar las etiquetas de caso que deberían terminar el ciclo.Por supuesto, esta solución solo funciona si no hay código adicional para ejecutar después de la instrucción de cambio.
fuente
:(
:(
De lo contrario, una implementación muy limpia.Una forma ordenada de hacer esto sería poner esto en una función:
Opcionalmente (pero 'malas prácticas'): como ya se sugirió, podría usar un goto o lanzar una excepción dentro del interruptor.
fuente
AFAIK no hay "doble ruptura" o construcción similar en C ++. El más cercano sería un
goto
, que, si bien tiene una mala connotación en su nombre, existe en el idioma por una razón, siempre que se use con cuidado y con moderación, es una opción viable.fuente
Podría poner su interruptor en una función separada como esta:
fuente
Incluso si no le gusta goto, no use una excepción para salir de un bucle. El siguiente ejemplo muestra lo feo que podría ser:
Usaría
goto
como en esta respuesta. En este casogoto
, el código será más claro que cualquier otra opción. Espero que esta pregunta sea de ayuda.Pero creo que usar
goto
es la única opción aquí debido a la cadenawhile(true)
. Debería considerar la refactorización de su bucle. Supongo la siguiente solución:O incluso lo siguiente:
fuente
goto
, no use una excepción para salir de un bucle:"?No hay una construcción de C ++ para salir del ciclo en este caso.
Use una bandera para interrumpir el ciclo o (si corresponde) extraiga su código en una función y use
return
.fuente
Potencialmente, podría usar goto, pero preferiría establecer una bandera que detenga el bucle. Luego salga del interruptor.
fuente
¿Por qué no arreglar la condición en su bucle while, haciendo que el problema desaparezca?
fuente
No, C ++ no tiene una construcción para esto, dado que la palabra clave "break" ya está reservada para salir del bloque de interruptores. Alternativamente, un do.. while () con una bandera de salida podría ser suficiente.
fuente
Yo creo que;
fuente
La forma más sencilla de hacerlo es poner un IF simple antes de hacer el SWITCH, y que IF pruebe su condición para salir del bucle ... tan simple como puede ser
fuente
La
break
palabra clave en C ++ solo termina la iteración oswitch
declaración adjunta más anidada . Por lo tanto, no podría salir delwhile (true)
bucle directamente dentro de laswitch
declaración; sin embargo, podría usar el siguiente código, que creo que es un patrón excelente para este tipo de problema:Si necesita hacer algo cuando
msg->state
es igualDONE
(como ejecutar una rutina de limpieza), coloque ese código inmediatamente después delfor
ciclo; es decir, si actualmente tiene:Luego usa en su lugar:
fuente
Me sorprende lo simple que es esto considerando la profundidad de las explicaciones ... Aquí está todo lo que necesita ...
LOL !! ¡De Verdad! ¡Eso es todo lo que necesitas! ¡Una variable extra!
fuente
fuente
Tengo el mismo problema y lo resolví usando una bandera.
fuente
Si recuerdo bien la sintaxis de C ++, puede agregar una etiqueta a las
break
declaraciones, como paragoto
. Entonces, lo que desea se escribiría fácilmente:fuente
fuente