Jeśli użyję break
instrukcji, spowoduje to tylko przerwanie pętli wewnętrznej i muszę użyć flagi, aby przerwać pętlę zewnętrzną. Ale jeśli istnieje wiele zagnieżdżonych pętli, kod nie będzie dobrze wyglądał.
Czy jest inny sposób na przerwanie wszystkich pętli? (Proszę nie używać 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
c
nested-loops
break
user966379
źródło
źródło
Odpowiedzi:
Posługiwać się:
if (condition) { i = j = 1000; break; }
źródło
const int count =1000
, w globalnej inicjalizacji. lub jako#define
makro.Nie, nie psuj zabawy plikiem
break
. To jest ostatnie ważne użyciegoto
;)Jeśli nie to, możesz użyć flag, aby wyrwać się z głęboko zagnieżdżonych pętli.
Innym podejściem do wyrwania się z zagnieżdżonej pętli jest rozłożenie obu pętli na osobną funkcję i powrót z tej funkcji, gdy chcesz wyjść.
Podsumowanie - aby wyrwać się z zagnieżdżonych pętli:
goto
Nie mogłem się oprzeć włączeniu tutaj xkcd :)
źródło
Goto są uważane za szkodliwe, ale wiele osób w komentarzach sugeruje, że nie musi. Jeśli jest używany rozsądnie, może być świetnym narzędziem. Wszystko, co jest używane z umiarem, jest zabawne.
źródło
bool stop = false; for (int i = 0; (i < 1000) && !stop; i++) { for (int j = 0; (j < 1000) && !stop; j++) { if (condition) stop = true; } }
źródło
goto
rozwiązanie. Nie wymaga znajomości ograniczeńi
ij
wewnątrz stanu. Podoba mi się pomysł umieszczeniaif (stop) break;
po wewnętrznej pętli, która mogłaby się samabreak
po ustawieniustop
.Jednym ze sposobów jest umieszczenie wszystkich zagnieżdżonych pętli w funkcji i powrót z najbardziej wewnętrznej pętli na wypadek potrzeby wyrwania się ze wszystkich pętli.
function() { for(int i=0; i<1000; i++) { for(int j=0; j<1000;j++) { if (condition) return; } } }
źródło
Myślę, że
goto
rozwiąże problemfor(int i = 0; i < 1000; i++) { for(int j = 0; j < 1000; j++) { if (condition) { goto end; } } } end: stmt2
źródło
Będziesz potrzebować zmiennej boolowskiej, jeśli chcesz, aby była czytelna:
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; }
Jeśli chcesz, aby była mniej czytelna, możesz dołączyć do oceny boolowskiej:
bool broke = false; for(int i = 0; i < 1000 && !broke; i++) { for(int j = 0; j < 1000; i++) { if (condition) { broke = true; break; } } }
Ostatecznym sposobem na unieważnienie początkowej pętli jest:
for(int i = 0; i < size; i++) { for(int j = 0; j < 1000; i++) { if (condition) { i = size; break; } } }
źródło
Skorzystaj z tej mądrej rady od zespołu LLVM:
„Zamień pętle predykatów w funkcje predykatów”
Widzieć:
http://llvm.org/docs/CodingStandards.html#turn-predicate-loops-into-predicate-functions
źródło
Uwaga: ta odpowiedź pokazuje naprawdę niejasną konstrukcję.
Jeśli używasz GCC, sprawdź tę bibliotekę . Podobnie jak w PHP,
break
może zaakceptować liczbę zagnieżdżonych pętli, które chcesz zakończyć. Możesz napisać coś takiego:for(int i = 0; i < 1000; i++) { for(int j = 0; j < 1000; j++) { if(condition) { // break two nested enclosing loops break(2); } } }
źródło
goto
:)goto
) jest o wiele lepsze niż w przypadku wbudowanego asm (specyficzne dla komputera, łatwiejsze do popełnienia błędu, trudniejsze do odczytania, ...).for(int i = 0; i < 1000; i++) { for(int j = 0; j < 1000; i++) { if(condition) { goto end; } } end:
źródło
Jeśli potrzebujesz wartości i i j, powinno to działać, ale z mniejszą wydajnością niż inne
for(i;i< 1000; i++){ for(j; j< 1000; j++){ if(condition) break; } if(condition) //the same condition break; }
źródło
j
wartość warunku musi być w jakiś sposób zapisana, aby to nadal działało.for (int i = 0; i < 1000; i++) { for (int j = 0; j < 1000; j++) { if (workComplete[i][j]) break; /* do work */ workComplete[i][j] = true; } if (workComplete[i][j]) break; ... }
będzie zawsze wyrwać się z pętli zewnętrznej po pierwszej iteracji pętli wewnętrznej.Innym podejściem jest refaktoryzacja kodu z dwóch pętli for do pętli for i jednej pętli ręcznej. W ten sposób przerwa w pętli ręcznej dotyczy pętli zewnętrznej. Użyłem tego raz w eliminacji Gaussa-Jordana, która wymagała trzech zagnieżdżonych pętli do przetworzenia.
for (int i = 0; i < 1000; i++) { int j = 0; MANUAL_LOOP:; if (j < 1000) { if (condition) { break; } j++; goto MANUAL_LOOP; } }
źródło
goto
, dlaczego niegoto
wyjść poza pętlę?Zauważam, że pytanie brzmi po prostu: „Czy istnieje inny sposób na przerwanie wszystkich pętli?” Nie widzę żadnych zastrzeżeń, ale tak nie jest
goto
, w szczególności PO nie prosił o dobrą drogę. A co powiesz nalongjmp
wyjście z wewnętrznej pętli? :-)#include <stdio.h> #include <setjmp.h> int main(int argc, char* argv[]) { int counter = 0; jmp_buf look_ma_no_goto; if (!setjmp(look_ma_no_goto)) { for (int i = 0; i < 1000; i++) { for (int j = 0; j < 1000; j++) { if (i == 500 && j == 500) { longjmp(look_ma_no_goto, 1); } counter++; } } } printf("counter=%d\n", counter); }
setjmp
Zwraca dwukrotnie. Za pierwszym razem zwraca 0, a program wykonuje zagnieżdżone pętle for. Następnie, gdy obai
ij
wynoszą 500, wykonuje sięlongjmp
, co powodujesetjmp
powrót z wartością 1, pomijając pętlę.Nie tylko pozwala
longjmp
wydostać się z zagnieżdżonych pętli, ale działa również z zagnieżdżonymi funkcjami!źródło
int i = 0, j= 0; for(i;i< 1000; i++){ for(j; j< 1000; j++){ if(condition){ i = j = 1001; break; } } }
Zerwie obie pętle.
źródło
for(int i = 0; i < 1000; i++) { for(int j = 0; j < 1000; i++) { if(condition) { func(para1, para2...); return; } } } func(para1, para2...) { stmt2; }
źródło
condition
się fałszywy. Aha, i druga pętla będzie działać wiecznie, ponieważi
j
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);
źródło