web-dev-qa-db-fra.com

Comment sortir des boucles imbriquées?

Si j'utilise une instruction break, cela ne fera que casser la boucle interne et je dois utiliser un indicateur pour casser la boucle externe. Mais s'il y a beaucoup de boucles imbriquées, le code ne sera pas beau.

Y a-t-il un autre moyen de briser toutes les boucles? (Merci de ne pas utiliser goto stmt.)

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; j++) {
       if(condition) {
            // both of the loops need to break and control will go to stmt2
       }
   }

}

stmt2
80
user966379

Qu'en est-il de:

if(condition) {
i = j = 1000;break;
}
42
user879760

Non, ne gâchez pas le plaisir avec un break. Ceci est la dernière utilisation valide de goto;)

Sinon, vous pouvez utiliser des drapeaux pour sortir des boucles imbriquées profondes.

Une autre approche pour rompre une boucle imbriquée consiste à factoriser les deux boucles dans une fonction distincte et à renvoyer cette fonction lorsque vous souhaitez quitter.

Résumé - pour sortir des boucles imbriquées:

  1. utiliser goto
  2. utiliser des drapeaux
  3. factoriser les boucles en appels de fonction séparés

Impossible de résister à l'inclusion de xkcd ici :)

enter image description here

source

Les Goto sont considérés comme nuisibles mais autant de personnes dans les commentaires suggèrent que ce n'est pas nécessaire. Si utilisé judicieusement, il peut être un excellent outil. Tout ce qui est utilisé avec modération est amusant.

157
Srikar Appalaraju
bool stop = false;
for (int i = 0; (i < 1000) && !stop; i++)
{
    for (int j = 0; (j < 1000) && !stop; j++)
    {
        if (condition)
            stop = true;
    }
}
34
Tung

Une solution consiste à placer toutes les boucles imbriquées dans une fonction et à revenir de la boucle la plus interne en cas de besoin de sortir de toutes les boucles.

function() 
{    
  for(int i=0; i<1000; i++)
  {
   for(int j=0; j<1000;j++)
   {
      if (condition)
        return;
   }
  }    
}
23
Jay

Je pense que goto va résoudre le problème

for(int i = 0; i < 1000; i++) {
    for(int j = 0; j < 1000; i++) {
        if (condition) {
            goto end;
        }
    }
}

end:
stmt2 
16
Renjith K N

Vous aurez besoin d'une variable booléenne, si vous voulez qu'elle soit lisible:

bool broke = false;
for(int i = 0; i < 1000; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
  if (broke)
    break;
}

Si vous le souhaitez moins lisible, vous pouvez rejoindre l'évaluation booléenne:

bool broke = false;
for(int i = 0; i < 1000 && !broke; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      broke = true;
      break;
    }
  }
}

En dernier recours, vous pouvez invalider la boucle initiale:

for(int i = 0; i < size; i++) {
  for(int j = 0; j < 1000; i++) {
    if (condition) {
      i = size;
      break;
    }
  }
}
11
Jack

Utilisez ce conseil judicieux de l'équipe LLVM:

"Transforme les boucles de prédicat en fonctions de prédicat"

Voir:

http://llvm.org/docs/CodingStandards.html#turn-predicate-loops-into-predicate-functions

8
ouah

Si vous avez besoin des valeurs de i et j, cela devrait fonctionner mais avec moins de performances que d'autres

for(i;i< 1000; i++){    
    for(j; j< 1000; j++){
        if(condition)
            break;
    }
    if(condition) //the same condition
        break;
}
4
Ali Eren Çelik

Attention: Cette réponse montre une construction vraiment obscure.

Si vous utilisez GCC, consultez cette bibliothèque . Comme en PHP, break peut accepter le nombre de boucles imbriquées que vous souhaitez quitter. Vous pouvez écrire quelque chose comme ceci:

for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; j++) {
       if(condition) {
            // break two nested enclosing loops
            break(2);
       }
   }
}
3
DaBler
for(int i = 0; i < 1000; i++) {
   for(int j = 0; j < 1000; i++) {
       if(condition) {
            goto end;
   }
} 

end:
2
chikuba