Piszę kod, który wygląda następująco:
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
break; // **HERE, I want to break out of the loop itself**
}
}
Czy jest na to bezpośredni sposób?
Wiem, że mogę użyć flagi i przerwać pętlę, wstawiając warunkową przerwę tuż po przełączeniu. Chcę tylko wiedzieć, czy C ++ ma już jakąś konstrukcję do tego.
goto
atrakcyjne i czasami jedyne proste wyjście. Jeśli masz tendencję do organizowania kodu w małe funkcje, które mają tylko kilka wierszy i każda z nich wykonuje jedną rzecz, nigdy nie napotkasz tego problemu. (Nawiasem mówiąc, twój kod też będzie łatwiejszy do odczytania.):)
Odpowiedzi:
Przesłanka
Poniższy kod należy uznać za zły format, niezależnie od języka lub pożądanej funkcjonalności:
Argumenty wspierające
while( true )
Pętla jest słaba postać ponieważ:while(true)
pętli, które nie są nieskończone, tracimy zdolność do zwięzłego komunikowania się, gdy pętle w rzeczywistości nie mają warunku zakończenia. (Prawdopodobnie to już się stało, więc kwestia jest dyskusyjna.)Alternatywa dla „Idź do”
Poniższy kod jest lepszą formą:
Zalety
Bez flagi. Nie
goto
. Bez wyjątku. Łatwe do zmiany. Łatwe do odczytania. Łatwe do naprawienia. Dodatkowo kod:Druga kwestia jest ważna. Nie wiedząc, jak działa kod, gdyby ktoś poprosił mnie o zrobienie głównej pętli, aby inne wątki (lub procesy) miały trochę czasu procesora, przychodzą mi na myśl dwa rozwiązania:
Opcja 1
Łatwo wstaw pauzę:
Opcja 2
Zastąp wykonaj:
Ten kod jest prostszy (dzięki temu łatwiejszy do odczytania) niż pętla z osadzonym
switch
.isValidState
Metoda powinna określić tylko wtedy, gdy pętla powinna kontynuować. Koń roboczy metody powinien zostać wyabstrahowany doexecute
metody, co umożliwia podklasom przesłonięcie domyślnego zachowania (trudne zadanie przy użyciu osadzonychswitch
igoto
).Przykład Pythona
Porównaj następującą odpowiedź (na pytanie w Pythonie), która została opublikowana w StackOverflow:
Przeciw:
Tutaj
while True
skutkuje wprowadzającym w błąd i zbyt złożonym kodem.źródło
while(true)
powinien być szkodliwy, wydaje mi się dziwny. Są pętle, które sprawdzają przed wykonaniem, są takie, które sprawdzają później, i są takie, które sprawdzają w środku. Ponieważ te ostatnie nie mają konstrukcji składniowej w C i C ++, będziesz musiał użyćwhile(true)
lubfor(;;)
. Jeśli uważasz, że to niewłaściwe, nie poświęciłeś jeszcze wystarczająco dużo uwagi różnym rodzajom pętli.while(true) {string line; std::getline(is,line); if(!is) break; lines.push_back(line);}
Oczywiście mógłbym przekształcić to w wstępnie uwarunkowaną pętlę (używającstd::getline
jako warunku pętli), ale ma to same wady (line
musiałaby to być zmienna poza zakresem pętli). A gdybym to zrobił, musiałbym zapytać: po co w ogóle mamy trzy pętle? Zawsze moglibyśmy przekształcić wszystko w wstępnie uwarunkowaną pętlę. Użyj tego, co najlepiej pasuje. Jeśliwhile(true)
pasuje, użyj go.Możesz użyć
goto
.źródło
goto
. OP wyraźnie wspomniano bez użycia flag . Czy możesz zaproponować lepszy sposób, biorąc pod uwagę ograniczenia PO? :)Alternatywnym rozwiązaniem jest użycie słowa kluczowego
continue
w połączeniu zbreak
np .:Użyj
continue
instrukcji, aby zakończyć każdą etykietę przypadku, w której chcesz, aby pętla była kontynuowana, i użyjbreak
instrukcji, aby zakończyć etykiety przypadku, które powinny zakończyć pętlę.Oczywiście to rozwiązanie działa tylko wtedy, gdy po instrukcji switch nie ma dodatkowego kodu do wykonania.
źródło
:(
:(
W przeciwnym razie bardzo czysta implementacja.Zgrabnym sposobem na zrobienie tego byłoby umieszczenie tego w funkcji:
Opcjonalnie (ale „złe praktyki”): jak już sugerowano, możesz użyć goto lub zgłosić wyjątek wewnątrz przełącznika.
źródło
AFAIK nie ma „podwójnego przerwania” ani podobnej konstrukcji w C ++. Najbliższa byłaby a
goto
- która, choć ma złe konotacje ze swoją nazwą, istnieje w języku z jakiegoś powodu - o ile jest używana ostrożnie i oszczędnie, jest to realna opcja.źródło
Możesz umieścić swój przełącznik w oddzielnej funkcji, takiej jak ta:
źródło
Nawet jeśli nie lubisz goto, nie używaj wyjątku do wyjścia z pętli. Poniższy przykład pokazuje, jak brzydki może być:
Użyłbym
goto
jak w tej odpowiedzi. W takim przypadkugoto
kod będzie bardziej przejrzysty niż każda inna opcja. Mam nadzieję, że to pytanie będzie pomocne.Ale myślę, że użycie
goto
jest tutaj jedyną opcją ze względu na ciągwhile(true)
. Powinieneś rozważyć refaktoryzację swojej pętli. Przypuszczam, że następujące rozwiązanie:Lub nawet następujące:
źródło
goto
, nie używaj wyjątku do wyjścia z pętli:”?W tym przypadku nie ma konstrukcji C ++ do wyrwania się z pętli.
Użyj flagi, aby przerwać pętlę lub (jeśli to konieczne) wyodrębnij kod do funkcji i użyj
return
.źródło
Potencjalnie możesz użyć goto, ale wolałbym ustawić flagę, która zatrzymuje pętlę. Następnie wyłam się z przełącznika.
źródło
Dlaczego po prostu nie naprawić stanu w pętli while, powodując zniknięcie problemu?
źródło
Nie, C ++ nie ma takiej konstrukcji, biorąc pod uwagę, że słowo kluczowe „break” jest już zarezerwowane na wyjście z bloku przełącznika. Alternatywnie może wystarczyć do..while () z flagą wyjścia.
źródło
Myślę;
źródło
Najprostszym sposobem jest wprowadzenie prostego JEŻELI przed wykonaniem PRZEŁĄCZNIKA, a jeśli przetestujesz swój warunek wyjścia z pętli .......... tak proste, jak to tylko możliwe
źródło
Słowo
break
kluczowe w C ++ kończy tylko najbardziej zagnieżdżoną iterację lubswitch
instrukcję. Dlatego nie można było wyjść zwhile (true)
pętli bezpośrednio wswitch
instrukcji; jednak możesz użyć następującego kodu, który moim zdaniem jest doskonałym wzorcem dla tego typu problemów:Jeśli trzeba było coś zrobić, gdy
msg->state
jest równeDONE
(na przykład uruchomić procedurę czyszczenia), należy umieścić ten kod bezpośrednio pofor
pętli; czyli jeśli obecnie masz:Następnie użyj zamiast tego:
źródło
Zdumiewa mnie, jak proste jest to, biorąc pod uwagę głębokość wyjaśnień ... Oto wszystko, czego potrzebujesz ...
LOL!! Naprawdę! To wszystko, czego potrzebujesz! Jedna dodatkowa zmienna!
źródło
źródło
Mam ten sam problem i rozwiązałem go za pomocą flagi.
źródło
Jeśli dobrze pamiętam składnię C ++, możesz dodać etykietę do
break
instrukcji, tak jak w przypadkugoto
. Więc to, co chcesz, można łatwo napisać:źródło
źródło