web-dev-qa-db-fra.com

Comment puis-je sortir de deux boucles imbriquées dans Objective-C?

J'ai deux boucles imbriquées comme ceci:

for(...) {
    for(...) {

    }
}

Je sais qu'il existe une déclaration break. Mais je suis confus quant à savoir si cela casse les deux boucles ou seulement celle dans laquelle elle s'appelait? Je dois casser les deux dès que je vois qu'il est insensé de répéter plusieurs fois.

73
Thanks

break rompt une boucle, mais vous pouvez ajouter un contrôle à la boucle externe qui se rompt lorsque l’intérieur se casse.

bool dobreak = false;
for ( ..; !dobreak && ..; .. ) {
   for ( ... ) {
      if (...) {
         dobreak = true;
         break;
      }
   }
}
91
jbasko

Si goto simplifie le code, alors ce serait approprié.

for (;;) 
{
    for (;;) 
    {
        break; /* breaks inner loop */
    } 
    for (;;) 
    {
        goto outer; /* breaks outer loop */
    }
} 
outer:;
105
Ori Pessach

La déclaration break vous permet uniquement de sortir de la boucle la plus profonde. Si vous ne voulez pas la surcharge de code, de mémoire et de performances d'une variable d'état dédiée, je vous recommande de refactoriser le code dans une fonction ou une méthode qui lui est propre et d'utiliser return pour sortir de toutes les boucles:

void do_lots_of_work(void)
{
  int i, j;

  for(i=0; i<10 ; i++)
  {
    for(j=0;j< 10; j++)
    {
     ..
     ..
     if(disaster_struck())
      return; /* Gets us out of the loops, and the function too. */
    }
  }
}
13
unwind

Autre que la variable flag ou goto déjà mentionnée, vous pouvez lancer une exception Objective-C:

@try {
  for() {
    for() {
       @throw ...
    }
  }
}
@catch{
  ...
}
9
lothar

D'autres ont déjà expliqué comment définir un indicateur ou utiliser une variable goto, mais je vous conseillerais de refactoriser votre code afin que la boucle interne devienne une méthode distincte. Cette méthode peut ensuite renvoyer un indicateur pour indiquer que la boucle externe doit break. Si vous nommez vos méthodes de manière appropriée, ceci est beaucoup plus lisible.

for (int i = 0; i < 10; i++) {
   if (timeToStop(i)) break;
}

-(bool) timeToStop: (int) i {
    for (int j = 0; j < 10; j++) {
        if (somethingBadHappens) return true;
    }

    return false;
}

Pseudocode, non testé, mais vous voyez l'idée.

7
George Armhold

Changer le compteur du top loop avant la pause

for(i=0; i<10 ; i++)
  for(j=0;j< 10; j++){
     ..
     ..
     i = 10; 
     break;
  }
2
oxigen

Une autre solution consiste à factoriser la deuxième boucle dans une fonction:

int i;

for(i=0; i<10 ; i++){
    if !innerLoop(i) {
        break;
    }
}

bool innerLoop(int i)
    int j;
    for(j=0;j< 10; j++){
        doSomthing(i,j);
        if(endcondtion){
            return false;
        }
    }
}
2
Martijn

L'instruction break ne fera que sortir de la boucle dans la portée, qui est la boucle parente. Si vous souhaitez également vous échapper de la deuxième boucle, vous pouvez utiliser une variable booléenne située dans l'étendue des deux boucles.

bool isTerminated = false;

for (...)
{
    if (!isTerminated)
    {
        for(...)
        {
            ...

            isTerminated = true;
            break;
        }
    }
    else
    {
        break;
    }
}
2
Nick Allen

Le moyen le plus simple est probablement d’utiliser une variable "flag" 

for(i=0; i<10 && (done==false); i++)
  for(j=0;j< 10; j++){
     ..
     ..
     if(...){done=true; break;}
  }
2
Yogi

La déclaration de rupture sort de la boucle la plus interne. Un test et une instruction de rupture supplémentaires seraient nécessaires pour sortir de la boucle externe.

1
Lance Richardson

Si une pause est exécutée depuis un ensemble de boucles imbriquées, seule la boucle la plus interne dans laquelle la pause est exécutée est terminée. (Juste comme standard C)

0
Mitch Wheat

Juste pour les sourires, pourquoi ne pas transformer cette vérification vrai/faux en une méthode et utiliser les instructions return:

- (bool) checkTrueFalse: parameters{

   for ( ...) {
      for ( ... ) {

         if (...) {
            return true;
         }

      }
   }
   return false;
}
0
Tom Howard

Exactement comme les derniers, généralement comme ceci:

for(i=0;i<a;i++){  
 for(j=0;j<a;j++){
  if(Something_goes_wrong){
   i=a;
   break;
   }
 }
}
0
Martin