English Русский 中文 Español 日本語 Português
preview
Von der Grundstufe bis zur Mittelstufe: IF ELSE

Von der Grundstufe bis zur Mittelstufe: IF ELSE

MetaTrader 5Beispiele |
73 0
CODE X
CODE X

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: Übergabe als Wert oder Referenz“ haben wir eine praktische und objektive Erklärung der Konzepte, Risiken und Vorsichtsmaßnahmen gegeben, die Sie bei der Übertragung von Daten zwischen verschiedenen Programmen beachten sollten.

Auf der Grundlage dieser Diskussion sowie der zuvor behandelten Inhalte können wir nun damit beginnen, fortgeschrittenere Themen zu untersuchen. Das liegt daran, dass wir beim Programmieren selbst nicht nur mit mathematischen Ausdrücken arbeiten. Dies wäre nicht nur eine enorme Verschwendung der Rechenleistung und der Faktorisierungsmöglichkeiten, die ein Computer bietet, sondern würde auch die Möglichkeiten dessen, was wir wirklich erreichen können, einschränken.

Voraussetzung für das Verständnis dessen, was im Folgenden erläutert wird, ist daher eine gute Kenntnis der in den vorangegangenen Artikeln vorgestellten Konzepte. Wenn Sie sich irgendwann einmal nicht mehr sicher sind, warum etwas passiert, lesen Sie diese Artikel sorgfältig durch. Vermeiden Sie es, den Lernprozess zu überstürzen, und befolgen Sie die Schritte, die Ihnen vorgestellt werden.

Bevor wir jedoch mit dem ersten von mehreren Themen beginnen, die in diesem und zukünftigen Artikeln behandelt werden, ist es notwendig, einen Begriff zu erklären, der bei der Erörterung von Erklärungen häufig vorkommen wird. Kommen wir also zum ersten Thema dieses Artikels.


Definition einer Routine

Jede Programmiersprache ist durch bestimmte Begriffe definiert. Um ein klares Verständnis und eine korrekte Interpretation der gegebenen Erläuterungen zu gewährleisten, müssen wir zunächst einen wesentlichen Begriff definieren.


Abbildung 01

Ein Codeblock, wie in Abbildung 01 dargestellt, beginnt mit einer öffnenden und endet mit einer schließenden geschweiften Klammer. Alles innerhalb dieses Blocks sollte als eine Einheit betrachtet werden. Unabhängig von der Anzahl der Zeilen oder dem, was zwischen den öffnenden und schließenden Klammern steht, sollten Sie den Text als eine zusammenhängende Einheit betrachten. Diese Einheit bezeichnen wir als Routine.

Also, passen Sie gut auf! Eine Routine kann ein Codeblock sein, der der folgenden Abbildung entspricht.

   {
      ExtAOBuffer[i] = ExtFastBuffer[i] - ExtSlowBuffer[i];

      double sumAO = 0.0;

      for(int j = 0; j < FAST_PERIOD; j++)
         sumAO+=ExtAOBuffer[i - j];

      ExtSMABuffer[i] = sumAO / FAST_PERIOD;
      ExtACBuffer[i] = ExtAOBuffer[i] - ExtSMABuffer[i];

      if ( ExtACBuffer[i] >= ExtACBuffer[i - 1])
         ExtColorBuffer[i] = 0.0; // set color Green
      else
         ExtColorBuffer[i] = 1.0; // set color Red
   }

Es kann auch ein beliebiger Ausdruck sein, wie unten angegeben.

ExtACBuffer[i] = ExtAOBuffer[i] - ExtSMABuffer[i];

Auch ein Aufruf zur Ausführung einer Funktion oder Prozedur würde in diese Kategorie fallen. Mit anderen Worten: Alle diese Elemente sind das, was wir als Routine bezeichnen werden. Wann immer wir also erwähnen, dass eine Routine ausgeführt wird, sollten Sie verstehen, dass sich dies auf alles beziehen kann, von einem Funktions- oder Prozeduraufruf bis hin zu einem ganzen Codeblock. Dieser Block kann mehrere Ausdrücke, Prozedur- oder Funktionsaufrufe und sogar andere Routinen enthalten, die in der ursprünglichen Routine verschachtelt sind. Kurzum: Erweitern Sie Ihren Horizont bis zur Unendlichkeit und darüber hinaus! Nun, da wir diesen Begriff definiert haben, können wir beginnen.


Die IF-Anweisung: Die ultimative Kontrolle

Bevor wir eintauchen, möchte ich eine kleine Warnung aussprechen. Auch wenn die Programmieranweisungen in englischer Sprache abgefasst sein müssen, sind Sie, lieber Leser und zukünftiger Programmierer, nicht unbedingt verpflichtet, englischsprachige Anweisungen zu verwenden. Es gibt Möglichkeiten, dies zu umgehen. Aber nehmen wir einmal an, dass Sie gerade erst mit dem Programmieren anfangen. Kümmern Sie sich nicht zu sehr um die spezifische Terminologie, sondern konzentrieren Sie sich darauf, das Konzept zu verstehen. Die Beherrschung von Konzepten ist viel wertvoller als das bloße Auswendiglernen von Anweisungslisten oder Syntaxregeln.

Aber warum habe ich die IF-Anweisung im Titel dieses Abschnitts als „ultimative Kontrolle“ bezeichnet? Und warum beginne ich mit IF? Könnten wir nicht mit einer anderen Aussage beginnen? Nun, ja, das könnten wir. Wenn Sie jedoch wirklich verstehen, wie die IF-Anweisung funktioniert, und das anwenden, was in den vorangegangenen Artikeln erklärt wurde, werden Sie in der Lage sein, fast alles in der Programmierung zu tun. Ich sage „fast“, weil es noch ein weiteres wichtiges Konzept gibt, das wir später behandeln werden. Dieses Konzept ist jedoch viel leichter zu verstehen, wenn Sie zunächst eine solide Grundlage mit einfacheren Befehlen schaffen, die wir in Kürze untersuchen werden. Wenn Sie die notwendigen Konzepte beherrschen und sie richtig anwenden, werden Sie buchstäblich in der Lage sein, jedes beliebige Programm nur mit Hilfe der IF-Anweisungen, anderer Operatoren und Variablen zu erstellen. Das war's. Mehr nicht. Klingt unmöglich, nicht wahr? Aber ich versichere Ihnen, es ist wahr. Und mit der Zeit werden Sie sehen, dass dies wirklich so ist.

Beginnen wir damit, einen grundlegenden Aspekt der IF-Anweisung zu verstehen. IF bedeutet wörtlich „wenn“. Wann immer Sie auf diese Anweisung stoßen, lesen Sie sie genau als IF. Dadurch wird es viel einfacher, die Bedeutung zu erfassen.

Bei ihrer Ausführung wertet die IF-Anweisung eine Bedingung aus. Diese Bedingung muss immer entweder als wahr oder falsch verstanden werden. IMMER. Es spielt keine Rolle, was getestet oder analysiert wird. Ob die IF-Routine die darin enthaltene Routine ausführt, hängt davon ab, ob die Testbedingung als wahr oder falsch ausgewertet wird. Wie in den vorangegangenen Artikeln erläutert, gilt eine Bedingung als falsch, wenn ihr Wert gleich Null ist, und als wahr, wenn ihr Wert einen anderen Wert als Null hat. Im Gegensatz zu dem, was viele glauben, erfordert die IF-Anweisung nicht unbedingt Vergleichsoperatoren wie „größer als“, „kleiner als“ oder „gleich“. Sie muss nur feststellen, ob die Bedingung wahr oder falsch ist. Mehr nicht.

Um dieses Konzept leichter verständlich zu machen, wollen wir uns ein einfaches Beispiel aus der Praxis ansehen.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char info = 10;
07. 
08.     Print(__FUNCTION__, " : #1 => ", info);
09. 
10.     if (info)
11.         Print("True condition...");
12. 
13.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
14. }
15. //+------------------------------------------------------------------+

Code 01

Wenn Sie diesen Code ausführen, werden Sie in MetaTrader 5 etwas Ähnliches sehen wie hier:


Abbildung 02

Hier wenden wir genau das an, was zuvor erklärt wurde. In Zeile sechs definieren wir eine Variable. Unmittelbar danach, in Zeile acht, geben wir eine Meldung aus, um den aktuellen Stand unserer Daten zu analysieren. In Zeile zehn führen wir jedoch eine Kontrollflussanweisung ein: die IF-Anweisung. Passen Sie gut auf, lieber Leser. Wenn „info“ gleich true ist, wird die Routine innerhalb der IF-Anweisung ausgeführt. Wenn „info“ falsch ist, wird die Routine innerhalb der IF-Anweisung nicht ausgeführt, und die Ausführung wird mit der nächsten Routine im Code fortgesetzt. Auf diese Weise können wir den Fluss der Ausführung unseres Codes kontrollieren und steuern. Die nächste Routine befindet sich in diesem Fall in Zeile 13.

Da der Wert von „info“ von Null verschieden ist, wird die Routine innerhalb der IF-Anweisung ausgeführt. Als Ergebnis erhalten wir die in Abbildung 02 gezeigte Ausgabe. Es gibt einige wichtige Überlegungen dazu, wie Sie diese Erklärung verfassen sollten. Einige davon sind obligatorisch, andere sind optional. Die grundlegende Syntax der IF-Anweisung lautet jedoch wie folgt:


Abbildung 03

Daran können Sie deutlich erkennen, wie die Anweisung ausgeführt wird. Die Syntax ist einfach und leicht zu verstehen.

Was aber, wenn wir die Routine innerhalb der IF-Anweisung nicht ausführen wollen, wenn die Bedingung wahr ist, sondern wenn sie falsch ist? Ist das möglich? Das ist eine ausgezeichnete Frage! Und genau das ist der Punkt, an dem viele Programmieranfänger Schwierigkeiten haben, manchmal bis zur Frustration. Dies geschieht, weil sie das zugrunde liegende Konzept der Aussage nicht verstehen. Ich möchte noch einmal betonen: Die IF-Anweisung führt die darin enthaltene Routine nur aus wenn und nur wenn die Bedingung wahr ist. Andernfalls wird die Routine innerhalb der IF-Anweisung nicht ausgeführt. „Aber warte! Ich habe Code gesehen, bei dem die Routine innerhalb der IF-Anweisung ausgeführt wurde, selbst wenn der Wert falsch war. Ich glaube, Sie wissen nicht, wovon Sie reden.“ Also gut, lassen Sie uns nicht darüber streiten. Lassen Sie uns stattdessen die Probe aufs Exempel machen. Wir werden ein einfaches Programm erstellen, um zu überprüfen, ob dies tatsächlich geschehen kann. Zu diesem Zweck erzwingen wir absichtlich eine Bedingung, bei der der Ausdruck in der IF-Anweisung immer als wahr bewertet wird. Der Code dafür ist unten abgebildet. Wie ist das möglich? Sie haben vielleicht schon Code gesehen, bei dem die Routine innerhalb der IF-Anweisung auch dann ausgeführt wurde, wenn der Wert falsch war. Man könnte meinen, ich wüsste nicht, wovon ich rede.

Lassen Sie uns nicht darüber streiten. Stattdessen machen wir Folgendes: Wir erstellen ein einfaches Programm, um zu überprüfen, ob dies tatsächlich geschehen kann. Zu diesem Zweck erzwingen wir absichtlich eine Bedingung, bei der der Ausdruck in der IF-Anweisung immer wahr ist. Der Code dafür 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.     if (true)
09.         Print("True condition...");
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. }
13. //+------------------------------------------------------------------+

Code 02

Jetzt können Sie sehen, dass der Test in Zeile 8 IMMER wahr sein wird. Daher wird Zeile 9 IMMER ausgeführt, unabhängig davon, wie oft der Code ausgeführt wird. Die neunte Zeile wird IMMER ausgeführt. Das Ergebnis ist unten zu sehen:


Abbildung 04

Es wurde bereits erwähnt, dass Sie die IF-Anweisung gesehen haben, um eine Routine auszuführen, wenn ein Ausdruck falsch war. Okay, machen wir den Ausdruck falsch und schauen, was passiert. Dies wird im folgenden Code gezeigt: 

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     if (false)
09.         Print("True condition...");
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. }
13. //+------------------------------------------------------------------+

Code 03

Beachten Sie, dass die einzige Änderung, die ich vorgenommen habe, der Ausdruck innerhalb der IF-Anweisung in Zeile acht ist. Wenn der Code jedoch ausgeführt wird, sieht die Ausgabe wie in der folgenden Abbildung aus.


Abbildung 05

Moment... wo ist die andere Zeile, die in Abbildung 04 erschien? Wo ist es hin? Nun, liebe Leserin, lieber Leser, sie fehlt in Abbildung 05, weil sie nie ausgeführt wurde. Dies geschah, weil der in Zeile acht getestete Ausdruck falsch ist. Und sie wird immer falsch sein. Da die Bedingung falsch ist, wird die Routine innerhalb der IF-Anweisung niemals ausgeführt. Allerdings gibt es hier ein kleines, aber entscheidendes Detail, das viele übersehen. Vielleicht haben Sie deshalb gedacht, dass eine falsche Bedingung die Routine innerhalb der IF-Anweisung trotzdem auslösen könnte. Zu diesem Missverständnis kommt es in der Regel, wenn das Ergebnis eines Ausdrucks auf irgendeine Weise umgedreht wird, d. h. was vorher falsch war, wird wahr und umgekehrt.

Achten Sie sehr genau darauf. Die Art und Weise, wie Sie Ihren Code schreiben, kann bestimmen, ob der Endwert wahr oder falsch ist. Diese Art von Problemen frustriert Programmierer häufig, da ein Ausdruck auf den ersten Blick korrekt erscheinen mag. Aufgrund eines internen Faktors, der in der Regel mit dem Vorrang von Operatoren zusammenhängt, kann der Ausdruck jedoch ein unerwartetes Ergebnis liefern. Es handelt sich nicht um einen mathematischen Fehler, sondern um einen logischen Fehler im Zusammenhang mit der IF-Anweisung. Dies ist ein so wichtiges Thema, dass es einen eigenen Artikel verdient. Da es jedoch zusätzliche Anweisungen und Operatoren erfordert, um sie vollständig zu verstehen, werde ich diese Diskussion vorerst zurückstellen.

In der Zwischenzeit können Sie dieses Thema in der Dokumentation nachlesen: Prioritaeten und Operationsordnung.

Auch ohne in diese Regeln einzutauchen, können wir eine einfache Änderung des Codes vornehmen. Diese Änderung ermöglicht die Ausführung der Routine in der IF-Anweisung in Zeile 8, auch wenn der Ausdruck falsch zu sein scheint. Dies wird erreicht, indem der Code wie unten gezeigt geändert wird:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     if (~false)
09.         Print("True condition...");
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. }
13. //+------------------------------------------------------------------+

Code 04

Durch diese fast unmerkliche Änderung erhalten wir das unten dargestellte Ergebnis:


Abbildung 06

Auf den ersten Blick, wenn man den Code 04 unbedacht betrachtet, könnte man annehmen, dass der getestete Ausdruck falsch ist. Beachten Sie jedoch das Symbol, das dem reservierten Wort false vorangestellt ist. In den meisten Fällen wird das Ausrufezeichen verwendet. Aber es gibt viele andere Möglichkeiten, dies zu erreichen. Wenn Sie zum Beispiel wissen, dass der Test immer prüft, ob der Wert gleich Null ist oder nicht, könnten Sie etwas wie das Folgende schreiben:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
07. 
08.     if (false | true)
09.         Print("A very crazy condition always true ...");
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. }
13. //+------------------------------------------------------------------+

Code 05

Nach der Ausführung dieses Codes sehen Sie die unten angezeigte Ausgabe:


Abbildung 07

Ich könnte noch viele weitere Varianten aufzählen, aber nichts ist besser, als selbst zu experimentieren und dabei genau zu verstehen, was passiert. Damit haben wir die IF-Anweisung als erledigt betrachtet und gehen zur nächsten Kontrollstruktur über, die es ohne IF gar nicht geben würde. Ich meine die ELSE-Anweisung. Wir werden dies im nächsten Abschnitt untersuchen.


ELSE-Anweisung. Sie steht nicht allein

Ein häufiger Fehler von Anfängern, der möglicherweise auf die Art des verwendeten Lernmaterials zurückzuführen ist, besteht darin, dass sie versuchen, die ELSE-Anweisung isoliert zu verwenden. Die ELSE-Anweisung, die mit „sonst“ erklärt werden könnte, muss immer mit einer anderen Anweisung gekoppelt werden. Die Anweisung, die ELSE vorausgeht, hängt von der Programmiersprache ab. Viele gehen davon aus, dass ELSE immer mit einer IF-Anweisung verbunden ist, aber in SQL kann ELSE beispielsweise mit einer CASE-Anweisung verbunden sein. Das mag merkwürdig erscheinen, aber so ist die Sprache nun einmal konzipiert. Gehen Sie also nicht davon aus, dass die Kenntnis einer Programmiersprache Sie automatisch für die Programmierung in einer anderen qualifiziert. Einige Konzepte sind zwar übertragbar, aber jede Sprache hat ihre eigenen Nuancen, die es zu verstehen gilt.

Wenn Sie die IF-Anweisung verstanden haben, wird es viel einfacher sein, ELSE zu verstehen. Wird der ELSE-Block neben IF verwendet, wird er nur ausgeführt, wenn die IF-Bedingung falsch ist. Das ist im Grunde alles, was es zu tun gibt. Viel mehr gibt es dazu nicht zu sagen.

Werfen wir jedoch einen Blick auf den Ablauf der Ausführung, der die Dinge noch deutlicher macht. Das Flussdiagramm ist unten abgebildet:


Abbildung 08

Bei der Betrachtung von Abbildung 08 werden Sie feststellen, dass eine ELSE-Anweisung immer mit einer IF-Anweisung verknüpft ist. Auch wenn dieses Konzept auf den ersten Blick einfach erscheint, ist es in der Praxis nicht immer so einfach. Bei der Verwendung einer IF-Anweisung mit einem ELSE-Block müssen Sie, lieber Leser, einige Vorsichtsmaßnahmen treffen. Wir werden diese später in diesem Artikel behandeln. Aber warum machen Sie sich nicht vorher einen Spaß daraus, die vorherigen Codebeispiele so zu ändern, dass sie ELSE-Anweisungen enthalten? Ich werde nicht jedes Beispiel ändern, denn das wäre angesichts der Einfachheit dessen, was wir bis jetzt behandelt haben, unnötig. Stattdessen nehmen wir einen der Codes und ändern ihn durch Hinzufügen eines ELSE-Blocks.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     int info = 10;
07. 
08.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #1 => ", info);
09. 
10.     if (info)
11.         Procedure(info);
12.     else
13.         Print("Variable info is equal to zero...");
14. 
15.     if (info)
16.         Print("True condition...");
17.     else
18.         Print("False condition...");
19.     
20.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway... #2 => ", info);
21. }
22. //+------------------------------------------------------------------+
23. void Procedure(int & arg1)
24. {
25.     Print(__FUNCTION__, " ", __LINE__, " #1 => ", arg1);
26.     arg1 = 0;
27.     Print(__FUNCTION__, " ", __LINE__, " #1 => ", arg1);
28. }
29. //+------------------------------------------------------------------+

Code 06

Der Code 06, der auf den ersten Blick kompliziert erscheint, ist in Wirklichkeit viel einfacher und klarer, als es auf den ersten Blick scheinen mag. Wenn wir den Code 06 ausführen, erhalten wir das unten dargestellte Ergebnis:


Abbildung 09

Wenn man sich Image 09 ansieht, könnte man meinen: „Das sind eine Menge Informationen, die ich verarbeiten muss!“ Aber genau deshalb sollten Sie noch mehr motiviert sein, sich zu konzentrieren und tiefer einzutauchen. Gehen wir Schritt für Schritt vor, um besser zu verstehen, wie man die IF-ELSE-Kombination effektiv einsetzt.

Zunächst erstellen wir in Zeile 6 eine Variable, die im gesamten Code verwendet wird. In der achten Zeile wird die erste Ausgabezeile in Abbildung 09 gedruckt. Wenn Sie die IF-Anweisung verstanden haben, wissen Sie bereits, was in Zeile 10 passieren wird. An diesem Punkt können wir die Prozedurroutine ausführen oder auch nicht. Um zu verstehen, was hier vor sich geht, müssen Sie verstehen, was in früheren Artikeln erklärt wurde, in denen wir über Variablen gesprochen haben. Schließlich erreicht die Ausführung Zeile 15, wo eine von zwei Routinen ausgeführt werden kann. In beiden Fällen wird eine neue Nachricht auf dem Terminal ausgegeben. Schließlich folgt Zeile 20, die die letzte im Terminal sichtbare Meldung ausgibt.

Dieser Code 06 wird beigefügt, damit Sie mit kleinen Änderungen experimentieren können. Hier sind einige Vorschläge zur Optimierung des Codes. Sie können den Wert der Variablen in Zeile 6 ändern, sodass der Test in Zeile 10 zu einer anderen Routine führt. Führen Sie den Code nach dieser Änderung aus, um sein Verhalten zu verstehen. Sie können dann die WENN-Bedingungen ändern, um zu bestimmen, wie die Meldungen gedruckt werden. Passen Sie die Bedingungen innerhalb der Prozedurroutine an, damit sich die IF-Anweisung in Zeile 15 anders verhält. Beobachten Sie jedes Mal, wenn Sie eine Änderung vornehmen, das Ergebnis und analysieren Sie, warum es sich so verhält, wie es sich verhält. Diese Übung wird Ihnen helfen, ein gutes Verständnis für die IF-Anweisung zu entwickeln. Dies ist entscheidend für das Verständnis der Kontrollstrukturen, die in späteren Artikeln behandelt werden.

Allerdings gibt es ein kleines Problem bei der Verwendung der IF ELSE-Kombination. Um dieses Problem zu lösen, sollten wir mit einem neuen Thema beginnen.


Das Verschachtelungsproblem

Wenn die IF-ELSE-Kombination ausgiebig verwendet wird, tritt häufig ein Verschachtelungsproblem auf. Sie tritt auf, wenn mehrere IF-ELSE-Blöcke ineinander eingebettet sind, wodurch eine Kaskade von Bedingungen entsteht. Dieses Problem tritt jedoch nicht auf, wenn nur IF-Anweisungen verschachtelt werden, sondern vor allem, wenn ELSE eingeführt wird. Erfahrene Programmierer vermeiden jedoch auch eine übermäßige Verschachtelung von IF-Anweisungen, da dies im Allgemeinen zu unlesbarem Code führt. Dieser Entwurf ist nicht sehr sinnvoll.

Um Ihnen zu verdeutlichen, was ich mit Verschachtelung und Kaskadierung meine, betrachten Sie das folgende Beispiel:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if (c1)
14.         if (c2)
15.             if (c3)
16.                 if (c4)
17.                     Print("True condition...");
18.     
19.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
20. }
21. //+------------------------------------------------------------------+

Code 07

Hier ist ein typisches Beispiel für verschachtelte IF-Anweisungen. Sie fragen sich vielleicht: „Was ist falsch daran, so zu kodieren?“ Technisch gesehen, nichts. Erfahrene Programmierer schreiben ihren Code jedoch selten auf diese Weise. Stattdessen werden sie in der Regel mit logischen Operatoren umgeschrieben, wodurch eine funktional gleichwertige, aber besser lesbare Version entsteht. Eine mögliche Alternative zu Code 07 ist unten dargestellt:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if ((c1) && (c2) && (c3) && (c4))
14.         Print("True condition...");
15.     
16.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
17. }
18. //+------------------------------------------------------------------+

Code 08

Beachten Sie, dass die Ausgabe von Code 07 und Code 08 identisch sein wird. In Code 08 wurden jedoch die verschachtelten IF-Anweisungen aus Code 07 durch eine Kette von logischen Operationen ersetzt. In diesem Fall verwenden wir AND-Verknüpfungen. Jede andere Art von Operation verändert das Verhalten von Code 08 und führt dazu, dass er nicht das gleiche Ergebnis wie Code 07 liefert. Wenn Sie sich einmal nicht sicher sind, ob sich Ihr Code wie erwartet verhält, versuchen Sie, ihn in einem anderen Format zu schreiben, um Klarheit zu schaffen.

Das Problem der Verschachtelung tritt jedoch nicht nur bei Kaskaden von IF-Anweisungen auf. Sie ist besonders häufig in der Kombination IF und ELSE zu finden. Doch wie kommt es zu einem solchen Problem? Ich verstehe das immer noch nicht ganz. Um dies zu verstehen, werden wir etwas Ähnliches wie Code 07 verwenden, aber eine ELSE-Anweisung hinzufügen. Der resultierende Code ist unten dargestellt:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if (c1)
14.         if (c2)
15.             if (c3)
16.                 if (c4)
17.                     Print("True condition...");
18.         else
19.             Print("False condition...");
20.     
21.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
22. }
23. //+------------------------------------------------------------------+

Code 09

Auf den ersten Blick sieht der Code 09 dem Code 07 recht ähnlich. Hier im Code 09 haben wir jedoch ein Problem, und zwar ein großes. Wenn Sie das Ausmaß des Problems noch nicht erkannt haben, dann brauchen Sie unbedingt diese Artikel, um besser zu verstehen, wie Sie Ihre Programme aufbauen können.

Das Problem ist hier genau das ELSE, das in Zeile 18 steht. Lassen Sie mich Sie fragen: Zu welcher IF-Anweisung gehört dieses ELSE?

Aufgrund der Einrückung könnte man annehmen, dass das ELSE in Zeile 18 mit dem IF in Zeile 14 verbunden ist. Einige Programmiersprachen interpretieren es auf diese Weise, viele jedoch nicht. In der Realität wird die Einrückung in den allermeisten Fällen nicht als Teil des funktionalen Codes verwendet, sondern als Mittel, um ihn zu organisieren und lesbarer zu machen.

In MQL5 hat die Einrückung keinen Einfluss auf die Codeausführung; sie macht den Code nur besser lesbar. Der ELSE-Code in Zeile 18 ist in seiner jetzigen Form mit dem IF in Zeile 16 verknüpft.

Um dieses Problem zu lösen, ohne es zu kompliziert zu machen, und um zu erklären, wie man es beheben kann, werde ich zwei mögliche Lösungen aufzeigen. Eine davon wird von den meisten Programmierern bevorzugt, während die andere nur von wenigen verwendet wird. Beginnen wir mit der ersten, der Lieblingsvariante der meisten Programmierer. Diese Lösung besteht darin, den Code in Blöcke aufzuteilen, was dem Compiler klar macht, dass wir genau das tun wollen. Außerdem wird das Programm dadurch besser lesbar und verständlich. Diese Lösung ist unten dargestellt:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if (c1)
14.         if (c2)
15.         {
16.             if (c3)
17.                 if (c4)
18.                     Print("True condition...");
19.         }
20.         else
21.             Print("False condition...");
22.     
23.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
24. }
25. //+------------------------------------------------------------------+

Code 10

Eigentlich ist dies eine großartige Lösung. Beachten Sie, dass wir in Zeile 14 ein IF haben, das wir mit einem ELSE verknüpfen wollen. Um sicherzustellen, dass das Unterprogramm, das ausgeführt wird, wenn der Ausdruck in Zeile 14 IF wahr ist, korrekt definiert ist, platzieren wir es innerhalb eines Blocks. Da wir die gesamte IF-Sequenz verschachtelt haben, ist der Block, der in Zeile 15 beginnt und in Zeile 19 endet, eigentlich ein Unterprogramm, das in der IF-Sequenz in Zeile 14 ausgeführt werden sollte. Dieser Block kann sogar in einer Funktion oder Prozedur außerhalb des OnStart-Blocks platziert werden.

Es ist sehr wichtig, lieber Leser, dass Sie dies verstehen. Wenn die IF-Anweisung in Zeile 14 den Wert false ergibt, springt das Programm direkt zur ELSE-Anweisung, um das darin enthaltene Unterprogramm auszuführen. Beachten Sie, dass das auszuführende Unterprogramm ein beliebiges Programm sein kann. Daher ist es wichtig, die Anweisung zu verstehen und nicht nur die Syntax oder den Programmierstil auswendig zu lernen.

Bitte beachten Sie diese Tatsache. Wenn Sie die IF-Anweisung wirklich verstehen und wissen, wie man sie mit der ELSE-Anweisung kombiniert, können Sie eine andere Lösung für Code 09 verwenden. Diese Art von Lösung hat sich jedoch nicht durchgesetzt, da sie in vielen Fällen den Code nicht wirklich verständlich macht. Da wir aber mit didaktischem Material arbeiten und erklären, wie wir vorgehen sollen, können wir das ELSE in Zeile 18 mit dem IF in Zeile 14 verbinden. Dazu werden einfach weitere ELSE-Anweisungen mit anderen IF-Anweisungen verkettet, wie unten dargestellt:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char c1 = 10,
07.          c2 = 0,
08.          c3 = -6,
09.          c4 = 3;
10. 
11.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
12. 
13.     if (c1)
14.         if (c2)
15.             if (c3)
16.                 if (c4)
17.                     Print("True condition...");
18.                 else;
19.             else;
20.         else
21.             Print("False condition...");
22.     
23.     Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
24. }
25. //+------------------------------------------------------------------+

Code 11

Beachten Sie, dass in Code 11 die Verbindung zwischen dem IF in Zeile 14 und dem ELSE, das sich jetzt in Zeile 20 befindet, nicht so einfach und klar ist. Um dies zu verstehen, müssen Sie den Code sorgfältig analysieren. Die Ausführung von Code 10 und Code 11 führt jedoch zu demselben Ergebnis. Das heißt, wenn das IF in Zeile 14 falsch ist, wird das Unterprogramm ausgeführt, das in dem entsprechenden ELSE enthalten ist.


Abschließende Überlegungen

In diesem Artikel haben wir Kontrollflussanweisungen vorgestellt. Ich verstehe, dass diese Konzepte auf den ersten Blick verwirrend sein können. Aber mit Geduld und beständigem Üben, bei dem Sie neue Lösungen für Probleme finden, die Ihnen begegnen, werden Sie allmählich zur Meisterschaft gelangen - etwas, das nur wenige erreichen.

Um dies zu erreichen, ist es jedoch notwendig, ständig nach der besten Lösung für ein und dasselbe Problem zu suchen. Die Tatsache, dass ein Problem bereits gelöst wurde, bedeutet nicht, dass es keine andere, effektivere Lösung gibt. Es gibt immer einen besseren Weg. Sie müssen noch lernen, über das Offensichtliche hinauszusehen.

Und schließlich enthält die Anlage nicht alle Codes, die Sie hier sehen, sondern nur eine Teilmenge davon. Sie können jedoch nach dem Studium des Artikels noch alle notwendigen Änderungen vornehmen, sodass Sie am Ende alle hier vorgestellten Codes haben. Das Material ist nicht nur eine großartige Übung zum Lernen, sondern hilft Ihnen auch, Ihren eigenen Stil zu finden. Denn auch wenn der Code derselbe ist, kann die Art und Weise, wie er geschrieben wird, je nach Programmierer und dessen Stil unterschiedlich sein. Es ist also an der Zeit, Ihren Programmierstil zu definieren. Suchen Sie nach Möglichkeiten, Ihren Code für andere Programmierer nutzbar zu machen und gleichzeitig Ihre eigenen Lösungen schnell zu erstellen und zu ändern.


Übersetzt aus dem Portugiesischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/pt/articles/15365

Beigefügte Dateien |
Anexo.zip (2.64 KB)
Entwicklung eines Replay-Systems (Teil 62): Abspielen des Dienstes (III) Entwicklung eines Replay-Systems (Teil 62): Abspielen des Dienstes (III)
In diesem Artikel befassen wir uns mit dem Problem eines Übermaßes an Ticks, der die Anwendungsleistung bei der Verwendung echter Daten beeinträchtigen kann. Dieses Übermaß beeinträchtigt häufig das korrekte Timing, das erforderlich ist, um einen einminütigen Balken im entsprechenden Fenster zu erstellen.
Entwicklung eines Replay-Systems (Teil 61): Den Dienst abspielen (II) Entwicklung eines Replay-Systems (Teil 61): Den Dienst abspielen (II)
In diesem Artikel werden wir uns mit Änderungen befassen, die einen effizienteren und sichereren Betrieb des Replay-/Simulationssystems ermöglichen. Ich möchte auch nicht die Aufmerksamkeit derjenigen vernachlässigen, die das Beste durch die Verwendung von Klassen machen wollen. Darüber hinaus werden wir ein spezielles Problem in MQL5 betrachten, das die Codeleistung bei der Arbeit mit Klassen verringert, und erklären, wie man es lösen kann.
Von der Grundstufe bis zur Mittelstufe: WHILE- und DO WHILE-Anweisungen Von der Grundstufe bis zur Mittelstufe: WHILE- und DO WHILE-Anweisungen
In diesem Artikel werden wir einen praktischen und sehr visuellen Blick auf die erste Schleifenanweisung werfen. Viele Anfänger fühlen sich zwar eingeschüchtert, wenn sie mit der Aufgabe konfrontiert werden, Schleifen zu erstellen, aber das Wissen, wie man es richtig und sicher macht, kann nur mit Erfahrung und Übung erworben werden. Aber wer weiß, vielleicht kann ich Ihren Ärger und Ihr Leid verringern, indem ich Ihnen die wichtigsten Probleme und Vorsichtsmaßnahmen aufzeige, die Sie bei der Verwendung von Schleifen in Ihrem Code beachten müssen.
Neuronale Netze im Handel: Vereinheitlichtes Trajektoriengenerierungsmodell (UniTraj) Neuronale Netze im Handel: Vereinheitlichtes Trajektoriengenerierungsmodell (UniTraj)
Das Verständnis des Agentenverhaltens ist in vielen verschiedenen Bereichen wichtig, aber die meisten Methoden konzentrieren sich nur auf eine der Aufgaben (Verstehen, Rauschunterdrückung oder Vorhersage), was ihre Effektivität in realen Szenarien verringert. In diesem Artikel werden wir uns mit einem Modell vertraut machen, das sich an die Lösung verschiedener Probleme anpassen lässt.