2012-03-14 17 views
55

Se utilizzo un'istruzione break, si interromperà solo il ciclo interno e sarà necessario utilizzare un flag per interrompere il ciclo esterno. Ma se ci sono molti cicli annidati, il codice non sembra buono.Come uscire da cicli annidati?

C'è un altro modo per interrompere tutti i loop? (Si prega di non utilizzare 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 
+1

si può provare int i e j int prima dell'inizio del ciclo e quindi sulla condizione renderli 1001 il ciclo non si iterare il prossimo. –

+0

Versione C++: http://stackoverflow.com/questions/1257744/can-i-use-break-to-exit-multiple-nested-for-loops –

risposta

33

Che dire:

if(condition) { 
i = j = 1000;break; 
} 
+0

sembra soluzione pratica – user966379

+21

Works, ma brutto e non generale. Cosa succede se qualcuno cambia il limite a 2000 (supponiamo che il codice sia più lungo, quindi non lo noti immediatamente)? – ugoren

+0

@ugoren È anche così semplice allora. cosa succede se hai usato un 'const int count = 1000', nell'Inizializzazione globale. o come macro '# define'. – Laksith

11

avrete bisogno di una variabile booleana, se lo vuoi leggibile:

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; 
} 

Se lo vuoi meno leggibile è possibile unire la valutazione booleana:

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

Come un modo migliore si può invalidare il ciclo iniziale:

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

for(i;i< 1000; i++){  
    for(j; j< 1000; j++){ 
     if(condition){ 
      i = j = 1001; 
      break; 
     } 
    } 
} 

si romperà entrambi i loop.

112

No, non rovinare il divertimento con uno break. Questo è l'ultimo utilizzo valido rimanente di goto :)

In caso contrario, è possibile utilizzare i flag per uscire da loop nidificati profondi.

Un altro approccio per l'interruzione di un ciclo annidato consiste nel troncare entrambi i loop in una funzione separata e tornare da quella funzione quando si desidera uscire.

Riassunti - per uscire da cicli annidati:

  1. uso goto
  2. money
  3. fattore out loop in funzione separata chiamate

non ha potuto resistere ad esclusione di xkcd qui :)

enter image description here

source

Goto's are considered harmful ma come molte persone nei commenti suggeriscono che non è necessario. Se usato con giudizio, può essere un ottimo strumento. Qualsiasi cosa usata con moderazione è divertente.

+17

Goto è chiaro come lo farai, sì. L'impostazione della variabile di uscita su 1000 è ancora più sfacciata. – correnos

+3

Vorrei aggiungere che i gotos non sono esplicitamente malvagi, possono solo essere usati per il male. Trovo che ci siano parecchi casi, ad esempio questo, dove sono la soluzione migliore. "Non usare gotos" è un buon inizio, ma penso che il prossimo passaggio di abilità ti permetta di "Non usare gotos a lungo raggio". – Aatch

+1

+1 per il riassunto più breve delle alternative finora. –

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

end: 
21
bool stop = false; 
for (int i = 0; (i < 1000) && !stop; i++) 
{ 
    for (int j = 0; (j < 1000) && !stop; j++) 
    { 
     if (condition) 
      stop = true; 
    } 
} 
+0

La soluzione incrementa entrambe le variabili di una su _break_, che può causare problemi – Thesola10

+2

È possibile impostare "stop = true;" e poi "rompere". Quindi, subito dopo la fine del ciclo "for" interno, fai "if (stop) break". –

14

Un modo è quello di mettere tutti i cicli annidati in una funzione e tornare dal più ciclo interno in caso di un bisogno di uscire tutti i loop.

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

sembra la soluzione migliore per me –

0
i = 0; 

do 
{ 
    for (int j = 0; j < 1000; j++) // by the way, your code uses i++ here! 
    { 
    if (condition) 
    { 
     break; 
    } 
    } 

    ++i; 

} while ((i < 1000) && !condition); 
11

Penso goto risolverà il problema

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

end: 
stmt2 
+0

@chikuba Ho ricevuto risposta da http://www.cprogramming.com/tutorial/goto.html e la tua risposta non viene pubblicata quando sto facendo la stessa cosa, ecco perché non vedo il tuo post –

3

Se avete bisogno i valori di i e j, questo dovrebbe funzionare ma con meno prestazioni rispetto ad altri

for(i;i< 1000; i++){  
    for(j; j< 1000; j++){ 
     if(condition) 
      break; 
    } 
    if(condition) //the same condition 
     break; 
} 
+0

Si noti che se la condizione dipende da 'j', allora il valore della condizione deve essere memorizzato in qualche modo affinché funzioni ancora. – SuperBiasedMan

+1

Hai ragione ma dopo ** pausa **, il valore di ** j ** non cambia e quindi è il valore della condizione. –

0
for(int i = 0; i < 1000; i++) { 
    for(int j = 0; j < 1000; i++) { 
     if(condition) { 
      func(para1, para2...); 
      return; 
     } 
    } 
} 

func(para1, para2...) { 
    stmt2; 
} 
0

Attenzione: Questa risposta dimostra una costruzione veramente oscuro.

Se si utilizza GCC, vedere this library. Come in PHP, break può accettare il numero di cicli nidificati che si desidera chiudere. È possibile scrivere qualcosa di simile:

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