Je suis tombé sur cette question il y a une seconde, et j'en retire une partie du matériel: y a- t-il un nom pour la construction «break n»?
Cela semble être un moyen inutilement complexe pour les gens d'avoir à demander au programme de sortir d'une boucle for double-nested:
for (i = 0; i < 10; i++) {
bool broken = false;
for (j = 10; j > 0; j--) {
if (j == i) {
broken = true;
break;
}
}
if (broken)
break;
}
Je sais que les manuels aiment dire que les déclarations goto sont le diable, et je ne les aime pas du tout moi-même, mais cela justifie-t-il une exception à la règle?
Je cherche des réponses qui traitent des boucles n-imbriquées.
REMARQUE: Que vous répondiez oui, non ou quelque part entre les deux, les réponses totalement étroites ne sont pas les bienvenues. Surtout si la réponse est non, fournissez une bonne raison légitime (ce qui n'est pas trop loin de la réglementation Stack Exchange de toute façon).
la source
for (j = 10; j > 0 && !broken; j--)
vous n'aurez pas besoin de l'break;
instruction. Si vous déplacez la déclaration debroken
to avant que la boucle externe ne commence, alors si cela peut être écrit comme cela,for (i = 0; i < 10 && !broken; i++)
je pense qu'aucunbreak;
s n'est nécessaire.goto
: goto (référence C #) - "L'instruction goto est également utile pour sortir des boucles profondément imbriquées."goto
est en fait requis dans un commutateur C # pour passer à un autre cas après avoir exécuté un code à l'intérieur du premier cas. C'est le seul cas où j'ai utilisé goto, cependant.Réponses:
Le besoin apparent d'une instruction go-to vient de votre choix d'expressions conditionnelles médiocres pour les boucles .
Vous déclarez que vous vouliez que la boucle externe continue aussi longtemps
i < 10
et la boucle la plus interne se poursuive aussi longtempsj > 0
.Mais en réalité, ce n'est pas ce que vous vouliez , vous n'avez tout simplement pas dit aux boucles l'état réel que vous vouliez qu'elles évaluent, puis vous voulez le résoudre en utilisant break ou goto.
Si vous dites aux boucles vos véritables intentions pour commencer , alors pas besoin de pauses ou de goto.
la source
i
à la fin de la boucle externe, donc court-circuiter l'incrément est important pour rendre le code 100% équivalent. Je ne dis rien dans votre réponse est faux, je voulais juste souligner que rompre la boucle immédiatement était un aspect important du code.i
à la fin de la boucle externe dans la question OP.goto
(je suis sûr qu'il y en a de meilleurs), même s'il a engendré une question qui semble l'utiliser en tant que telle, mais pour illustrer l'action de base debreak(n)
dans des langues qui ne l'ont pas été. t le soutenir.Dans ce cas, vous pouvez refactoriser le code dans une routine distincte, puis uniquement à
return
partir de la boucle interne. Cela annulerait la nécessité de sortir de la boucle extérieure:la source
i
après la fin de la boucle extérieure. Donc, pour vraiment refléter cela,i
c'est la valeur importante, ici lereturn true;
etreturn false;
devrait être les deuxreturn i;
.Non, je ne pense pas qu'un
goto
soit nécessaire. Si vous l'écrivez comme ceci:Avoir
&&!broken
sur les deux boucles vous permet de sortir des deux boucles quandi==j
.Pour moi, cette approche est préférable. Les conditions de boucle sont extrêmement claires:
i<10 && !broken
.Une version de travail peut être consultée ici: http://rextester.com/KFMH48414
Code:
Production:
la source
broken
dans votre premier exemple du tout ? Utilisez simplement la pause sur la boucle intérieure. De plus, si vous devez absolument l'utiliserbroken
, pourquoi le déclarer en dehors des boucles? Déclarez-le simplement dans lai
boucle. Quant à lawhile
boucle, veuillez ne pas l'utiliser. Je pense honnêtement qu'elle parvient à être encore moins lisible que la version goto.broken
est utilisée parce que je n'aime pas utiliser l'break
instruction (sauf dans switch-case, mais c'est tout). Il est déclaré en dehors de la boucle externe au cas où vous voudriez casser TOUTES les boucles quandi==j
. Vous avez raison, en général, ilbroken
suffit de déclarer avant la boucle la plus externe qu'il se cassera.i==2
à jour, à la fin de la boucle. La condition de réussite doit également court-circuiter l'incrément s'il doit être équivalent à 100% à abreak 2
.broken = (j == i)
plutôt que le if et, si le langage le permet, de mettre la déclaration cassée à l'intérieur de l'initialisation de la boucle externe. Bien qu'il soit difficile de dire ces choses pour cet exemple spécifique, car la boucle entière est un no-op (elle ne renvoie rien et n'a aucun effet secondaire) et si elle fait quelque chose, elle le fait peut-être à l'intérieur du if (bien que j'aime toujoursbroken = (j ==i); if broken { something(); }
mieux personnellement)i
après la fin de la boucle externe. En d'autres termes, la seule réflexion vraiment importante est quand exactement elle se détache de la boucle extérieure.La réponse courte est "ça dépend". Je préconise de choisir en ce qui concerne la lisibilité et la compréhensibilité de votre code. Le chemin d'accès peut être plus lisible que de modifier la condition, ou vice versa. Vous pouvez également prendre en compte le principe de la moindre surprise, les directives utilisées dans la boutique / le projet et la cohérence de la base de code. Par exemple, goto pour quitter le commutateur ou pour la gestion des erreurs est une pratique courante dans la base de code du noyau Linux. Notez également que certains programmeurs peuvent avoir des problèmes de lecture de votre code (soit soulevé avec le mantra "goto is evil", ou tout simplement pas appris parce que leur professeur le pense) et certains d'entre eux pourraient même "vous juger".
D'une manière générale, un aller plus loin dans la même fonction est souvent acceptable, surtout si le saut n'est pas trop long. Votre cas d'utilisation de quitter une boucle imbriquée est l'un des exemples connus de goto "pas si mal".
la source
Dans votre cas, goto est une amélioration suffisante pour paraître tentante, mais ce n'est pas tant une amélioration qu'il vaut la peine d'enfreindre la règle contre leur utilisation dans votre base de code.
Pensez à votre futur critique: il devra penser: "Est-ce que cette personne est un mauvais codeur ou est-ce en fait un cas où le goto en valait la peine? Permettez-moi de prendre 5 minutes pour décider par moi-même ou faire une recherche sur le l'Internet." Pourquoi diable feriez-vous cela à votre futur codeur alors que vous ne pouvez pas utiliser goto entièrement?
En général, cette mentalité s'applique à tout "mauvais" code et le définit même: si cela fonctionne maintenant, et est bon dans ce cas, mais crée des efforts pour vérifier qu'il est correct, ce qui à cette époque un goto fera toujours, alors ne le faites pas fais le.
Cela étant dit, oui, vous avez produit l'un des cas légèrement plus épineux. Tu peux:
Il est très difficile pour moi de créer un cas où une double boucle n'est pas si cohérente qu'elle ne devrait de toute façon pas être sa propre routine.
Soit dit en passant, la meilleure discussion à ce sujet que j'ai vue est le code complet de Steve McConnell . Si vous aimez penser à ces problèmes de manière critique, je vous recommande fortement de lire, même de couverture en couverture malgré son immensité.
la source
TLD; DR: non en particulier, oui en général
Pour l'exemple spécifique que vous avez utilisé, je dirais non pour les mêmes raisons que beaucoup d'autres ont signalées. Vous pouvez facilement refactoriser le code sous une forme équivalente qui élimine le besoin de
goto
.En général, la proscription contre
goto
est une généralité basée sur la nature comprisegoto
et le coût de son utilisation. Une partie du génie logiciel prend des décisions de mise en œuvre. La justification de ces décisions se produit en pesant le coût par rapport aux avantages et chaque fois que les avantages l'emportent sur le coût, la mise en œuvre est justifiée. La controverse découle de différentes évaluations, à la fois en termes de coûts et d'avantages.Le fait est qu'il y aura toujours des exceptions où a
goto
est justifié, mais seulement pour certains en raison de valorisations différentes. Le dommage est que de nombreux ingénieurs excluent simplement les techniques dans une ignorance délibérée car ils les lisent sur Internet plutôt que de prendre le temps de comprendre pourquoi.la source
Je ne pense pas que ce cas justifie une exception, car cela peut s'écrire:
la source