Ist es möglich, mit dieser break
Funktion mehrere verschachtelte for
Schleifen zu verlassen?
Wenn ja, wie würden Sie dies tun? Können Sie auch steuern, wie viele Schleifen die break
Ausgänge haben?
Ist es möglich, mit dieser break
Funktion mehrere verschachtelte for
Schleifen zu verlassen?
Wenn ja, wie würden Sie dies tun? Können Sie auch steuern, wie viele Schleifen die break
Ausgänge haben?
Antworten:
AFAIK, C ++ unterstützt keine Namensschleifen wie Java und andere Sprachen. Sie können ein goto verwenden oder einen von Ihnen verwendeten Flag-Wert erstellen. Überprüfen Sie am Ende jeder Schleife den Flag-Wert. Wenn es auf true gesetzt ist, können Sie aus dieser Iteration ausbrechen.
goto
wenn dies die beste Option ist.
goto
: schlechte Programmierer und pragmatische Programmierer. Ersteres ist selbsterklärend. Letztere, in die Sie passen würden, wenn Sie sie gut verwenden möchten, verwenden ein sogenanntes "böses" Konzept, wenn es das geringere von (zwei) Übeln ist. Lesen Sie dies, um einige C ++ - Konzepte besser zu verstehen, die Sie möglicherweise von Zeit zu Zeit verwenden müssen (Makros, Goto, Präprozessor, Arrays): parashift.com/c++-faq-lite/big-picture.html#faq-6.15
goto
selten die beste Option ist. Warum nicht die Loops in ihre eigene Funktion versetzen ( inline
wenn Sie sich Gedanken über die Geschwindigkeit machen) und return
daraus?
Nein, verwöhne es nicht mit einem break
. Dies ist die letzte verbleibende Festung für die Nutzung von goto
.
Nur um eine explizite Antwort mit Lambdas hinzuzufügen:
for (int i = 0; i < n1; ++i) {
[&] {
for (int j = 0; j < n2; ++j) {
for (int k = 0; k < n3; ++k) {
return; // yay we're breaking out of 2 loops here
}
}
}();
}
Natürlich hat dieses Muster einige Einschränkungen und natürlich nur C ++ 11, aber ich denke, es ist ziemlich nützlich.
Ein anderer Ansatz zum Ausbrechen einer verschachtelten Schleife besteht darin, beide Schleifen in eine separate Funktion und return
aus dieser Funktion heraus zu zerlegen, wenn Sie sie beenden möchten.
Dies wirft natürlich das andere Argument auf, ob Sie jemals explizit return
von einer anderen Funktion als am Ende ausgehen sollten.
continue_processing
) übersät waren , die die Ausführung von Codeblöcken weiter unten in der Funktion kontrollierten.
break beendet nur die innerste Schleife, die es enthält.
Sie können goto verwenden , um aus einer beliebigen Anzahl von Schleifen auszubrechen.
Natürlich wird goto oft als schädlich angesehen .
Ist es richtig, die Unterbrechungsfunktion [...] zu verwenden?
Die Verwendung von break und goto kann es schwieriger machen, über die Richtigkeit eines Programms nachzudenken. Hier finden Sie eine Diskussion dazu: Dijkstra war nicht verrückt .
break
oder zu empfehlen return
.
break
und return
haben den Vorteil, goto
dass Sie nicht nach einem Label suchen müssen, um herauszufinden, wohin sie gehen. Ja, darunter sind sie eine Art goto
, aber eine sehr eingeschränkte. Sie sind vom Mustervergleichsgehirn eines Programmierers viel einfacher zu entziffern als das uneingeschränkte goto
. Also IMO sind sie vorzuziehen.
goto
.
Obwohl diese Antwort bereits vorgestellt wurde, denke ich, dass ein guter Ansatz darin besteht, Folgendes zu tun:
for(unsigned int z = 0; z < z_max; z++)
{
bool gotoMainLoop = false;
for(unsigned int y = 0; y < y_max && !gotoMainLoop; y++)
{
for(unsigned int x = 0; x < x_max && !gotoMainLoop; x++)
{
//do your stuff
if(condition)
gotoMainLoop = true;
}
}
}
gotoMainLoop
in jedem Zyklus überprüft wird
goto
macht die Verwendung des Real den Kern lesbarer und leistungsfähiger.
Wie wäre es damit?
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
//Some statement
if (condition)
{
j=50;
k=50;
}
}
}
}
Ein Codebeispiel mit goto
und eine Bezeichnung zum Ausbrechen einer verschachtelten Schleife:
for (;;)
for (;;)
goto theEnd;
theEnd:
Eine gute Möglichkeit, aus mehreren verschachtelten Schleifen auszubrechen, besteht darin, Ihren Code in eine Funktion umzuwandeln:
void foo()
{
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < 50; j++)
{
for(unsigned int k=0; k < 50; k++)
{
// If condition is true
return;
}
}
}
}
goto kann sehr hilfreich sein, um verschachtelte Schleifen zu brechen
for (i = 0; i < 1000; i++) {
for (j = 0; j < 1000; j++) {
for (k = 0; k < 1000; k++) {
for (l = 0; l < 1000; l++){
....
if (condition)
goto break_me_here;
....
}
}
}
}
break_me_here:
// Statements to be executed after code breaks at if condition
Ich denke, a goto
ist unter diesen Umständen gültig:
Um ein break
/ zu simulieren continue
, möchten Sie:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
goto theEnd;
}
}
}
theEnd:
for ( ; ; ) {
for ( ; ; ) {
/*Code here*/
if (condition) {
i++;
goto multiCont;
}
}
multiCont:
}
i
. Daher i++
vor dem goto
Andere Sprachen wie PHP akzeptieren einen Parameter für break (dh break 2;), um die Anzahl der verschachtelten Schleifenebenen anzugeben, aus denen Sie ausbrechen möchten, C ++ jedoch nicht. Sie müssen es herausfinden, indem Sie einen Booleschen Wert verwenden, den Sie vor der Schleife auf false gesetzt haben, der in der Schleife auf true gesetzt ist, wenn Sie brechen möchten, sowie eine bedingte Unterbrechung nach der verschachtelten Schleife, um zu überprüfen, ob der Boolesche Wert auf true gesetzt wurde und brechen wenn ja.
Ich weiß, das ist ein alter Beitrag. Aber ich würde eine etwas logische und einfachere Antwort vorschlagen.
for(unsigned int i=0; i < 50; i++)
{
for(unsigned int j=0; j < conditionj; j++)
{
for(unsigned int k=0; k< conditionk ; k++)
{
// If condition is true
j= conditionj;
break;
}
}
}
j = conditionj
sie nicht funktioniert, wenn Sie stattdessen ein komplexes Prädikat haben j < conditionj
.
Brechen Sie eine beliebige Anzahl von Schleifen mit nur einer bool
Variablen (siehe unten):
bool check = true;
for (unsigned int i = 0; i < 50; i++)
{
for (unsigned int j = 0; j < 50; j++)
{
for (unsigned int k = 0; k < 50; k++)
{
//Some statement
if (condition)
{
check = false;
break;
}
}
if (!check)
{
break;
}
}
if (!check)
{
break;
}
}
In diesem Code haben wir break;
alle Schleifen.
Ich bin mir nicht sicher, ob es sich lohnt, aber Sie können Javas benannte Schleifen mit ein paar einfachen Makros emulieren:
#define LOOP_NAME(name) \
if ([[maybe_unused]] constexpr bool _namedloop_InvalidBreakOrContinue = false) \
{ \
[[maybe_unused]] CAT(_namedloop_break_,name): break; \
[[maybe_unused]] CAT(_namedloop_continue_,name): continue; \
} \
else
#define BREAK(name) goto CAT(_namedloop_break_,name)
#define CONTINUE(name) goto CAT(_namedloop_continue_,name)
#define CAT(x,y) CAT_(x,y)
#define CAT_(x,y) x##y
Anwendungsbeispiel:
#include <iostream>
int main()
{
// Prints:
// 0 0
// 0 1
// 0 2
// 1 0
// 1 1
for (int i = 0; i < 3; i++) LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << i << ' ' << j << '\n';
if (i == 1 && j == 1)
BREAK(foo);
}
}
}
Ein anderes Beispiel:
#include <iostream>
int main()
{
// Prints:
// 0
// 1
// 0
// 1
// 0
// 1
int count = 3;
do LOOP_NAME(foo)
{
for (int j = 0; j < 3; j++)
{
std::cout << ' ' << j << '\n';
if (j == 1)
CONTINUE(foo);
}
}
while(count-- > 1);
}
Sie können try ... catch verwenden.
try {
for(int i=0; i<10; ++i) {
for(int j=0; j<10; ++j) {
if(i*j == 42)
throw 0; // this is something like "break 2"
}
}
}
catch(int e) {} // just do nothing
// just continue with other code
Wenn Sie aus mehreren Schleifen gleichzeitig ausbrechen müssen, ist dies oft eine Ausnahme.
Das Ausbrechen einer for-Schleife ist für mich etwas seltsam, da die Semantik einer for-Schleife normalerweise anzeigt, dass sie eine bestimmte Anzahl von Malen ausgeführt wird. Es ist jedoch nicht in allen Fällen schlecht; Wenn Sie nach etwas in einer Sammlung suchen und es brechen möchten, nachdem Sie es gefunden haben, ist es nützlich. Das Aufbrechen verschachtelter Schleifen ist in C ++ jedoch nicht möglich. Es ist in anderen Sprachen durch die Verwendung einer beschrifteten Pause. Sie können ein Etikett und ein Goto verwenden, aber das kann nachts zu Sodbrennen führen. Scheint jedoch die beste Option zu sein.