Ist es möglich, in C ++ eine Vor-Zeit zu beenden, wenn eine Endbedingung erreicht ist?

7

Ich möchte wissen, ob es möglich ist, eine for-Schleife in C ++ zu beenden, wenn eine Endbedingung (die sich von der richtigen Anzahl von Iterationen unterscheidet) verifiziert wird. Zum Beispiel:

%Vor%

Ich weiß, dass dies in Perl mit den nächsten LABEL- oder LABEL-Aufrufen und beschrifteten Blöcken möglich ist, ist es möglich, es in C ++ zu tun oder ich sollte eine while-Schleife verwenden?

Danke.

    
tunnuz 06.01.2009, 13:16
quelle

15 Antworten

51

Sie können das Schlüsselwort return verwenden: Verschieben Sie die verschachtelte Schleife in eine Subroutine, rufen Sie die Unterroutine auf, um die verschachtelten Schleifen auszuführen, und kehren Sie von der Unterroutine zurück, um [alle] Schleifen zu beenden.

    
ChrisW 06.01.2009, 13:33
quelle
47

Trotz der Argumente " goto als schädlich" scheint dies der perfekte Ort für goto zu sein. Das ist im Wesentlichen, was Sie in Perl machen. Ernsthaft ... betrachte die Alternativen:

Zusätzliche Statusvariablen

%Vor%

Über Ausnahmen verlassen

%Vor%

Komplexe Logik

%Vor%

goto

%Vor%

Ist der letzte weniger klar? Ich glaube nicht, dass es so ist. Ist es fragiler? IMHO, die anderen sind ziemlich fehleranfällig und zerbrechlich im Vergleich zur goto Version. Entschuldigung, hier auf der Seifenkiste zu stehen, aber das hat mich schon eine Weile gestört;)

Die einzige Sache, die Sie haben müssen, ist, dass goto und Ausnahmen ziemlich ähnlich sind. Sie eröffnen beide die Möglichkeit, Ressourcen auszulaugen und sie nicht so sorgfältig zu behandeln.

    
D.Shawley 06.01.2009 13:45
quelle
13

Lassen Sie mich das mit Nachdruck sagen (aber höflich ;-), so gut ich kann: Beim for -Konstrukt in C-ähnlicher Sprache geht es nicht um Zählen.

Der Testausdruck, der bestimmt, ob fortgefahren werden soll, kann alles sein, was für den Zweck der Schleife relevant ist; Der Aktualisierungsausdruck muss nicht "zu einem Zähler hinzufügen" sein.

%Vor%

wäre eine (ziemlich willkürliche) Möglichkeit zum Neuschreiben.

Der Punkt ist, dass wenn eine Bedingung erstellt wird, der Punkt einer Interaktion normalerweise in der Lage ist, eine Schleife (mit while oder for ) so zu schreiben, dass die continue / terminate Bedingung explizit angegeben wird.

(Wenn Sie eine Beschreibung des Geschehens veröffentlichen könnten, würde es wahrscheinlich etwas schreiben, das nicht so willkürlich aussieht wie oben beschrieben.)

    
joel.neely 06.01.2009 13:31
quelle
8

Sie können nicht mit einer einzigen Unterbrechungsanweisung aus zwei Schleifen springen, sondern mit einem Sprung aus der inneren Schleife heraus springen.

Wenn das Goto lokalisiert ist und bedeutet, dass es weniger Logik gibt als sonst, denke ich, dass es ein vollkommen akzeptabler Code ist. Wenn Sie zusätzliche Flag-Variablen haben oder die Iterator-Variable aus der inneren Schleife herausziehen, damit Sie sie in der äußeren Schleife vergleichen können, erleichtert das den Code IMHO nicht.

    
Rob Walker 06.01.2009 13:22
quelle
8

Von allen obigen Vorschlägen würde ich vermeiden, den try / catch-Mechanismus zu verwenden, da Ausnahmen für außergewöhnliche Umstände und nicht für normale Kontrollflüsse reserviert werden sollten.

Die Verwendung von zwei Unterbrechungen ist in Ordnung, wenn Sie die zweite Bedingung entsprechend erstellen können. Es wäre auch gut, einen booleschen Wert für diesen Zweck zu verwenden, und Sie könnten ihn sogar in den Zustand jeder for-Schleife einbinden. Zum Beispiel:

%Vor%

Wenn Sie jedoch mehr als zwei Loops verwenden, ist es möglicherweise sinnvoller, sie in eine Funktion zu packen und einfach return zu verwenden, um die Funktion (und auch alle Loops) zu beenden. Dann könnten Sie den Code auf eine Weise umgestalten, die alle Schleifen außer einer der Schleifen beseitigen kann, sei es durch Aufruf einer Funktion zur Ausführung des inneren Schleifencodes, usw.

Schließlich haben Sie keine Angst, einen goto in diesem Fall zu verwenden, normalerweise sind goto's schlechte unstrukturierte Programmierung, aber in einigen Fällen (so) sind sie sehr nützlich.

    
Daemin 06.01.2009 13:48
quelle
6
%Vor%

Oder du könntest einfach gehen. Oder nicht: -)

    
Gilad Naor 06.01.2009 13:47
quelle
6

Sie können in C / C ++ nicht so springen:

%Vor%

ohne die Verwendung von goto. Du brauchst ein Konstrukt wie:

%Vor%

Alternativ verwenden Sie throw und catch - aber das ist nicht gut, da throw wirklich für Ausnahmen und nicht für die Flusskontrolle verwendet werden sollte.

Ein sauberer Weg ist, die innere Schleife zu einer Funktion zu machen:

%Vor%     
Skizz 06.01.2009 13:25
quelle
4
%Vor%     
Marcin Gil 06.01.2009 13:22
quelle
4

Sie könnten eine goto-Anweisung verwenden, aber das wird im Allgemeinen als eine angesehen schlechte Praxis.

Ihre andere Möglichkeit ist, so etwas zu tun

%Vor%     
brien 06.01.2009 13:22
quelle
2

Das Lesen von Code sollte nicht wie das Lesen eines Detektivbuches sein (was immer herausgefunden werden muss) ...

ein Beispiel:

Java:

%Vor%

Sie müssen nicht herausfinden, was break iterate_rows macht, Sie lesen es einfach.

C ++:

%Vor%

goto break_iterate_rows ist nur eine sichtbare Version von break iterate_rows

Wenn Sie Ihre Verwendung von goto und Labels nur auf diese Art von Code beschränken, werden Sie die Absicht nicht herausfinden. Wenn Sie die Verwendung von goto und Labels auf diese Art von Code beschränken, werden Sie den Code nur lesen, nicht analysieren oder herausfinden. Du wirst nicht beschuldigt, ein böser Programmierer zu sein.

Und wenn Sie wirklich Ihre gotos in dieser Art von Code einschränken, werden Sie in der Lage sein, die Gewohnheit zu entwickeln, nicht herauszufinden, was diese verflixten gotos in Ihrem Code tun. Zusätzlicher Vorteil ist, dass Sie Booleans nicht einführen und verfolgen müssen (was imho, führt Sie zu Erkennung des Codes , so dass es ein wenig unlesbar, was den eigentlichen Zweck der Vermeidung von gotos vereitelt)

P.S.

Verknüpfen Sie diese Beschriftungen mit Kommentaren (vor der Schleife). Wenn Sie diese Zeilen mit goto-Anweisung lesen, kennen Sie die Absicht dieser gotos bereits.

    
Michael Buen 06.01.2009 15:11
quelle
1

Ich habe ein paar Vorschläge:

  1. throw .... setze die beiden Loops in einen "try {}" und "fange" dann den "throw" an der Bedingung.

  2. Setzen Sie die beiden Schleifen in eine Methode und geben Sie die Bedingung zurück.

  3. Goto ist nicht böse, die Leute benutzen es auch ... Sie können "goto" verwenden, es kann der klarste Code sein, besonders im Umgang mit Fehlern. Ich habe keine in 20 Jahren benutzt.

Tony

    
AnthonyLambert 06.01.2009 13:31
quelle
1

Ich habe immer versucht, mich von goto -Aussagen fernzuhalten (es wurde in der Schule und aus irgendeinem Grund immer abgelehnt). Ich würde etwas verwenden, was Daemin vorgeschlagen hat.

    
user17720 06.01.2009 14:02
quelle
1

Sie können Labels verwenden, etwa wie folgt:

%Vor%

In Java können Sie Etiketten übergeben, um zu brechen, denke ich?

Edit - Ich habe den goto nach End anstatt nach Outer geändert, aber ich denke nicht, dass der negative rep gerechtfertigt ist. Diese Antwort gibt den einfachsten Weg, es zu tun.

    
Dynite 06.01.2009 13:20
quelle
1

Ein weiterer Grund, das Konstrukt for vollständig zu überdenken, besteht darin, dass sein Scoping den Zugriff auf die gesteuerten Variablen verhindert, nachdem die Schleife beendet wurde. Der Wert (die Werte) der Variablen, die in der Schleife mutiert sind, kann aus einer Vielzahl von Gründen nützlich sein (z. B. um den Erfolg von einem Fehler in einer Suche zu unterscheiden), die ansonsten zusätzliche Variablen erfordern würden, um diese Information nach dem Verlassen des Bereichs zu bewahren. Hier ist ein kleines Beispiel, das ein quadratisches Array namens a für einen target Wert durchsucht (vorausgesetzt, dass SIZE nicht Null ist, sonst ist keine Suche notwendig!):

%Vor%

Der nachfolgende Code kann i < SIZE verwenden, um festzustellen, ob der gewünschte Wert gefunden wurde.

Ein weiterer Vorteil der oben genannten ist die Flexibilität. Nehmen wir an, dass wir jetzt wissen, dass die Werte in den Zeilen von a aufsteigend sind, so dass der Rest einer Zeile irrelevant ist, wenn ein Wert größer als target angetroffen wird. Es ist einfach, genau zu wissen, welche Änderungen vorgenommen werden müssen und wo es zu machen ist. Da diese neue Information es uns ermöglicht, die aktuelle Zeile aufzugeben, ist nur die innere Entscheidung betroffen und wird zu:

%Vor%

Ich sehe mehr der neueren Sprachen (insbesondere funktional orientierte), die das alte "zählende" Schleifenkonstrukt aufgeben; Das ist wahrscheinlich eine gute Sache, da es uns ermutigt, über die Bedeutung der Schleife nachzudenken, anstatt einfach zu zählen.

    
joel.neely 06.01.2009 18:36
quelle
1

Der beste Weg, den ich gesehen habe , sind Makros und Gotos, aber es ist eigentlich ganz nett (die verlinkten Posts) beginnt mit dem Sprechen über Perl, aber der letzte Absatz oder so führt die Makros ein.)

Es erlaubt Ihnen, Code wie zu schreiben:

%Vor%     
Max Lybbert 06.01.2009 19:26
quelle

Tags und Links