English Русский Español Português
preview
Von der Grundstufe bis zur Mittelstufe: Array (III)

Von der Grundstufe bis zur Mittelstufe: Array (III)

MetaTrader 5Beispiele |
23 1
CODE X
CODE X

Einführung

Im vorherigen Artikel „Von der Grundstufe zur Mittelstufe: Array (II)“ habe ich die Grundlagen der Verwendung dynamischer und statischer Arrays, den Unterschied zwischen ihnen und die grundlegenden Vorsichtsmaßnahmen bei der Verwendung von Arrays in Anwendungen erläutert.

Wir werden uns weiter mit dem Thema Arrays beschäftigen. Die Voraussetzung für das Verständnis dieses Artikels ist ein gutes Verständnis der im vorherigen Artikel behandelten Konzepte. Darüber hinaus ist es wichtig zu verstehen, wie die Übergabe per Wert und die Übergabe per Referenz funktioniert. Alle diese Themen wurden in früheren Artikeln erörtert und demonstriert. Wenn Sie also irgendwelche Zweifel haben oder mit diesen Konzepten nicht vertraut sind, weil Sie gerade erst anfangen, schlage ich vor, dass Sie sich etwas Zeit nehmen, um die vorherigen Artikel durchzulesen, bevor Sie fortfahren. So ist gewährleistet, dass Sie den Erklärungen folgen können.

Wie üblich beginnen wir einen neuen Abschnitt, um unsere Studien und Demonstrationen fortzusetzen.


Verwendung von Arrays in Funktionen und Prozeduren

Eines der Themen, das Anfängern oft Rätsel aufgibt, ist die Verwendung von Arrays als Mittel zur Übergabe von Werten zwischen Funktionen und Prozeduren. Hier möchte ich einen Punkt in Bezug auf dieses Konzept ganz klar herausstellen. Die Art und Weise, wie MQL5 dies handhabt, ist viel einfacher als die Art und Weise, wie einige andere Sprachen mit demselben Problem umgehen.

Sprachen wie C und C++ sind in dieser Hinsicht äußerst komplex. In diesen Fällen gibt es KEINE echte Array-Struktur wie in MQL5. Stattdessen verwenden wir eine andere Struktur, die als Zeiger bekannt ist. Das Problem mit Zeigern, das sie komplex und schwer zu beherrschen macht, rührt daher, dass wir in einigen Fällen indirekte Referenzen verwenden können. Dies bietet dem Programmierer zwar enorme Möglichkeiten, macht den Code aber auch viel schwerer verständlich. Vor allem für diejenigen, die nur wenig Erfahrung mit der Programmierung und der Verwendung von Zeigern haben.

In MQL5 sind die Dinge viel einfacher zu begreifen und anzuwenden. Angefangen bei der einfachen Tatsache, dass:

Jedes Array wird IMMER als Referenz übergeben, egal ob an eine Funktion oder an eine Prozedur.

Es gibt keine Option Übergabe per Wert bei der Verwendung eines Arrays als Argument in einer Funktion oder Prozedur in MQL5.

Sie werden jetzt vielleicht denken: „Aber wenn jedes Argument, das Arrays verwendet, per Referenz übergeben wird, egal ob an eine Funktion oder eine Prozedur, macht das den Code nicht unsicherer?“ Eigentlich nicht, liebe Leserin, lieber Leser. So überraschend es auch klingen mag, die Verwendung von Arrays in MQL5 ist viel sicherer als die Verwendung anderer Variablentypen.

Ich würde sogar so weit gehen zu sagen, dass die Verwendung von Arrays in MQL5 wesentlich einfacher ist als jede andere Methode, die in anderen Programmiersprachen verwendet wird. Das liegt daran, dass Sie in MQL5 die vollständige Kontrolle darüber haben, was mit einem Array passieren kann und was nicht, auch wenn es immer per Referenz an eine Funktion oder Prozedur übergeben wird.

Was dieses Maß an Sicherheit und Zuverlässigkeit gewährleistet, ist in der Tat die sorgfältige Arbeit des Programmierers. Als ich erklärt habe, wie wir die Übergabe per Referenz oder die Übergabe per Wert verwenden können, habe ich die Vor- und Nachteile jedes Ansatzes hervorgehoben. Aber hier ist es viel einfacher. Schon die Deklaration einer Funktion oder Prozedur macht dies deutlich und klar.

Es gibt noch ein zweites wichtiges Detail zu beachten. Sie betrifft die Tatsache, dass:

Jedes als Parameter einer Funktion oder Prozedur deklarierte Array muss IMMER dynamisch sein.

Wenn Sie diese beiden Prinzipien anwenden, können Sie jede Art von Implementierung in MQL5 erstellen, die Arrays beinhaltet. Oft ist es praktischer und angemessener, Berechnungen innerhalb von Funktionen oder Prozeduren durchzuführen, anstatt Code inline zu platzieren.

Anmerkung: Für diejenigen, die mit dem Begriff „Inline-Code“ nicht vertraut sind: Er bezieht sich auf die Praxis, dass der Programmierer keine Funktionen oder Prozeduren in der Anwendung verwendet. Stattdessen schaffen sie eine Reihe von Routinen, eine nach der anderen, wie nach einem langen Rezept. Obwohl es seltene Szenarien gibt, in denen dieser Ansatz durchführbar ist, kommt er doch vor. Das Hauptmerkmal eines solchen Codes ist das völlige Fehlen von Funktionen oder Prozeduren in der Implementierung.

Kehren wir nun zu unserem Hauptthema zurück: wie man Arrays als Parameter in Funktionen und Prozeduren verwendet. Trotz der scheinbaren Einfachheit dieses Verfahrens sollten Sie, lieber Leser, nicht unvorsichtig werden und davon ausgehen, dass alles einfach und risikofrei ist.

In der Tat gibt es gewisse Nuancen, die erst in der Praxis deutlich werden. Die Theorie mag übersichtlich erscheinen und verlangt von uns nur das Verständnis einiger weniger Konzepte. In der Praxis können die Dinge jedoch knifflig werden und sich gelegentlich festbeißen, bevor wir sie überwinden können. Sehen wir uns also zunächst an, wie die Dinge in der Praxis funktionieren. Beginnen wir mit dem unten stehenden Code.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     const char Infos[]  = {2, 3, 3, 5, 8};
07. 
08.     Print("Based on the values:");
09.     ArrayPrint(Infos);
10.     PrintFormat("There are %d possibilities.", Possibilities(Infos));
11. }
12. //+------------------------------------------------------------------+
13. ushort Possibilities(const uchar &arg[])
14. {
15.     ushort info = 0;
16. 
17.     for (uchar c = 0; c < arg.Size(); c++)
18.         info = (c ? info * arg[c] : arg[c]);
19. 
20.     return info;
21. }
22. //+------------------------------------------------------------------+

Code 01

Wenn der Code 05 ausgeführt wird, sehen Sie das Ergebnis wie in der folgenden Abbildung dargestellt.

Abbildung 01

Was Sie in Abbildung 01 sehen, kann auf viele verschiedene Arten erzeugt werden. Die in Code 01 verwendete Methode dient nur zu Lehrzwecken. Das Ziel ist es, zu erklären, was in dieser Ausgabe passiert, und zu demonstrieren, wie wir ein Array an eine Funktion oder Prozedur übergeben können.

Schauen wir uns also an, was hier vor sich geht. Ich werde nur die Teile hervorheben, die meines Erachtens noch nicht in einem der vorherigen Artikel behandelt wurden. Beginnen wir mit den Highlights in Zeile sechs. Obwohl wir hier ein statisches Array verwenden, geschieht dies lediglich zur Vereinfachung des Codes. Wir hätten in dieser Zeile auch ein dynamisches Array verwenden können, ohne dass sich an der Funktionalität etwas geändert hätte. Das eigentliche Ziel besteht darin, die Werte an die in Zeile dreizehn deklarierte Funktion zu übergeben. Alles, was vor Zeile zehn in Code 01 passiert, hat also keinen Einfluss darauf, wie das Array übergeben wird. Nun, solange die Funktion so deklariert wird, wie in Zeile dreizehn gezeigt.

Passen Sie also gut auf, was hier erklärt wird, lieber Leser. In früheren Artikeln haben wir gesehen, dass ein als konstant deklariertes Array in der Deklaration selbst initialisiert werden MUSS. Dies geschieht, um Kompilierungsfehler zu vermeiden. Schauen Sie sich jedoch die dreizehnte Zeile genau an. Hier deklarieren wir ein Array als konstant. Dennoch erzeugt der Compiler die ausführbare Datei.

Warum ist es erlaubt, dies hier so zu deklarieren, während es in Zeile sechs nicht funktionieren würde? Der Grund dafür ist, dass das Array in Zeile dreizehn, anders als in Zeile sechs, nicht als Variable, sondern als Parameter deklariert wird. Und wie bereits erwähnt, muss jedes Array per Referenz übergeben werden. Und genau das ist hier der Fall.

Einige von Ihnen, vor allem diejenigen, die neu in der Programmierung sind, könnten fälschlicherweise denken, dass das in Zeile dreizehn deklarierte Array wegen des Arrays in Zeile sechs NICHT als konstant deklariert ist. Das eine hat mit dem anderen nichts zu tun. Sie könnten sogar das Array in Zeile sechs als vollständig dynamisch deklarieren und initialisieren. Dies würde jedoch nichts an der Erklärung in Zeile dreizehn ändern, da der Kontext und der Zweck völlig unterschiedlich sind.

Es gibt noch ein weiteres Detail im Code 01, das meines Erachtens hier noch einmal hervorgehoben werden sollte, obwohl es bereits erwähnt wurde. Das Problem bezieht sich auf den Testwert in Zeile siebzehn. Dort verwenden wir arg.Size(). Dies ist erlaubt und vollkommen gültig, da das Ergebnis dasselbe ist, als wenn wir die Funktion ArraySize verwendet hätten. In beiden Fällen würde die Kontrolle auf dieselbe Weise durchgeführt. Versuchen Sie als Hausaufgabe, arg.Size() durch ArraySize zu ersetzen, um besser zu verstehen, wie der Code in der Praxis implementiert werden würde.

Gut, ich glaube, dieser erste Überblick war relativ angenehm und hat Ihnen eine Vorstellung davon vermittelt, wie man Code zur Übergabe eines Arrays an eine Funktion oder eine Prozedur implementiert. Die Methode, mit dem Array zu arbeiten und es als Parameter zu deklarieren, würde sich in diesem speziellen Kontext nicht ändern. Nur der Zweck könnte ein anderer sein.

Das war der einfache Teil. Jetzt können wir zu etwas Komplexerem übergehen. Um Ihnen jedoch die Möglichkeit zu geben, jedes Thema sorgfältig zu studieren, werden wir diese neuen komplexen Dinge in einem neuen Abschnitt behandeln.


Ein Array aus der Ferne modifizieren

Einer der Anwendungsfälle, der die Arbeit mit Arrays in Funktionen und Prozeduren etwas kompliziert machen kann, ist die Möglichkeit, den Inhalt eines Arrays ferngesteuert zu ändern. Mit anderen Worten: Sie übergeben ein Array an eine Funktion oder Prozedur, und es wird innerhalb dieser Funktion oder Prozedur geändert. Dieses Verhalten kann zu recht verwirrenden und komplexen Problemen führen, die es zu lösen gilt. Da wir jedoch in vielen Fällen diese Art von Maßnahmen ergreifen müssen, ist es wichtig, dass Sie genau verstehen, was passiert. Aber zunächst einmal ist es wichtig zu verstehen, warum dies geschieht.

Im Gegensatz zu diskreten Werten wie char, int, long, double und ähnlichen Typen erlauben die meisten Programmiersprachen NICHT die Rückgabe von Arrays, außer in besonderen Fällen, in denen die Sprache selbst einen Mechanismus zur Handhabung dieser Werte bietet. Ein solches Beispiel in MQL5 sind Zeichenketten (string).

Wie in den vorangegangenen Artikeln gezeigt wurde, ist eine Zeichenkette in der Tat eine spezielle Art von Array. Dies ist einer der wenigen Fälle, in denen wir ein Array aus einer Funktion in MQL5 zurückgeben können. Diese Funktion beseitigt bereits das Risiko und die potenziellen Probleme, die bei bestimmten Implementierungen auftreten können, wenn wir wirklich ein geändertes Array zurückgeben müssen.

Bevor wir uns jedoch näher mit diesem Thema befassen, da es sich um ein recht komplexes Konzept handelt, das in echtem Code zu verstehen ist, müssen wir uns ansehen, wie andere Sprachen mit diesem Problem umgehen. In C und C++ z. B. liegt die Verantwortung vollständig in den Händen des Programmierers. In diesen beiden Sprachen haben wir sowohl die Möglichkeit, das Array zu ändern als auch ein völlig neues Array zurückzugeben. Lassen Sie sich jedoch nicht zu der Annahme verleiten, dass Sie dadurch weniger anfällig für Fehler sind. Vielmehr werden Sie dadurch noch mehr komplexen Fehlern ausgesetzt. Das ist einer der Gründe, warum C und C++ so schwierig zu beherrschen sind.

Andere Sprachen, wie Python und JavaScript, umgehen die Verwendung herkömmlicher Datentypen im Wesentlichen vollständig. Sie implementieren eigene Methoden, mit denen wir Arrays zurückgeben oder sie sogar ändern können. Dieses Verfahren ist weniger verbreitet und daher für bestimmte Arten von einer Überarbeitung etwas einfacher. Dennoch liegt unser Schwerpunkt hier auf MQL5.

Beginnen wir also mit dem einfachsten Beispiel, das möglich ist. Wir nehmen Code 01 und ändern nur ein kleines Detail. Dies führt zu der nachstehenden Darstellung.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char Infos[]  = {2, 3, 3, 5, 8};
07. 
08.     Print("Based on the values:");
09.     ArrayPrint(Infos);
10.     PrintFormat("There are %d possibilities.\nValue after call:", Possibilities(Infos));
11.     ArrayPrint(Infos);
12. }
13. //+------------------------------------------------------------------+
14. ushort Possibilities(uchar &arg[])
15. {
16.     ushort info = 0;
17. 
18.     for (uchar c = 0; c < arg.Size(); c++)
19.         info = (c ? info * arg[c] : arg[c]);
20. 
21.     arg[0] += 2;
22. 
23.     return info;
24. }
25. //+------------------------------------------------------------------+

Code 02

Wenn wir Code 02 ausführen, erhalten wir die unten gezeigte Ausgabe.

Abbildung 02

Beachten Sie, dass ich in Abbildung 02 zwei Werte hervorgehoben habe. Damit möchte ich Ihre Aufmerksamkeit auf das lenken, was hier geschieht.

Beachten Sie, dass der Unterschied zwischen Code 02 und Code 01 genau darin besteht, dass die Parameterdeklaration in der Funktion in Zeile 14 NICHT MEHR KONSTANT ist. Der Mechanismus der Weitergabe durch Referenz, der bei Arrays immer zum Tragen kommt, ermöglicht es uns daher, Zeile 21 zu verwenden, in der wir den Wert eines der Elemente in dem in Zeile 6 deklarierten Array ändern.

Da wir hier in einem didaktischen Kontext arbeiten und uns darauf konzentrieren, bestimmte Konzepte zu erklären, die auf MQL5 anwendbar sind, ist diese Änderung recht einfach zu erkennen. In echtem Code kann sie jedoch viel tiefer eingebettet und oft so verstrickt sein, dass man am liebsten aufgeben und alles von Grund auf neu programmieren würde, so komplex kann sie werden.

Deshalb möchte ich Sie, liebe Leserin, lieber Leser, ermutigen, diese Konzepte gründlich zu üben, vor allem, wenn Sie gerade erst mit dem Programmieren beginnen oder nur wenig Erfahrung haben. Nur durch die Praxis werden Sie die nötige Erfahrung sammeln, um mit den unweigerlich auftretenden Problemen umzugehen.

Nun gut, Code 02 ist in der Tat der einfachste mögliche Typ. In gewisser Weise ist das fast trivial. Die Dinge werden jedoch komplizierter, wenn wir uns eingehender mit dem Thema befassen. Schauen wir uns also ein anderes Beispiel an, das diesmal etwas komplexer ist. Sie ist unten abgebildet.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char Infos[];
07.     
08.     ArrayResize(Infos, 7);   
09.     ZeroMemory(Infos);
10. 
11.     Infos[0] = 2;
12.     Infos[1] = 3;
13.     Infos[2] = 3;
14.     Infos[3] = 5;
15.     Infos[4] = 8;
16. 
17.     Print("Based on the values:");
18.     ArrayPrint(Infos);
19.     PrintFormat("There are %d possibilities.\nValue after call:", Possibilities(Infos));
20.     ArrayPrint(Infos);
21. 
22.     ArrayFree(Infos);
23. }
24. //+------------------------------------------------------------------+
25. ushort Possibilities(uchar &arg[])
26. {
27.     ushort info = 0;
28. 
29.     for (uchar c = 0; c < arg.Size(); c++)
30.         info = (c ? (arg[c] ? info * arg[c] : info) : arg[c]);
31. 
32.     arg[arg.Size() - 1] = 9;
33. 
34.     return info;
35. }
36. //+------------------------------------------------------------------+

Code 03

Nun gut, in Code 03 wird es etwas komplizierter. Die zusätzliche Komplexität ist jedoch nicht auf die Linie 30 zurückzuführen. Diese Linie bleibt recht einfach.

Die Komplexität von Code 03 ergibt sich aus der Tatsache, dass wir in Zeile 6 ein rein dynamisches Array deklarieren. Hier beginnen die Dinge wirklich komplex zu werden. Trotzdem ist Code 03 etwas, das ein Anfänger vollständig und perfekt verstehen kann, wenn er dem in diesen Artikeln vorgestellten Material folgt, einen Schritt nach dem anderen macht und übt, was auf dem Weg demonstriert wurde.

Aber sehen wir uns das Ergebnis der Ausführung von Code 03 an. Sie ist auf dem Bild unten dargestellt.

Abbildung 03

Auch hier hebe ich einige der im Bild enthaltenen Informationen hervor. Diese hervorgehobenen Informationen sind sehr wichtig, um sie vollständig zu verstehen.

Schauen wir uns also an, was hier passiert. In Zeile acht geben wir an, dass das Array sieben Elemente haben soll. In den Zeilen elf bis fünfzehn werden dann einige dieser Elemente initialisiert. Sie können sehen, dass der Inhalt des Arrays in Zeile 18 einige Nullwerte enthält. Das ist normal, denn in Zeile neun wird der Speicher, in dem das Array zugewiesen wurde, wieder gelöscht.

Gerade wegen dieser Nullen war es notwendig, in Zeile 30 einen zusätzlichen ternären Operator einzufügen. Ohne sie wäre das Ergebnis der Funktion gleich Null. Dies ist jedoch nicht der wichtigste Punkt von Interesse. Der eigentliche Punkt von Interesse ist in Zeile 32. Beachten Sie, dass wir hier einem bestimmten Element, das in diesem Fall das letzte Element im Array ist, einen Wert zuweisen.

Aber warum tue ich das, und warum in dieser Reihenfolge der Demonstrationen? Der Grund dafür ist, dass es in MQL5 eine Möglichkeit gibt, mit Arrays zu arbeiten, die es uns erlaubt, etwas zu tun, was auf natürliche Weise nicht möglich wäre. Es sei denn, Sie, lieber Leser, verstehen bestimmte Konzepte im Zusammenhang mit der Verwendung von Arrays. Gleichzeitig werden Sie feststellen, dass hier bestimmte Dinge passieren, die andere Konzepte viel natürlicher erscheinen lassen, wenn wir sie in Kürze untersuchen.

Großartig. Wir haben unserem System bereits eine gehörige Portion Komplexität hinzugefügt. Aber wir können die Dinge noch interessanter machen. Ehrlich gesagt, wenn es nach mir ginge, würde der Artikel hier enden, damit Sie bereits mit dem Gezeigten üben können. Und, seien wir ehrlich, das ist schon eine ganze Menge, und viele dieser Konzepte sind anfangs recht schwierig zu verstehen. Aber lassen Sie uns einen letzten Versuch unternehmen, etwas zu visualisieren, das interessant sein kann und in direktem Zusammenhang mit dem hier behandelten Thema steht. Da es sich um ein viel komplizierteres Konzept handelt, gehen wir zu einem neuen Abschnitt über.


Remote Initialisierung

An dieser Stelle möchte ich Sie, lieber und geschätzter Leser und Freund, um Folgendes bitten: Halten Sie inne und studieren Sie das bisher Gesagte. Erst wenn Sie alles verstanden haben, keine Zweifel oder Unklarheiten mehr bestehen und Sie sich vergewissert haben, dass Sie die vorherigen Codes verstanden haben, sollten Sie mit diesem Abschnitt fortfahren. Dieser Teil ist viel zu komplex, um ihn ohne die richtige Vorbereitung zu bewältigen.

Was wir bisher gesehen haben, zeigt, dass wir Daten mit Arrays senden können. Danach haben wir gelernt, dass wir Daten in einem Array innerhalb einer anderen Funktion oder Prozedur ändern können. Dies muss mit großer Sorgfalt geschehen, insbesondere wenn Sie eine umfangreichere Anwendung erstellen. Als Nächstes haben wir gesehen, dass wir mit einem Array arbeiten können, indem wir einstellen, wo wir seinen Wert ändern. Jetzt ist es an der Zeit, etwas anderes zu tun. Dies wird im nächsten Code gezeigt.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char Infos[];
07.     
08.     InitArray(Infos);
09. 
10.     Print("Based on the values:");
11.     ArrayPrint(Infos);
12.     PrintFormat("There are %d possibilities.\nValue after call:", Possibilities(Infos));
13.     ArrayPrint(Infos);
14. 
15.     ArrayFree(Infos);
16. }
17. //+------------------------------------------------------------------+
18. void InitArray(uchar &arg[])
19. {
20.     ArrayResize(arg, 7);    
21.     ZeroMemory(arg);
22. 
23.     arg[0] = 2;
24.     arg[1] = 3;
25.     arg[2] = 3;
26.     arg[3] = 5;
27.     arg[4] = 8;
28. }
29. //+------------------------------------------------------------------+
30. ushort Possibilities(uchar &arg[])
31. {
32.     ushort info = 0;
33. 
34.     for (uchar c = 0; c < arg.Size(); c++)
35.         info = (c ? (arg[c] ? info * arg[c] : info) : arg[c]);
36. 
37.     arg[arg.Size() - 1] = 9;
38. 
39.     return info;
40. }
41. //+------------------------------------------------------------------+

Code 04

Und hier sind wir nun, lieber Leser. Dies ist der Höhepunkt dessen, was wir in diesem Artikel behandeln werden. Lassen Sie sich jedoch nicht von der scheinbaren Einfachheit von Code 04 täuschen. Trotz der Tatsache, dass die Ausgabe das ist, was wir gerade unten sehen, ist es viel komplexer als es scheint.

Abbildung 04

Beachten Sie, dass die Ausgabe genau die gleiche ist wie in Abbildung 03, in jeder Hinsicht identisch. Aber hier, in Code 04, zeige ich auf einfache Weise etwas, das bei falscher Handhabung äußerst komplex werden kann. Bei richtiger und angemessener Umsetzung kann dieser Ansatz jedoch eine Reihe von Problemen lösen. Vor allem Dinge, von denen einige so genannte „erfahrene Programmierer“ behaupten, sie seien in MQL5 unmöglich zu erledigen. Zumindest in reiner Form und ohne Rückgriff auf Ressourcen außerhalb dessen, was MQL5 selbst bietet.

Ich habe diese Änderungen schrittweise vorgenommen, damit Sie genau verfolgen können, was hier passiert. Obwohl man denken könnte, dass Code 04 nur eine einfache Variation dessen ist, was in Code 03 gemacht wird, zeigt Code 04 im Grunde, dass wir tatsächlich etwas tun können, was nicht möglich ist, ohne bestimmte Konzepte gründlich zu verstehen.

Eines dieser Konzepte - und das ist genau das, was wir in Code 04 erforschen - ist die Tatsache, dass jedes Array per Referenz übergeben wird. Und wenn wir dies tun und die in früheren Artikeln behandelten Konzepte anwenden, können wir tatsächlich etwas erreichen, von dem viele behaupten, es sei nicht möglich. Nämlich: Initialisierung oder sogar Änderung von Arrays außerhalb des Bereichs, in dem sie deklariert wurden.

Wir können diese Idee sogar noch weiterführen, ohne den Schwierigkeitsgrad zu erhöhen, den wir bisher behandelt haben. Um dies zu erklären, müssen wir den Code 04 geringfügig ändern.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     char Infos[];
07.     
08.     if (ArraySize(Infos))
09.     {
10.         Print("Based on the values:");
11.         ArrayPrint(Infos);
12.     }else
13.         Print("Array has not been initialized yet.");
14.     PrintFormat("There are %d possibilities.\nValue after call:", Possibilities(Infos));
15.     ArrayPrint(Infos);
16. 
17.     ArrayFree(Infos);
18. }
19. //+------------------------------------------------------------------+
20. void InitArray(uchar &arg[])
21. {
22.     const char init [] = {2, 3, 3, 5, 8};
23. 
24.     ArrayCopy(arg, init);
25. }
26. //+------------------------------------------------------------------+
27. ushort Possibilities(uchar &arg[])
28. {
29.     ushort info = 0;
30. 
31.     InitArray(arg);
32. 
33.     for (uchar c = 0; c < arg.Size(); c++)
34.         info = (c ? (arg[c] ? info * arg[c] : info) : arg[c]);
35. 
36.     ArrayResize(arg, arg.Size() + 1);
37.     arg[arg.Size() - 1] = 9;
38. 
39.     return info;
40. }
41. //+------------------------------------------------------------------+

Code 05

Wenn Sie den obigen Code 05 ausführen, sehen Sie das untenstehende Bild.

Abbildung 05

Nun, dann fragen Sie sich vielleicht: Wie ist das möglich? So etwas macht nicht viel Sinn. Aber hier, liebe Leserinnen und Leser, mache ich mir nur einen Spaß mit demselben Code, den wir seit Beginn dieses Artikels untersuchen. Es gibt absolut keinen Grund zur Panik oder Verzweiflung.

Das entscheidende Detail ist, dass wir hier, anders als sonst üblich, die Grenzen von Konzepten ausloten, die in MQL5 perfekt erforscht werden können. In diesen letzten Codebeispielen gehen wir jedoch ein wenig über das hinaus, was viele verstehen können. Das liegt daran, dass sie die Konzepte hinter der Umsetzung nicht wirklich verstehen. Sie kopieren und fügen Codefragmente ein, ohne wirklich zu verstehen, warum der Code funktioniert. Aber das ist nicht das, was ich will. Ich möchte, dass Sie, liebe Leserin, lieber Leser, die damit verbundenen Konzepte wirklich verstehen. Wenn Sie das erreichen können, dann hat es sich gelohnt, diese Artikel zu schreiben und diese Dinge zu demonstrieren.

Na gut. Da ich in diesem Artikel noch nicht auf weitere Details eingehen möchte, widmen wir den Rest des Artikels der ausführlichen Erläuterung von Code 05. Schließlich ist der Code 04 etwas einfacher als der Code 05.

Schauen wir uns also an, wie Code 05 funktioniert. Zunächst haben wir in Zeile 6 die Deklaration eines rein dynamischen Arrays. Dieser muss irgendwann zugewiesen werden, damit wir den Speicher als Speicherplatz nutzen können.

Angenommen, wir sind nicht sicher, ob das Array aus Zeile 6 initialisiert wurde oder nicht. In Zeile 8 wird geprüft, ob sich Elemente im Array befinden. Denken Sie daran: Es handelt sich um ein rein dynamisches Array. Wenn Sie es direkt in Zeile 6 initialisieren, wird es in Zeile 8 abgefangen. Auch wenn er zwischen den Zeilen 6 und 8 initialisiert wird, wird er in Zeile 8 erkannt.

Wenn die Initialisierung jedoch genau in Zeile 6 erfolgt, wo das Array deklariert wird, treten andere Probleme auf. Probieren Sie es selbst aus, um zu sehen, welche Probleme auftreten. So können Sie üben und Erfahrungen mit Arrays sammeln.

Wenn mindestens ein Element im Array vorhanden ist, werden die Zeilen 10 und 11 ausgeführt, die zeigen, dass Elemente im Array vorhanden sind. Wenn es nicht initialisiert wurde, wird die Meldung in Zeile 13 im Terminal angezeigt.

Jetzt kommt der Teil, der die Sache wirklich interessant macht. Dies geschieht durch die Zeile 14, die die Funktion in Zeile 27 aufruft. Beachten Sie, dass das Array bis zu diesem Punkt noch nicht initialisiert wurde. Es wird erst initialisiert, wenn Zeile 31 ausgeführt wird. Das liegt daran, dass genau in dieser Zeile die Prozedur aus Zeile 20 aufgerufen wird.

In dieser Prozedur wird in Zeile 24 das in Zeile 6 erstellte dynamische Array initialisiert. Beachten Sie, dass wir dazu ein statisches Array vom Typ ROM verwenden, wie in Zeile 22 gezeigt. Ich weiß, dass dies sehr verwirrend und schwer zu verstehen sein mag. Aber wenn Sie einen Blick auf die Funktion ArrayCopy aus der Standardbibliothek werfen, werden Sie verstehen, warum dies funktioniert. Diese Funktion kopiert im Wesentlichen ein Array in ein anderes. Und es gibt unzählige Szenarien, in denen dies in realen Anwendungen äußerst nützlich sein kann.

Danach geht es in die Schleife in Zeile 33, wo Berechnungen durchgeführt werden, um einen Rückgabewert für Zeile 14 zu erhalten.

Bevor wir jedoch zu Zeile 14 zurückkehren, fügen wir in Zeile 36 ein neues Element zu dem in Zeile 6 deklarierten Array hinzu, das jedoch bereits in Zeile 24 initialisiert wurde. Und das ist der interessante Teil. Denn wenn Sie das Array nicht initialisieren, weil Sie Zeile 31 aus dem Code entfernen, gibt die Funktion „Possibilities“ einen Wert zurück, der dem in Zeile 29 entspricht. Das liegt daran, dass die Schleife in Zeile 33 nicht ausgeführt werden kann.

Wenn Sie jedoch den Inhalt des in Zeile 6 deklarierten Arrays überprüfen, werden Sie feststellen, dass es ein Element im Array gibt. Und dieses Element hat den in Zeile 37 angegebenen Wert.

Sie müssen dies in der Praxis ausprobieren, um die Erklärung zu verstehen. Wie ich bereits erwähnt habe, sollten Sie also üben und den Inhalt des Anhangs nutzen, um ein besseres Verständnis dafür zu erlangen, wie alles funktioniert.


Abschließende Überlegungen

In diesem Artikel werden die Dinge viel spannender als in den vorherigen, denn wir beginnen, neue Möglichkeiten zu erforschen, indem wir Konzepte verwenden, die bereits im ersten Artikel erklärt wurden. Ich weiß, dass denjenigen, die hier einsteigen, ohne die vorherigen Artikel gelesen zu haben, vieles von dem, was hier gezeigt wurde, äußerst komplex und verwirrend erscheinen mag. Diejenigen jedoch, die jeden einzelnen Artikel geübt und studiert haben, wissen bereits, wie interessant und wertvoll diese Inhalte sind. Sie eröffnet auch viele Möglichkeiten, darunter eine, die bereits in einem älteren Artikel kurz angesprochen wurde.

Im nächsten Artikel werden wir etwas, das wir schon einmal gesehen haben, so alltäglich machen, dass Sie gar nicht merken werden, dass Sie ein besserer Programmierer werden als viele andere da draußen. Wenn Sie die richtigen Konzepte kennen und wissen, wie man sie anwendet, befreien Sie sich von den Beschränkungen, in denen viele Menschen stecken bleiben - einfach weil sie die zugrunde liegenden Programmierkonzepte nicht verstehen. Sie kopieren einfach den Code und fügen ihn ein. Also, viel Spaß mit den Dateien im Anhang, und wir sehen uns im nächsten Artikel.

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

Beigefügte Dateien |
Anexo.zip (2.52 KB)
Letzte Kommentare | Zur Diskussion im Händlerforum (1)
73065731
73065731 | 13 Juni 2025 in 07:02
Ja ok
Entwicklung eines Replay-Systems (Teil 71): Das richtige Bestimmen der Zeit (IV) Entwicklung eines Replay-Systems (Teil 71): Das richtige Bestimmen der Zeit (IV)
In diesem Artikel werden wir uns ansehen, wie man das, was im vorigen Artikel über unseren Wiedergabe-/Simulationsdienst gezeigt wurde, implementiert. Wie bei vielen anderen Dingen im Leben sind auch hier Probleme vorprogrammiert. Und dieser Fall war keine Ausnahme. In diesem Artikel werden wir die Dinge weiter verbessern. 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.
Neuronale Netze im Handel: Marktanalyse mit Hilfe eines Muster-Transformers Neuronale Netze im Handel: Marktanalyse mit Hilfe eines Muster-Transformers
Wenn wir Modelle zur Analyse der Marktsituation verwenden, konzentrieren wir uns hauptsächlich auf Kerzen. Es ist doch seit langem bekannt, dass Kerzen-Muster bei der Vorhersage künftiger Kursbewegungen helfen können. In diesem Artikel werden wir uns mit einer Methode vertraut machen, die es uns ermöglicht, diese beiden Ansätze zu integrieren.
Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
Entwicklung eines Replay-Systems (Teil 70): Das richtige Bestimmen der Zeit (III) Entwicklung eines Replay-Systems (Teil 70): Das richtige Bestimmen der Zeit (III)
In diesem Artikel erfahren Sie, wie Sie die Funktion CustomBookAdd richtig und effektiv nutzen können. Trotz ihrer scheinbaren Einfachheit hat sie viele Nuancen. So können Sie dem Mauszeiger beispielsweise mitteilen, ob ein nutzerdefiniertes Symbol gerade versteigert oder gehandelt wird oder ob der Markt geschlossen ist. 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.