初学者的问题 MQL4 MT4 MetaTrader 4 - 页 137

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

奇怪的是,为什么编译器在看到指标代码中的交易指令时不报告呢?

现在我们将不得不把交易部分从指标中拉到EA中,通过ICustom()将其与EA连接起来。

它看起来像 "尾巴在头上,弓箭在旁边"。

编译器只检查语法。它的任务不是确定所产生的程序将如何工作(或不工作)。交易指令的不可操作性只能在程序执行阶段被发现。也就是说,将收到一个运行时错误

 

大家好,能否告诉我是否可以做到以下几点?

例如,有一个结构。
//是一些事件的结构。
结构 MyStruct
{
int编号。
datetime DTm;
双重价值。
字符串类型。
}

我声明了一个 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]写入一个指向DataEvents[i]数组元素的数组元素中。
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:

是的,这是有可能的。如果该结构没有复杂的数据类型(这里包括字符串),它就会马上工作。而当结构中包含的数据类型的数据大小可能随时间变化时,你需要重载赋值运算符

谢谢你的提示!
 

再次出现了一个与上一个例子相同方向的问题。
如果结构很复杂,可能包含有其他结构的数组。例如,我做这样的声明。

// 带有属性的元素
结构 ItemProperty
{
双低。
双高。
双中。
双重范围。
双人区。
字符串类型。

空白运算符 = (const ItemProperty &SourceItemProperty)
{
Low = SourceItemProperty.Low;
高 = SourceItemProperty.High。
Middle = SourceItemProperty.Middle。
Range = SourceItemProperty.Range;
面积=SourceItemProperty.Area.Area。
Type = SourceItemProperty.Type;
}
}

// 具有统计特性的项目
结构ItemsProperty。
{
双重MinLow。
双倍MaxHigh。
双倍AvgRange。
双倍平均面积。
串联阶段。

项目 Items[]。

空白运算符 = (const ItemProperty &SourceItemsProperty)
{
MinLow = SourceItemsProperty.MinLow。
MaxHigh = SourceItemsProperty.MaxHigh。
AvgRange = SourceItemsProperty.AvgRange。
AvgArea = SourceItemsProperty.AvgArea。
阶段 = SourceItemsProperty.Phase.Basic。

// Items = SourceItemProperty.Items; // 如何使多个数组变量指向内存中的同一个物理数组?
}
}

基于项目分析的一些事件的//结构
结构 EventProperty
{
int编号。
datetime DTm;
双重价值。
字符串类型。

double Levels[]。
int Weigths[]。

ItemsProperty ItemsProp[];

空白的operator = (const ItemProperty &SourceEventProperty)
{
Number = SourceEventProperty.Number。
DTm = SourceEventProperty.DTm。
Value = SourceEventProperty.Value。
Type = SourceEventProperty.Type;

// Levels = SourceEventProperty.Levels; // 有一个小插曲
// Weigths = SourceEventProperty.Weigths; // ehhh.

// ItemsProp = SourceEventProperty.ItemsProp; // 这里也有一个问题

}
}

声明一个动态的 事件数组
EventProperty MyEvents[];

我在一些函数中填写了事件数组的数据。
空白GetEventsProperty(EventProperty& MyEvents)。
{
// 填充代码
}

并在某处需要通过添加或删除MyEvents数组的元素来操作它们。

int iNew = 2;
int i = ArraySize(MyEvents) - 2;
while( i>=iNew )
{
// MyEvents[i+1] = MyEvents[i]; // 这里我们有一个小插曲
i = i - 1。
}

在mt4中,有可能用数组结构来做这个吗?事实证明,我们需要能够从不同的变量引用变量中引用内存中结构数组的一个相同元素,创建和删除它们。
是否可以用一个引用结构的数组来工作?

 
GitSM:

在mt4中,有可能用数组结构来做这个吗?事实证明,你需要能够从不同的变量引用中引用内存中结构数组的一个相同的元素,创建和删除它们。

是否可以用一个引用结构的数组来工作?

在理论上,应该是这样的。

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[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中对结构做指针。不清楚为什么要做这样的限制,如果你可以用类来做。毕竟,这些结构并没有真正与班级不同。

原因: