J’écris du code qui ressemble à ceci:
while(true) { switch(msg->state) { case MSGTYPE: // ... break; // ... more stuff ... case DONE: break; // **HERE, I want to break out of the loop itself** } }
Y a-t-il un moyen direct de le faire?
Je sais que je peux utiliser un drapeau et quitter la boucle en mettant une pause conditionnelle juste après le changement. Je veux juste savoir si C ++ a déjà une construction pour cela.
Le code suivant doit être considéré comme une forme incorrecte, indépendamment de la langue ou de la fonctionnalité souhaitée:
while( true ) { }
La boucle while( true )
est de mauvaise forme car elle:
Le code suivant est mieux formé:
while( isValidState() ) { execute(); } bool isValidState() { return msg->state != DONE; }
Pas de drapeau Pas de goto
. Pas exception. Facile à changer Facile à lire. Facile à réparer De plus le code:
Le deuxième point est important. Sans savoir comment le code fonctionne, si quelqu’un m’a demandé de faire la boucle principale, laissez les autres threads (ou processus) gagner du temps CPU, deux solutions me viennent à l’esprit:
Insérez la pause facilement:
while( isValidState() ) { execute(); sleep(); }
Remplacer exécuter:
void execute() { super->execute(); sleep(); }
Ce code est plus simple (donc plus facile à lire) qu’une boucle avec un switch
incorporé. La méthode isValidState
doit uniquement déterminer si la boucle doit continuer. Le workhorse de la méthode doit être résumé dans la méthode execute
, ce qui permet aux sous-classes de remplacer le comportement par défaut (une tâche difficile en utilisant un switch
et un goto
incorporés).
Comparez la réponse suivante (à une question Python) qui a été publiée sur StackOverflow:
Code
while True: choice = raw_input('What do you want? ') if choice == 'restart': continue else: break print 'Break!'
Contre:
Code
choice = 'restart'; while choice == 'restart': choice = raw_input('What do you want? ') print 'Break!'
Ici, while True
traduit par un code trompeur et trop complexe.
Vous pouvez utiliser goto
.
while ( ... ) { switch( ... ) { case ...: goto exit_loop; } } exit_loop: ;
Une autre solution consiste à utiliser le mot-clé continue
en combinaison avec break
, à savoir:
for (;;) { switch(msg->state) { case MSGTYPE // code continue; // continue with loop case DONE: break; } break; }
Utilisez l’instruction continue
pour terminer chaque étiquette de cas où vous souhaitez que la boucle continue et utilisez l’instruction break
pour terminer les étiquettes de cas qui doivent terminer la boucle.
Bien entendu, cette solution ne fonctionne que s’il n’ya pas de code supplémentaire à exécuter après l’instruction switch.
Une manière intéressante de le faire serait de mettre cela dans une fonction:
int yourfunc() { while(true) { switch(msg->state) { case MSGTYPE: // ... break; // ... more stuff ... case DONE: return; } } }
Facultativement (mais «mauvaises pratiques»): comme déjà suggéré, vous pouvez utiliser un goto ou lancer une exception dans le commutateur.
AFAIK il n’y a pas de “double break” ou de construction similaire en C ++. Le plus proche serait un goto
– qui, bien qu’il ait une mauvaise connotation à son nom, existe dans la langue pour une raison – dans la mesure où il est utilisé avec prudence et parcimonie, c’est une option viable.
Vous pouvez mettre votre commutateur dans une fonction distincte comme ceci:
bool myswitchfunction() { switch(msg->state) { case MSGTYPE: // ... break; // ... more stuff ... case DONE: return false; // **HERE, I want to break out of the loop itself** } return true; } while(myswitchfunction()) ;
Même si vous n’aimez pas goto, n’utilisez pas une exception pour quitter une boucle. L’exemple suivant montre à quel point il peut être moche:
try { while ( ... ) { switch( ... ) { case ...: throw 777; // I'm afraid of goto } } } catch ( int ) { }
Je voudrais utiliser goto
comme dans cette réponse. Dans ce cas, goto
rendra le code plus clair que toute autre option. J’espère que cette question sera utile.
Mais je pense que l’utilisation de goto
est la seule option à cause de la chaîne while(true)
. Vous devriez envisager de refactoriser votre boucle. Je suppose que la solution suivante:
bool end_loop = false; while ( !end_loop ) { switch( msg->state ) { case MSGTYPE: // ... break; // ... more stuff ... case DONE: end_loop = true; break; } }
Ou même les suivants:
while ( msg->state != DONE ) { switch( msg->state ) { case MSGTYPE: // ... break; // ... more stuff ... }
Il n’y a pas de construction C ++ pour sortir de la boucle dans ce cas.
Utilisez un indicateur pour interrompre la boucle ou (le cas échéant) extrayez votre code dans une fonction et utilisez return
.
Vous pourriez potentiellement utiliser goto, mais je préférerais définir un drapeau qui arrête la boucle. Ensuite, sortez de l’interrupteur.
Pourquoi ne pas simplement corriger la condition dans votre boucle while, provoquant la disparition du problème?
while(msg->state != DONE) { switch(msg->state) { case MSGTYPE: // ... break; // ... more stuff ... case DONE: // We can't get here, but for completeness we list it. break; // **HERE, I want to break out of the loop itself** } }
Je pense;
while(msg->state != mExit) { switch(msg->state) { case MSGTYPE: // ... break; case DONE: // .. // .. msg->state =mExit; break; } } if (msg->state ==mExit) msg->state =DONE;
Non, C ++ n’a pas de construction pour cela, étant donné que le mot clé “break” est déjà réservé pour quitter le bloc de commutation. Sinon, un do..while () avec un indicateur de sortie pourrait suffire.
do { switch(option){ case 1: ..; break; ... case n: .. ;break; default: flag = false; break; } } while(flag);
La manière la plus simple de le faire est de mettre un simple IF avant de faire le SWITCH, et que le IF teste votre condition pour sortir de la boucle ………. aussi simple que cela puisse être
Le mot-clé break
en C ++ termine uniquement l’itération ou l’instruction switch
la plus nestede. Ainsi, vous ne pouviez pas sortir de la boucle while (true)
directement dans l’instruction switch
; Cependant, vous pouvez utiliser le code suivant, ce qui, à mon avis, est un excellent modèle pour ce type de problème:
for (; msg->state != DONE; msg = next_message()) { switch (msg->state) { case MSGTYPE: //... break; //... } }
Si vous deviez faire quelque chose lorsque msg->state
égal à DONE
(par exemple, exécuter une routine de nettoyage), placez ce code immédiatement après la boucle for
; c’est à dire si vous avez actuellement:
while (true) { switch (msg->state) { case MSGTYPE: //... break; //... case DONE: do_cleanup(); break; } if (msg->state == DONE) break; msg = next_message(); }
Ensuite, utilisez plutôt:
for (; msg->state != DONE; msg = next_message()) { switch (msg->state) { case MSGTYPE: //... break; //... } } assert(msg->state == DONE); do_cleanup();
Cela m’étonne à quel point c’est simple compte tenu de la profondeur des explications … Voici tout ce dont vous avez besoin …
bool imLoopin = true; while(imLoopin) { switch(msg->state) { case MSGTYPE: // ... break; // ... more stuff ... case DONE: imLoopin = false; break; } }
LOL !! Vraiment! C’est tout ce dont vous avez besoin! Une variable supplémentaire!
while(MyCondition) { switch(msg->state) { case MSGTYPE: // ... break; // ... more stuff ... case DONE: MyCondition=false; // just add this code and you will be out of loop. break; // **HERE, you want to break out of the loop itself** } }
J’ai eu le même problème et résolu en utilisant un drapeau.
bool flag = false; while(true) { switch(msg->state) { case MSGTYPE: // ... break; // ... more stuff ... case DONE: flag = true; // **HERE, I want to break out of the loop itself** } if(flag) break; }
Si je me souviens bien de la syntaxe C ++, vous pouvez append une étiquette pour break
instructions, comme pour goto
. Donc, ce que vous voulez serait facilement écrit:
while(true) { switch(msg->state) { case MSGTYPE: // ... break; // ... more stuff ... case DONE: break outofloop; // **HERE, I want to break out of the loop itself** } } outofloop: // rest of your code here
while(true) { switch(x) { case 1: { break; } break; case 2: //some code here break; default: //some code here } }