
Von der Grundstufe bis zur Mittelstufe: Die Anweisungen BREAK und CONTINUE
Einführung
Der hier dargestellte Inhalt ist ausschließlich für Bildungszwecke bestimmt. Die Anwendung sollte unter keinen Umständen zu einem anderen Zweck als zum Erlernen und Beherrschen der vorgestellten Konzepte verwendet werden.
Im vorigen Artikel „Von der Grundstufe zur Mittelstufe: Die Anweisungen WHILE und DO WHILE“ haben wir Schleifen eingeführt. Voraussetzung für das Verständnis der Konzepte in diesem Artikel ist daher, dass Sie die Erläuterungen und Beispiele im vorherigen Artikel verstanden haben.
Ich weiß, dass es vielen Programmieranfängern schwerfällt, die Funktionsweise von Schleifenbefehlen richtig zu verstehen. Schleifen sind jedoch unverzichtbar und kommen in fast jedem Programm vor, das Sie im Laufe Ihrer Karriere entwickeln werden, selbst wenn Sie Programme nur als Hobby erstellen. Das Verständnis und die effektive Arbeit mit schleifenbezogenen Befehlen ist entscheidend.
Es gibt noch eine andere Art von Schleife, die keine konventionellen Befehle verwendet, aber das werden wir zu einem späteren Zeitpunkt untersuchen. Im Folgenden werden wir uns auf drei Befehle konzentrieren, die häufig in Schleifen vorkommen. Während zwei von ihnen auch außerhalb einer Schleife verwendet werden können, ist eine von ihnen strikt auf Schleifenstrukturen beschränkt. Sie sollte jedoch, außer in sehr begründeten Fällen, niemals isoliert innerhalb einer Schleife verwendet werden.
In diesem Artikel werden wir diese Befehle untersuchen, insbesondere zwei von ihnen, wie im Titel hervorgehoben. Mit anderen Worten, es ist an der Zeit zu verstehen, wie man eine Schleife von innen heraus steuert. An dieser Stelle bitte ich Sie, liebe Leserin, lieber Leser, genau zuzuhören, was hier erklärt wird. Wenn Sie die hier vorgestellten Konzepte nicht verstehen, werden Sie zweifelsohne irgendwann Schwierigkeiten bei der Programmierung haben.
Eine mögliche Antwort
Bevor wir beginnen, habe ich Sie im letzten Artikel mit einer kleinen Herausforderung konfrontiert. Die Aufgabe bestand darin, den folgenden Code in eine Version umzuwandeln, bei der eine Schleife verwendet wird.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Factorial(); 07. Factorial(); 08. Factorial(); 09. Factorial(); 10. Factorial(); 11. } 12. //+------------------------------------------------------------------+ 13. void Factorial(void) 14. { 15. static uchar counter = 0; 16. static ulong value = 1; 17. 18. Print("Factorial of ", counter, " => ", value); 19. counter = counter + 1; 20. value = value * counter; 21. } 22. //+------------------------------------------------------------------+
Code 01
Wenn Sie keine Lösung finden konnten, machen Sie sich keine Sorgen, denn das gehört in dieser Phase zum Lernprozess. Lassen Sie jedoch nicht zu, dass sich das Material stapelt, bevor Sie mit dem Studium beginnen. Auf dem Weg zu dem, was ich als Mittelstufe ansehe, werden sich die Konzepte rasch vermehren.
Es gibt mehrere Möglichkeiten, eine Schleife in Code 01 umzuwandeln - oder besser gesagt, einzubauen - um sie effizienter zu machen. Ein solcher Ansatz ist bereits in greifbare Nähe gerückt, dank dessen, was wir im letzten Artikel behandelt haben.
Einfach ausgedrückt, könnten Sie den Code 07 aus dem vorigen Artikel ändern, um das gleiche Ergebnis zu erzielen wie mit Code 01. Wie? Durch die Verwendung von Code 02, der unten abgebildet ist:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. uchar counter = 0; 07. 08. while (counter < 5) 09. Factorial(counter); 10. } 11. //+------------------------------------------------------------------+ 12. void Factorial(uchar &counter) 13. { 14. static ulong value = 1; 15. 16. Print("Factorial of ", counter, " => ", value); 17. counter = counter + 1; 18. value = value * counter; 19. } 20. //+------------------------------------------------------------------+
Code 02
Dies ist nur eine Möglichkeit, das Problem zu lösen. Es gibt andere Ansätze, manche komplexer, manche weniger komplex. Angesichts der bisherigen Ausführungen ist diese Lösung jedoch eine solide Wahl. Wenn Sie nun nicht ganz verstehen, was Code 02 tut, oder noch wichtiger, warum er die gleiche Ausgabe wie Code 01 erzeugt, sollten Sie diesen Artikel sofort abbrechen. Lesen Sie die vorangegangenen Artikel und stellen Sie sicher, dass Sie Code 02 verstanden haben. Erst wenn Sie dies verstanden haben, sollten Sie mit diesem und künftigen Artikeln fortfahren.
Nachdem ich nun diese Warnung ausgesprochen habe, wollen wir nun die erste Aussage in diesem Artikel untersuchen. Wir beginnen mit der einfachsten Anweisung, die innerhalb einer Schleife verwendet werden kann. Doch bevor wir uns damit befassen, wollen wir ein neues Thema einführen.
Die RETURN-Anweisung
Ich weiß, dass viele von Ihnen, die bereits Erfahrung mit der MQL5-Programmierung haben, vielleicht denken: Aber diese Aussage hat nichts mit Schleifen zu tun, sondern eher mit Funktionen! Und Sie hätten absolut Recht. Die RETURN-Anweisung ist für Funktionen weitaus wichtiger als für Schleifen. Obwohl es in Funktionen eine obligatorische Anweisung ist, ist sie in Prozeduren optional. Gerade wegen ihrer Wirkung bei der Verwendung innerhalb von Prozeduren kann die RETURN-Anweisung manchmal innerhalb einer Schleife erscheinen.
Passen Sie jetzt gut auf. Der Zweck der RETURN-Anweisung besteht darin, die Kontrolle an die Funktion oder Prozedur zurückzugeben, die sie aufgerufen hat. Wenn Sie jedoch eine RETURN-Anweisung innerhalb der Hauptprozedur Ihrer Anwendung platzieren, wie z. B. OnInit oder OnStart (je nach Fall), wird Ihre Anwendung durch die Ausführung von RETURN beendet, was viele Anfänger nicht verstehen. Dies führt dazu, dass MetaTrader 5 es aus dem Chart entfernt. Dies ist der Fall, weil jede Anwendung letztlich nur eine Funktion oder Prozedur ist, die vom Betriebssystem ausgeführt wird. Wenn Sie dies verstehen, können Sie besser nachvollziehen, warum die Platzierung einer RETURN-Anweisung innerhalb von OnInit oder OnStart dazu führen kann, dass Ihre Anwendung vorzeitig beendet wird.
Wenn RETURN in OnInit erscheint, hängt es vom Wert ab, der an MetaTrader 5 zurückgegeben wird, ob die Anwendung beendet wird oder nicht. Wenn jedoch RETURN innerhalb der OnStart-Prozedur ausgeführt wird, wird die Anwendung beendet.
Um dies zu verstehen, lassen Sie uns mit einem einfachen Beispiel beginnen (siehe unten):
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 07. 08. return; 09. 10. Print(__FUNCTION__, " ", __LINE__, " This line will never be executed..."); 11. } 12. //+------------------------------------------------------------------+
Code 03
Das Ergebnis der Ausführung dieses Codes ist unten zu sehen:
Abbildung 01
Der wichtigste Punkt ist, dass die RETURN-Anweisung in Zeile 8 innerhalb einer Prozedur steht. Da es sich um eine Prozedur handelt, darf sie nicht mit einem Rückgabewert verbunden sein. Damit sollen Konflikte mit dem Compiler bei der Erstellung der ausführbaren Datei vermieden werden. Befindet sich RETURN jedoch innerhalb einer Funktion, wäre die Zuordnung eines Rückgabewerts zwingend erforderlich. Der Grund dafür ist, dass die aufrufende Funktion einen Rückgabewert erhalten muss. Wir haben dies bereits bei der Behandlung von Variablen besprochen.
Im Moment liegt unser Schwerpunkt jedoch auf etwas anderem. Hier geht es um das vorzeitige Verlassen einer Schleife. Dies ist oft notwendig und sogar wünschenswert, wenn ein bestimmter Zustand eintritt. Ein einfaches Beispiel für die Anwendung dieses Verfahrens ist unten dargestellt:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 07. 08. Procedure_Loop(); 09. 10. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 11. } 12. //+------------------------------------------------------------------+ 13. void Procedure_Loop(void) 14. { 15. char info = 10; 16. 17. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 18. 19. while (info) 20. { 21. info = info - 3; 22. 23. Print("Loop : ", info); 24. 25. if (info < -5) return; 26. } 27. 28. Print(__FUNCTION__, " ", __LINE__, " This line will never be executed..."); 29. } 30. //+------------------------------------------------------------------+
Code 04
Die Ausführung von Code 04 führt zu dem in der folgenden Abbildung dargestellten Ergebnis:
Abbildung 02
An dieser Stelle erscheint Ihnen das Verhalten vielleicht etwas ungewöhnlich. Wenn die Schleife beendet werden soll, wenn die Variable „info“ einen Wert von weniger als fünf erreicht, warum wird diese Bedingung nicht direkt in den Testausdruck der Schleife aufgenommen? Der Grund dafür ist, dass wir manchmal nicht wollen, dass die Schleife einen bestimmten Wert erreicht; aber wenn sie es tut, wollen wir den Rest der Routine oder Prozedur, in der die Schleife existiert, ignorieren.
Aufgrund dieses Details wird die Zeile 28 in Code 04 nie ausgeführt. Der Grund dafür ist, dass der Wert von „info“ nicht Null erreichen wird, bevor die IF-Bedingung die Ausführung der RETURN-Anweisung auslöst. Infolgedessen zeigt Bild 02 Werte von sieben bis hin zu negativen acht an.
Sie fragen sich vielleicht: Warum wird die Anwendung nicht beendet, wenn Zeile 25 ausgeführt wird, sodass Zeile 10 ausgeführt werden kann? Dieses Verhalten unterscheidet sich von dem, was wir bei Code 03 gesehen haben. Der Grund dafür ist, dass OnStart die erste Prozedur (oder Funktion) ist, die von MetaTrader 5 aufgerufen wird, während Procedure_Loop von OnStart aufgerufen wird. Wenn die RETURN-Anweisung ausgeführt wird, gibt sie daher die Kontrolle an die Funktion oder Prozedur zurück, die sie ursprünglich aufgerufen hat, in diesem Fall OnStart.
Die Art und Weise, wie MetaTrader 5 Funktionsaufrufe verwaltet, wird später im Detail erläutert. Vereinfacht ausgedrückt ruft MetaTrader 5 jedoch zwei Hauptfunktionen auf: OnStart und OnInit. Nur in diesen speziellen Fällen führt die RETURN-Anweisung zum Abbruch der Anwendung. Abgesehen von diesen Fällen führt die Verwendung von RETURN nicht zum Beenden der Anwendung.
Großartig. Jetzt sollten Sie wissen, wie RETURN innerhalb einer Schleife verwendet werden kann. Wenn etwas unklar bleibt, nehmen Sie sich etwas Zeit, um mit diesen einfacheren Beispielen zu üben, bis Sie das Konzept vollständig verstanden haben. Kommen wir nun zu der nächsten Aussage, die in diesem Artikel untersucht werden soll.
Die Anweisung BREAK
Die Anweisung BREAK ist recht interessant, aber sie erfordert besondere Aufmerksamkeit. Sie sollten sich Zeit nehmen, diese Aussage zu studieren. Es ist nicht ungewöhnlich, dass Anfänger mit der Verwendung des Programms Schwierigkeiten haben. Während die Verwendung von BREAK in einfachen Schleifen recht einfach ist, kann es bei komplizierteren Schleifenstrukturen komplizierter werden.
Einer der häufigsten Fehler bei der Verwendung von BREAK ist die Annahme, dass es eine andere Schleife oder sogar eine andere Kontrollflussanweisung beeinflussen wird. Das liegt daran, dass BREAK nicht nur für Schleifen verwendet wird, sondern auch für eine andere Kontrollstruktur, auf die wir später noch eingehen werden. Aber machen Sie sich darüber vorerst keine Sorgen. Konzentrieren wir uns ausschließlich auf sein Verhalten innerhalb von Schleifen.
Es gibt ein wichtiges Konzept, das viele Programmierer entweder übersehen oder vergessen: Die BREAK-Anweisung folgt einem Prinzip, das dem von RETURN sehr ähnlich ist. Mit anderen Worten, sie wird nicht willkürlich in einer Schleife platziert. Normalerweise ist sie Teil einer IF-Anweisung. Um dies zu veranschaulichen, können wir Code 04 aus dem vorherigen Abschnitt nehmen und die RETURN-Anweisung durch BREAK ersetzen. Die aktualisierte Version des Codes ist unten abgebildet:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 07. 08. Procedure_Loop(); 09. 10. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 11. } 12. //+------------------------------------------------------------------+ 13. void Procedure_Loop(void) 14. { 15. char info = 10; 16. 17. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 18. 19. while (info) 20. { 21. info = info - 3; 22. 23. Print("Loop : ", info); 24. 25. if (info < -5) break; 26. } 27. 28. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 29. } 30. //+------------------------------------------------------------------+
Code 05
Wenn Code 05 ausgeführt wird, sieht die Ausgabe im MetaTrader 5 Terminal wie folgt aus:
Abbildung 03
Interessant! Diesmal haben wir Informationen, die bisher noch nicht gezeigt wurden. Es ist wirklich interessant, es scheint, als ob Schleifen recht einfach zu bearbeiten sind. Jetzt sind wir bereit, mit komplexeren Codes zu arbeiten. (Lacht.) Beruhigen Sie sich, liebe Leserin, lieber Leser, wir stehen erst am Anfang. Es gibt ein Problem (eigentlich ein Missverständnis), das bei Programmieranfängern in Bezug auf diese Aussagen häufig auftritt. Ich bitte Sie daher, die Verwendung von Variationen der hier angegebenen Codes zu üben.
Das erste Missverständnis bezieht sich auf die Verwendung des BREAK-Operators in verschachtelten Schleifen. Ja, genau wie wir mehrere IF-Anweisungen verschachteln können, können wir auch mehrere Schleifen ineinander verschachteln. Dies ist sehr häufig bei der Arbeit mit mehrdimensionalen Matrizen der Fall, wenn wir die Indizes nicht manuell berechnen wollen. Schauen wir uns jedoch ein einfaches Beispiel für eine verschachtelte Schleife an, um zu verstehen, wie sich die BREAK-Anweisung in diesem Fall verhält. Ein einfaches Beispiel ist unten dargestellt:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 07. 08. Procedure_Loop(); 09. 10. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 11. } 12. //+------------------------------------------------------------------+ 13. void Procedure_Loop(void) 14. { 15. char info = 10, 16. limit = 5; 17. 18. do 19. { 20. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ") Limit (", limit, ")"); 21. 22. while (info > limit) 23. { 24. if (limit < 0) break; 25. 26. info = info - 3; 27. 28. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ") Limit (", limit, ")"); 29. } 30. info = info + limit; 31. limit = limit - 2; 32. 33. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ") Limit (", limit, ")"); 34. 35. }while (info > 0); 36. 37. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ") Limit (", limit, ")"); 38. } 39. //+------------------------------------------------------------------+
Code 06
Auch wenn der Code 06 aufgrund der Anzahl der gedruckten Nachrichten zunächst kompliziert erscheinen mag, ist er eigentlich recht einfach. Sie demonstriert, wie die BREAK-Anweisung in verschachtelten Schleifen funktioniert. Wenn Sie Code 06 ausführen, ist das Ergebnis recht interessant. Sie ist unten zu sehen:
Abbildung 04
Passen Sie gut auf, lieber Leser. Innerhalb der Schleife, die in Zeile 18 beginnt, gibt es eine weitere verschachtelte Schleife, die in Zeile 22 beginnt. Innerhalb dieser geschachtelten Schleife findet in Zeile 24 eine Bedingungsprüfung statt. An dieser Stelle wird es interessant. Vielleicht möchten Sie später experimentieren, indem Sie die BREAK-Anweisung durch eine RETURN-Anweisung ersetzen, um zu beobachten, wie sich der Code verhält. Aber jetzt wollen wir uns erst einmal darauf konzentrieren, was passiert, wenn wir BREAK verwenden.
Es ist klar, dass hier eine Art von Zählung stattfindet. Aber wie wird sie kontrolliert? Das ist die Schlüsselfrage. Oft müssen wir bestimmte Werte verfolgen, aber die manuelle Analyse der Ausgabe mehrerer verschachtelter Schleifen kann mühsam sein. In vielen Fällen entwickeln wir einen mathematischen Ausdruck oder eine Formel, die definiert, wie die Berechnung durchgeführt werden soll. Sobald wir diese Formel haben, setzen wir sie in Form von Code um.
Dabei müssen wir auf unsere Fähigkeit vertrauen, mathematische Ausdrücke in funktionalen Code zu übersetzen. Wenn die Anzahl der zu verarbeitenden Werte oder die Art und Weise, wie sie erzeugt werden, besonders komplex oder umfangreich ist, können wir nicht jeden Wert einzeln analysieren. Stattdessen verwenden wir Stichproben - wir ermitteln die erwarteten Werte innerhalb eines bestimmten Bereichs und analysieren nur diesen Bereich. Aus diesem Grund ist es wichtig, jeden Befehl zu beherrschen und zu verstehen, wie jeder Vorgang funktioniert.
Wenn Sie zum Code zurückkehren, werden Sie feststellen, dass in Abbildung 04 die Zeile 28 nur in bestimmten Fällen gedruckt wird, obwohl die Bedingung in der Schleife in Zeile 22 nahelegt, dass sie häufiger ausgeführt werden sollte. Dies geschieht, weil die BREAK-Anweisung die innere Schleife abbricht, bevor die Bedingung das Ende anzeigt. In diesem speziellen Fall führt der Abbruch der inneren Schleife jedoch nicht zur Beendigung der äußeren Schleife. Aus diesem Grund sollten Sie auch versuchen, BREAK durch RETURN zu ersetzen, um zu sehen, wie sich dies auf die endgültige Ausgabe im Terminal auswirkt. Die Ergebnisse sind sehr unterschiedlich.
Wenn Sie den Ablauf der Ausführung verfolgen, werden Sie dieses Konzept leicht verstehen. Da wir den Ablauf der WHILE- und DO-WHILE-Schleifen sowie der IF-Anweisung bereits in früheren Artikeln erforscht haben, sollten Sie in der Lage sein, sie auch in diesem Zusammenhang zu visualisieren. Wir haben jedoch noch nicht gezeigt, wie die Ausführung einer BREAK-Anweisung abläuft. Dies wird im Folgenden veranschaulicht:
Abbildung 05
LOOP (Schleife) steht hier für jeden Befehl, der die Erstellung von Schleifen ermöglicht. Die BREAK-Anweisung wird jedoch so dargestellt, als ob sie frei im Code platziert wäre. An dieser Stelle müssen wir eine Klarstellung vornehmen. Wenn wir alle notwendigen Bedingungen für die korrekte Implementierung der BREAK-Anweisung einbeziehen würden, müssten wir hier den Ausführungsfluss der IF-Anweisung hinzufügen. Wenn die Bedingung innerhalb von IF als wahr bewertet wird, wird die BREAK-Anweisung ausgeführt, und der Ablauf folgt dem in der Abbildung dargestellten Pfad. Beachten Sie auch, dass die BREAK-Anweisung vor, innerhalb oder nach der Ausführung der Schleifenroutine platziert werden kann. In der Regel wird sie entweder am Anfang oder am Ende platziert. Wenn es in der Mitte erscheint, bedeutet dies in der Regel, dass die Übung in zwei Teile aufgeteilt wurde. Um den Ausführungsablauf zu vereinfachen, habe ich diese Art von Operation jedoch nicht in das Diagramm aufgenommen.
Ich glaube, Sie haben das Konzept jetzt verstanden. Beachten Sie jedoch eine wichtige Sache: Die BREAK-Anweisung ist auch mit einer anderen Art von Kontrollflussbefehl verbunden. Wir werden diese Diskussion für später aufheben und die Dinge Schritt für Schritt angehen.
Betrachten wir nun eine weitere Anweisung - die letzte, die innerhalb einer Schleife erscheinen kann. Im Gegensatz zu den bisher besprochenen Befehlen existiert diese nächste Anweisung jedoch nur innerhalb von Schleifen, sodass bei ihrer Verwendung besondere Vorsicht geboten ist.
Die Anweisung CONTINUE
CONTINUE ist von Natur aus riskant, wenn sie innerhalb einer Schleife verwendet wird, insbesondere bei WHILE- oder DO-WHILE-Schleifen. Dies liegt daran, dass bei der Verwendung dieser Anweisung nur allzu oft versehentlich Endlosschleifen entstehen. Auch wenn die FOR-Schleife, auf die später noch eingegangen wird, scheinbar widerstandsfähiger gegen eine Endlosschleife ist, kann es dennoch passieren. Dies ist in der Regel auf ein einfaches Versehen bei der Implementierung zurückzuführen, das die Verwendung des Befehls CONTINUE erforderlich macht. Bleiben Sie also wachsam und seien Sie besonders vorsichtig, wenn Sie diese Anweisung in irgendeinem Abschnitt Ihres Codes verwenden müssen oder ihr begegnen. Sie wird immer mit irgendeiner Form von Schleife verknüpft sein, aber besondere Aufmerksamkeit sollte man vor allem bei WHILE- und DO-WHILE-Schleifen walten lassen.
In Anbetracht der potenziellen Gefahr, dass diese Aussage missbraucht wird, sollten wir sie hier etwas anders angehen. Wir beginnen damit, den Ablauf der Ausführung zu verstehen, wenn diese Anweisung auftaucht. Hierzu wird auf das nachstehende Bild verwiesen.
Abbildung 06
Die gleichen Ratschläge, die wir für andere Anweisungen wie BREAK und RETURN gegeben haben, gelten auch hier. In diesem speziellen Fall ist der Ratschlag, BREAK oder RETURN als Routine innerhalb einer IF-Anweisung zu verwenden, jedoch noch wichtiger. Wie Sie in Abbildung 06 sehen können, wird nichts innerhalb der Schleifenroutine ausgeführt, wenn CONTINUE verwendet wird. Im Gegensatz zu anderen Anweisungen, die die Schleife beenden, bewirkt CONTINUE, dass der Kontrollfluss sofort zum Anfang der Schleife zurückkehrt.
Wenn es also keine Bedingung gibt, die dazu führt, dass der Schleifenausdruck als falsch ausgewertet wird, läuft die Schleife unweigerlich unendlich lange. Aus diesem Grund ist bei der Verwendung von CONTINUE äußerste Vorsicht geboten. In vielen Programmiersprachen ist die GOTO-Anweisung aus diesem Grund nicht implementiert oder wird nicht verwendet, da es zu solchen Problemen kommen kann. Bei richtiger Verwendung und im richtigen Kontext ist CONTINUE jedoch in vielen Situationen sehr nützlich. Aber seien Sie immer ruhig und sehr aufmerksam, wenn Sie es nutzen.
Um das potenzielle Risiko einer unvorsichtigen Implementierung der CONTINUE-Anweisung zu demonstrieren, erstellen wir einen Code, der nur aufgrund eines externen Ereignisses beendet wird. Hierfür verwenden wir den folgenden Code:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 07. 08. Procedure_Loop(); 09. 10. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 11. } 12. //+------------------------------------------------------------------+ 13. void Procedure_Loop(void) 14. { 15. char info = 10; 16. 17. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 18. 19. while ((info) && (!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)) && (!IsStopped())) 20. { 21. if (info) continue; 22. 23. info = info - 3; 24. 25. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 26. 27. if (info < -5) return; 28. } 29. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 30. } 31. //+------------------------------------------------------------------+
Code 07
Bevor wir erörtern, was in Code 07 geschieht, wollen wir zunächst das Ergebnis der Ausführung sehen. Da dieser Code in eine Endlosschleife gerät, während er auf das Eintreten eines Ereignisses wartet, wird kein statisches Bild verwendet. Stattdessen werden wir eine Animation verwenden, um zu zeigen, wie ich es geschafft habe, die Anwendung zu beenden. Sie können sich die Animation unten ansehen:
Animation 01
Nun, liebe Leserinnen und Leser, bedenken Sie Folgendes. Dies geschah nur, weil ich eine Möglichkeit implementiert habe, die Endlosschleife, die wir erzeugen, zu beenden. Ohne diese Implementierung würden wir dort auf unbestimmte Zeit festsitzen oder bis jemand die Anwendung gewaltsam aus MetaTrader 5 entfernt. In keiner anderen Situation würde die Anwendung beendet werden. In Anbetracht dieser Warnung und dieses Alarms wollen wir uns nun genauer ansehen, was im Code 07 geschieht.
Da dieser Code eine Variation der anderen Beispiele ist, die wir in diesem Artikel gesehen haben, können wir uns auf die Teile konzentrieren, die wirklich wichtig sind. Zunächst ist festzustellen, dass die Variable in Zeile 15 so deklariert ist, dass die WHILE-Schleife laufen kann, wie in Zeile 19 zu sehen ist, wo die Schleife beginnt. Die nächste wichtige Beobachtung ist, dass wir drei Bedingungen haben, um die Schleife zu verlassen. Die erste ist, wenn die Variable „info“ falsch wird. Die zweite ist, wenn die ESC-Taste gedrückt wird. Der dritte Punkt ist die Aufforderung, das Skript zu beenden. Ohne die dritte Bedingung würde MetaTrader 5 versuchen, das Skript zu schließen, bis es erfolgreich ist. In diesem Fall wird im Terminal eine andere Meldung angezeigt, wie in der folgenden Abbildung zu sehen ist.
Abbildung 07
Dies wäre der ungünstigste Fall für die Beendigung des Codes. Es ist jedoch wichtig, noch einmal zu betonen, dass diese Meldung in Abbildung 07 nur erscheinen würde, wenn die dritte Bedingung (zu sehen in Zeile 19 in Code 07) fehlen würde. Da sie vorhanden ist, wäre das Ergebnis dasselbe wie in der Animation, was den Eindruck erweckt, dass der Code ordnungsgemäß beendet wurde.
Der entscheidende Punkt ist jedoch Zeile 21. Beachten Sie, dass trotz des Vorhandenseins der IF-Anweisung, die prüft, ob sich in der Schleife etwas ändern sollte, die Tatsache, dass die Routine innerhalb der IF-Anweisung nur aus einer CONTINUE-Anweisung besteht, die gesamte Schleife in einen unendlichen Zyklus zwingt. Dies liegt daran, dass kein anderer Teil der WHILE-Schleifenroutine ausgeführt wird.
Kleine Änderungen am gleichen Code können das Risiko jedoch verringern. Auch wenn die Zeilen 23 bis 27 nie ausgeführt werden, könnte man beispielsweise den Code 07 in einen Code 08 ändern, wie unten gezeigt:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 07. 08. Procedure_Loop(); 09. 10. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 11. } 12. //+------------------------------------------------------------------+ 13. void Procedure_Loop(void) 14. { 15. char info = 10; 16. 17. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 18. 19. while (((info = info - 3) > 0) && (!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)) && (!IsStopped())) 20. { 21. if (info) continue; 22. 23. info = info - 3; 24. 25. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 26. 27. if (info < -5) return; 28. } 29. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 30. } 31. //+------------------------------------------------------------------+
Code 08
Wenn wir Code 08 ausführen, sehen wir im Terminal eine andere Ausgabe als in Animation 01. Er ist unten aufgeführt:
Abbildung 08
Wie Sie sehen können, haben wir jetzt verschiedene Werte für die Variable info. Aber wie ist das passiert? Nun, liebe Leserin, lieber Leser, es liegt an einer kleinen Änderung im Code - und zwar in Zeile 19, innerhalb der ersten Bedingung im Ausdruck der WHILE-Schleife. Beachten Sie, dass wir in diesem speziellen Fall keine Endlosschleife mehr erzeugen. Dadurch wird jedoch der Rest der Schleifenroutine nicht ausführbar. Der Grund dafür ist, dass sich die Prozedurschleife wie im folgenden Fragment dargestellt zusammenfassen lässt:
. . . 12//+------------------------------------------------------------------+ 13void Procedure_Loop(void) 14{ 15 char info = 10; 16 17 Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 18 19 while (((info = info - 3) > 0) && (!TerminalInfoInteger(TERMINAL_KEYSTATE_ESCAPE)) && (!IsStopped())); 20 21 Print(__FUNCTION__, " 29 : Info (", info, ")"); 22} 23//+------------------------------------------------------------------+
Fragment 01
Der Grund dafür ist das Vorhandensein des CONTINUE-Befehls in Zeile 21 innerhalb einer IF-Anweisung, der bewirkt, dass er jedes Mal innerhalb der Schleife ausgeführt wird. Das war interessant. Was aber, wenn wir aus irgendeinem Grund statt der WHILE-Schleife die DO WHILE-Schleife verwendet hätten? Was würde dann passieren? Nun, liebe Leserinnen und Leser, dann hätten wir auf jeden Fall ein sehr interessantes Szenario, eines, das viele faszinieren wird. Je nachdem, wie Sie Ihren Code implementieren, kann er auf sehr komplexe Weise funktionieren.
Lassen Sie uns also mit einer sehr einfachen Version experimentieren, um zu zeigen, was passiert, wenn wir den Befehl CONTINUE in einer DO WHILE-Schleife verwenden. Dieses Beispiel ist in Code 09 unten zu sehen:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 07. 08. Procedure_Loop(); 09. 10. Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); 11. } 12. //+------------------------------------------------------------------+ 13. void Procedure_Loop(void) 14. { 15. char info = 10; 16. ulong counter = 0; 17. 18. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 19. 20. do 21. { 22. Sleep(500); 23. 24. Print(__FUNCTION__, " ", __LINE__, " : Counter (", counter = counter + 1, ")"); 25. 26. if (info) continue; 27. 28. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 29. 30. }while ((info = info - 2) > 0); 31. 32. Print(__FUNCTION__, " ", __LINE__, " : Info (", info, ")"); 33. } 34. //+------------------------------------------------------------------+
Code 09
Obwohl man zunächst denken könnte, dass hier eine Endlosschleife entsteht, wird dies aufgrund eines kleinen Details, das in den vorherigen Codebeispielen in diesem Abschnitt gezeigt wurde, nicht passieren. Viele Programmierer, die weniger Erfahrung mit DO WHILE-Schleifen haben, könnten jedoch annehmen, dass die Schleife nach der Ausführung von Zeile 26 zu Zeile 20 zurückkehrt. Diese Art des Denkens resultiert aus einem mangelnden Verständnis der Funktionsweise des Ausführungsflusses in der DO WHILE-Schleife. Wir haben den Ablauf der Ausführung im vorherigen Artikel behandelt. Daher werde ich hier nicht weiter ins Detail gehen. Eine Tatsache wird jedoch bewiesen, wenn Sie diesen Code studieren: Zeile 28 wird in dem, was in Code 09 zu sehen ist, NIEMALS ausgeführt. Das liegt an Zeile 26 und daran, wie der Ausführungsfluss in der DO WHILE-Schleife funktioniert.
Um dies zu veranschaulichen, habe ich statt eines Bildes lieber eine Animation verwendet. Meiner Meinung nach ist dieser Ansatz für den Unterricht viel effektiver und ermöglicht es Ihnen, über die Gründe für das Verhalten des Code 09 nachzudenken. Sie können sich die Animation unten ansehen. Schauen Sie genau hin und versuchen Sie zu verstehen, wie und warum das so ist.
Animation 02
Abschließende Überlegungen
In diesem Artikel habe ich mich bemüht, so einfach und klar wie möglich zu erklären, wie man mit den Anweisungen RETURN, BREAK und CONTINUE arbeitet, wenn sie in Schleifen verwendet werden. Obwohl sich der größte Teil des Inhalts auf die Verwendung von WHILE- und DO WHILE-Schleifen konzentriert, gelten die hier demonstrierten Prinzipien auch für die FOR-Schleife, die später erläutert wird.
Es ist jedoch unerlässlich, dass Sie, mein lieber und geschätzter Leser, sich die Zeit nehmen, das in diesem Artikel Behandelte zu studieren und zu üben. Auf dem Weg zu fortgeschritteneren Programmierebenen wird ein gründliches Verständnis dieser Konzepte erforderlich sein. Die hier besprochenen Themen und Konzepte werden nicht wieder aufgegriffen, wenn die Dinge komplexer werden.
Nutzen Sie daher die im Anhang enthaltenen Code-Beispiele. Studieren Sie sie sorgfältig und achten Sie darauf, wie diese drei Befehle (RETURN, BREAK und CONTINUE) den Codefluss während der Ausführung Ihrer Anwendungen beeinflussen. Das heißt, wir sehen uns im nächsten Artikel wieder. Bis bald!
Übersetzt aus dem Portugiesischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/pt/articles/15376





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.