初心者の方からの質問 MQL4 MT4 MetaTrader 4 - ページ 137

 
Игорь Васильев:

インジケータコードに取引コマンドがあるのになぜコンパイラが報告しないのか不思議です。

あとは、ICustom()を介してEAとリンクさせながら、インジケータからEAに取引部分を引っ張ってくる必要があります。

頭の上に尻尾、横に弓」みたいな感じですね。

コンパイラは構文のみをチェックする。その仕事は、出来上がったプログラムがどのように動くか(あるいは動かないか)を決めることではありません。トレードコマンドの非機能性は、プログラム実行の段階で初めて判明することがあります。つまり、ランタイムエラーが 発生する。

 

皆さんこんにちは、以下のことが可能かどうか教えてください。

などの仕組みがあります。
// いくつかのイベントの構造。
構造体MyStruct
{
int番号
datetime DTm;
double 値。
文字列のタイプ。
}

MyStruct型の構造体の動的 配列を宣言しています。
MyStruct DataEvents[];

私は何らかの関数で配列を形成し、記入する、例えば
void GetDataEventsTest(MyStruct& DataEvents[], int countEvent=5)
{
MathSrand(GetTickCount())。
ArrayResize(DataEvents, countEvent)。
int i = 0;
while( i<countEvent )
{
DataEvents.Number = i;
DataEvents.DTm = TimeCurrent();
DataEvents.Value = (double)MathRand();
if( MathMod(i, 2)>0 ) DataEvents.Type = "Up"; else DataEvents.Type = "Dn";
i = i + 1;
}
}

どこかでGetDataEventsTest()を呼び出して、配列を埋めています。
GetDataEventsTest(DataEvents)。

例えば,MyStruct型の新しい要素を配列の要素間隔の真ん中,インデックス2のどこかに挿入する必要があります.
ロジックでは、次のような手順が提案されています。
ArrayResize(DataEvents, ArraySize(DataEvents)+1);
とこんな感じです。
int iNew = 2;
int i = ArraySize(DataEvents) - 2;
while( i>=iNew )
{
// DataEvents[i+1] = DataEvents[i]; // 配列要素から参照されるアドレスを操作しなければならないので、当然ながらうまくいきません、そこで
// 配列要素 DataEvents[i+1] を指す配列要素に書き込む.
i = i - 1;
}
...そして、DataEvents[iNew]配列の要素にデータを入れています。


質問ですが、mql4の構造体でこのようなことは可能なのでしょうか?

 
GitSM:

質問 mql4の構造体でこのようなことは可能なのでしょうか?

はい、可能です。もし構造体が複雑なデータ型(ここでは文字列を含む)を持たないものであれば、すべてが一度に解決されるでしょう。また、構造体にデータ型が含まれ、そのサイズが時間と共に変化する可能性がある場合、代入演算 子をオーバーロードする必要があります。

struct MyStruct
{
    int Number;
    datetime DTm;
    double Value;
    string Type;

    void operator = (const MyStruct &stMyStruct)
    {
      Number = stMystruct.Number;
      DTm = stMyStruct.DTm;
      Value = stMyStruct.Value;
      Type = stMyStruct.Type;
    }
}
 
Ihor Herasko:

はい、可能です。もし、構造体が複雑なデータ型(ここでは文字列を含む)を持たないものであれば、すぐに動作するはずです。また、構造体の中にデータサイズが時間と共に変化するようなデータ型が含まれる場合は、代入演算 子をオーバーロードする必要があります。

ご指摘ありがとうございます。
 

またもや、前回の例と同じ方向の疑問が湧いてきた。
構造が複雑で、他の構造との間に配列が含まれる可能性がある場合。例えば、こんな風に宣言をするんです。

// プロパティを持つ要素
struct ItemProperty
{
ダブルロー
ダブルハイ
ダブルミドル
ダブルレンジ
ダブルエリア
文字列のタイプ。

void operator = (const ItemProperty &SourceItemProperty)
{
Low = SourceItemProperty.Low;
High = SourceItemProperty.High;
Middle = SourceItemProperty.Middle;
Range = SourceItemProperty.Range;
Area = SourceItemProperty.Area;
タイプ = SourceItemProperty.Type;
}
}

// 統計的性質を持つ項目
struct ItemsProperty;
{
ダブルMinLow。
double MaxHigh。
double AvgRange;
double AvgArea;
文字列フェーズ。

アイテム Item[];

void operator = (const ItemProperty &SourceItemsProperty)
{
MinLow = SourceItemsProperty.MinLow;
MaxHigh = SourceItemsProperty.MaxHigh;
AvgRange = SourceItemsProperty.AvgRange;
AvgArea = SourceItemsProperty.AvgArea.AvgArea;
Phase = SourceItemsProperty.Phase;

// Items = SourceItemProperty.Items; // 複数の配列変数がメモリ上の同じ物理配列を指すようにするにはどうすればよいですか?
}
}

アイテムの分析に基づく、いくつかのイベントの // 構造
struct EventProperty
{
int番号
datetime DTm;
double 値。
文字列のタイプ。

double Levels[];
int Weigths[];

ItemsProperty ItemsProp[];

void operator = (const ItemProperty &SourceEventProperty)
{
Number = SourceEventProperty.Number;
DTm = SourceEventProperty.DTm;
値 = SourceEventProperty.Value。
タイプ = SourceEventProperty.Type;

// Levels = SourceEventProperty.Levels; // ヒントがあります。
// Weigths = SourceEventProperty.Weigths; // えぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇぇす。

// ItemsProp = SourceEventProperty.ItemsProp; // ここも問題です。

}
}

イベントの動的 配列を宣言する。
EventProperty MyEvents[];

イベント配列のデータを何らかの関数で埋めています。
void GetEventsProperty(EventProperty& MyEvents)
{
// フィリングコード
}

で、どこかでMyEventsの配列の要素を追加したり削除したりして操作する必要があります。

int iNew = 2;
int i = ArraySize(MyEvents) - 2;
while( i>=iNew )
{
// MyEvents[i+1] = MyEvents[i]; // ここで不具合が発生しました。
i = i - 1;
}

mt4で構造体の配列で行うことは可能でしょうか?メモリ上の構造体の配列の1つの同じ要素を、異なる変数参照変数から参照し、作成、削除できるようにする必要があることがわかりました。
構造体への参照の配列を扱うことは可能ですか?

 
GitSM:

mt4で構造体の配列で行うことは可能でしょうか?メモリ上の構造体の配列の1つの同じ要素を、異なる変数参照から参照し、作成、削除できるようにする必要があることがわかりました。

構造体への参照の配列を扱うことは可能ですか?

理屈ではこうなるはずです。

struct ItemsProperty;
{
    double MinLow;
    double MaxHigh;
    double AvgRange;
    double AvgArea;
    string Phase;
    
    Item Items[];
    
    void operator = (const ItemProperty &SourceItemsProperty)
    {
        MinLow = SourceItemsProperty.MinLow;
        MaxHigh = SourceItemsProperty.MaxHigh;
        AvgRange = SourceItemsProperty.AvgRange;
        AvgArea = SourceItemsProperty.AvgArea;
        Phase = SourceItemsProperty.Phase;
 
        int nTotal = ArraySize(SourceItemProperty.Items);
        ArrayResize(Items, nTotal);
        for (int i = 0; i < nTotal; ++i)
           Items[i] = SourceItemProperty.Items[i];
    }
}

そして、他のすべてのアレイもまったく同じです。質問です。

複数の配列変数がメモリ上の同じ物理配列を指すようにするにはどうすればよいですか?

理解できない。

P.S.コードを挿入 するには、「</>」アイコンまたはAlt+Sを使用します。

 

Как сделать так чтобы на один и тот же физический массив в памяти могло указывать несколько переменных массива?

理解できない。

すみません、質問の仕方が良くなかったですね。私の理解が正しければ、構造体の配列は基本的に配列インデックスによる参照-アドレスで、それぞれがメモリ上のある物理アドレスを指し、データ構造に従ってある方法で分配されます。MyEvents[2]とMyEvents[5]がメモリ上の同じ構造体を指すようにすることができるかどうかということです。

この演算子をオーバーロードすると、構造体のコピーが作成されます。データ構造が非常に重い場合や、データ構造が多数ある場合でも、それらをコピーする必要はなく、あるインデックスから別のインデックスにジャンプしてデータ構造をアドレス指定するための配列が必要なだけです。このようなものです *MyEvents[2] = *MyEvents[1].ここでポインタの使い方が間違っていたかもしれないので、このように説明します。MyEvents[2]によるアドレスを取り出し、MyEvents[1]によるアドレスに変更する必要があります。

そうすれば、どんなに複雑で重いデータ構造であっても、計算資源を ほとんど無駄にすることなく、必要な順番で配列の中で「シャッフル」することができるのです。結局のところ、ある場所から別の場所へのメモリアドレスのコピーは、配列内のこの構造体を参照するインデックスを変更するために、複雑さが大きく異なる構造体をコピーするよりもはるかに簡単で、桁外れに速く、追加のメモリを必要としないのである。

Распределенные вычисления в сети MQL5 Cloud Network
Распределенные вычисления в сети MQL5 Cloud Network
  • cloud.mql5.com
Большую часть времени современные компьютеры простаивают и не используют всех возможностей процессора. Мы предлагаем задействовать их с пользой. Вы можете сдавать мощности вашего компьютера другим участникам нашей сети для выполнения разнообразных...
 
私の理解では、このような配列内の構造体への参照を「シャッフル」する仕組みを実装するためには、これらの構造体をクラスで実装する必要があるのでしょう。
そのような例を試してみたところ、うまくいきそうです。newで作成されたクラスオブジェクトの削除も監視する必要があると理解しています。
変数宣言に テストクラスとクラスへのポインタの動的配列(私の理解では、本質的に同じリンクです)を記述しています。
class MyClassTest
{
        public:
        int a;
        double b;
        string c;
};

MyClassTest* arrayRefsMyClassTest[];
こんなチェックもしました。
Print("Тест операций над массивом ссылок на классы: начало");

// создаём объекты классов и сохраняем ссылки на них в массиве ссылок.
i = 0;
while( i<5 )
{
        ArrayResize(arrayRefsMyClassTest, i+1);
        arrayRefsMyClassTest[i] = new MyClassTest();
        arrayRefsMyClassTest[i].a = i;
        arrayRefsMyClassTest[i].b = 3.14+i;
        arrayRefsMyClassTest[i].c = "testclass" + i;
        i = i + 1;
}

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Изменяем размер массива ссылок на классы");
ArrayResize(arrayRefsMyClassTest, ArraySize(arrayRefsMyClassTest)+2);

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Присваиваю последнему элементу ссылку во втором элементе");
i =  ArraySize(arrayRefsMyClassTest) - 1;
arrayRefsMyClassTest[i] = arrayRefsMyClassTest[2];

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("Присваиваю 2 элементу ссылку в 5 элементе");
arrayRefsMyClassTest[1] = arrayRefsMyClassTest[5];

i = 0;
while( i<ArraySize(arrayRefsMyClassTest) ) { if( CheckPointer(arrayRefsMyClassTest[i])!=POINTER_INVALID ) Print("arrayRefsMyClassTest[" + i + "]: a = " + arrayRefsMyClassTest[i].a, ", b = " + arrayRefsMyClassTest[i].b + ", c = " + arrayRefsMyClassTest[i].c); i = i + 1; }

Print("\nТест операций над массивом ссылок на классы: конец");
ログにこんな結果が出ました。
Тест операций над массивом ссылок на классы: начало
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Изменяем размер массива ссылок на классы
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Присваиваю последнему элементу ссылку во втором элементе
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 1, b = 4.14, c = testclass1
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[6]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: Присваиваю 2 элементу ссылку в 5 элементе
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[0]: a = 0, b = 3.14, c = testclass0
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[1]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[2]: a = 2, b = 5.14, c = testclass2
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[3]: a = 3, b = 6.14, c = testclass3
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[4]: a = 4, b = 7.14, c = testclass4
0       21:59:14.658    2018.02.01 00:00:00  Tester3 EURUSD,M5: arrayRefsMyClassTest[6]: a = 2, b = 5.14, c = testclass2
Тест операций над массивом ссылок на классы: конец
意図したとおりに動作しているようです。この場合、私の理解では、データの余分なコピーは作成されません。間違っていたら、訂正してください。何かご意見、ご感想はありますか?
 
MQL5(またはWinAPI)でチャートをフルスクリーンに拡大するにはどうすればいいのか?
 
GitSM:
私の理解では、このような配列内の構造体への参照を「シャッフル」する仕組みを実装するためには、これらの構造体をクラスで実装する必要があります。

はい、残念ながらMQLでは構造体へのポインタを作成することはできません。クラスでできることなのに、なぜこのような制限をするのかが不明です。結局、構造はクラスとあまり変わりません。