Structs mess with things, and I can't see why...

 

Why does this not work? overshoots is an array of struct...

int h=FileOpen("test.csv",FILE_WRITE|FILE_ANSI|FILE_CSV,",");
   if(h==INVALID_HANDLE)
   {
      Comment("Error opening file");
   }
   
   int _size = ArraySize(overshoots);
   for (int i=0;i<_size;i++)
   {
      FileWrite(h, "fubar");
   }
   
   FileClose(h);

but this does.

int h=FileOpen("test.csv",FILE_WRITE|FILE_ANSI|FILE_CSV,",");
   if(h==INVALID_HANDLE)
   {
      Comment("Error opening file");
   }
   
   //int _size = ArraySize(overshoots);
   int _size = 12;
   for (int i=0;i<_size;i++)
   {
      FileWrite(h, "fubar");
   }
   
   FileClose(h);

Using the debugger I can see that _size gets correctly set as the size of the array called overshoots. So it is an integer and is equal to 12. 

More struct weirdness below... 

 

Update:

This is even stranger than I thought. It seems that even looking at the contents of a struct means the file won't write:

struct ShootRecord
{
   bool is_overshoot;
   double level; 
   
};

In OnDeInit I try to write the contents of the first element of an array of ShootRecord (my struct):

void  OnDeinit(const int reason)
{
   int h=FileOpen("test.csv",FILE_WRITE|FILE_ANSI|FILE_CSV,",");
   if(h==INVALID_HANDLE)
   {
      Comment("Error opening file");
   }
   ShootRecord shoot = overshoots[0]; 
   double d = shoot.level;
   string test = DoubleToString(d, 5);
   Comment("test: " + test);
   FileWrite(h, test);
   
   FileClose(h);
}

The variable 'test' appears correctly in the debugger watch list and renders fine as a comment on the screen. However the file is always empty. If I substitute an actual double into the line, rather than accessing the struct,  like this:

ShootRecord shoot = overshoots[0];
   double d = 0.0258644;
   //double d = shoot.level;

then the file still fails to write (!!!!), but if I remove the (unnecessary) assignment to the struct:

   //ShootRecord shoot = overshoots[0];
   double d = 0.0258644;
   //double d = shoot.level;

then the FileWrite works fine. 

This is bizarre. I have spent a day reading forum posts without finding any references to this behaviour. There is no error generated (I have used _LastError), and if you step through in debug, everything looks fine.

So it seems to me that even mentioning a struct is enough to kill the FileWrite. What is going on?

 
peaveyyyy:

Update:

This is even stranger than I thought. It seems that even looking at the contents of a struct means the file won't write:

In OnDeInit I try to write the contents of the first element of an array of ShootRecord (my struct):

The variable 'test' appears correctly in the debugger watch list and renders fine as a comment on the screen. However the file is always empty. If I substitute an actual double into the line, rather than accessing the struct,  like this:

then the file still fails to write (!!!!), but if I remove the (unnecessary) assignment to the struct:

then the FileWrite works fine. 

This is bizarre. I have spent a day reading forum posts without finding any references to this behaviour. There is no error generated (I have used _LastError), and if you step through in debug, everything looks fine.

So it seems to me that even mentioning a struct is enough to kill the FileWrite. What is going on?

//+------------------------------------------------------------------+
//|                                                  StructArray.mq5 |
//|                        Copyright 2020, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
struct overshootstruct
{
   double c;
   double d;
   overshootstruct() { c=d=0.00; }
   ~overshootstruct() {}
};
struct Test
{
   double a;
   double b;
   Test() { a=b=0.00; }
   ~Test() {}
};

int OnInit()
  {
   overshootstruct overshoot[];
   Test test_a[];
   for(int i=0;i<10;i++)
   {
      ArrayResize(overshoot,i+1);
      overshoot[i].c = (double)(i+1);
      overshoot[i].d = (double)(i+2);
   }
   ArrayPrint(overshoot);
   ArrayResize(test_a,2);
   test_a[0].a = 1.23;
   test_a[0].b = 2.34;
   test_a[1].a = 1.23;
   test_a[1].b = 2.34;
   overshoot[0].c = test_a[0].a;
   overshoot[0].d = test_a[0].b;
   ArrayPrint(overshoot);
   Print("array struct of test_a size is ",ArraySize(test_a));
   Print("array struct of overshoot is ",ArraySize(overshoot));
   int h=FileOpen("test.csv",FILE_WRITE|FILE_ANSI|FILE_CSV,",");
   if(h==INVALID_HANDLE)
   {
      Comment("Error opening file");
   }
   
   int _size = ArraySize(overshoot);
   PrintFormat("%s file is available for writing","test.csv");
   for (int i=0;i<_size;i++)
   {
      FileWrite(h, "fubar");
   }
   PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));
   FileClose(h);
   
   
//---
   return(INIT_SUCCEEDED);
  }
KO      0       23:03:13.721    Tester  expert file added: Experts\StructArray.ex5. 16721 bytes loaded
IH      0       23:03:13.742    Tester  initial deposit 10000000.00 USD, leverage 1:500
IM      0       23:03:13.742    Tester  successfully initialized
JI      0       23:03:13.742    Network 16 Kb of total initialization data received
FP      0       23:03:13.742    Tester  Intel Xeon  E5-2686 v4 @ 2.30GHz, 8191 MB
KE      0       23:03:13.777    Symbols EURUSD: symbol to be synchronized
HQ      0       23:03:13.778    Symbols EURUSD: symbol synchronized already, 18 bytes received
MP      0       23:03:13.781    History EURUSD: history synchronization started
LG      0       23:03:13.786    History EURUSD: load 27 bytes of history data to synchronize in 0:00:00.002
PR      0       23:03:13.786    History EURUSD: history synchronized from 1999.01.04 to 2020.08.21
NE      0       23:03:13.787    Ticks   EURUSD: ticks synchronization started
RR      0       23:03:13.788    Ticks   EURUSD: load 34 bytes of tick data to synchronize in 0:00:00.000
DO      0       23:03:13.788    Ticks   EURUSD: history ticks synchronized from 2019.03.29 to 2020.08.21
LH      0       23:03:13.964    History EURUSD,M15: history cache allocated for 40787 bars and contains 40650 bars from 2019.01.02 09:00 to 2020.08.20 23:45
MJ      0       23:03:13.965    History EURUSD,M15: history begins from 2019.01.02 09:00
OE      0       23:03:13.976    Tester  EURUSD,M15 (XMGlobal-MT5 2): generating based on real ticks
KN      0       23:03:13.976    Tester  testing with execution delay 251 milliseconds
OI      0       23:03:13.976    Tester  EURUSD,M15: testing of Experts\StructArray.ex5 from 2020.08.21 00:00 to 2020.08.23 00:00 started
EJ      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00            [c]      [d]
CP      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [0]  1.00000  2.00000
FM      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [1]  2.00000  3.00000
IJ      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [2]  3.00000  4.00000
DG      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [3]  4.00000  5.00000
GL      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [4]  5.00000  6.00000
JI      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [5]  6.00000  7.00000
MF      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [6]  7.00000  8.00000
HS      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [7]  8.00000  9.00000
FI      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [8]  9.00000 10.00000
NE      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [9] 10.00000 11.00000
ES      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00            [c]      [d]
IO      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [0]  1.23000  2.34000
FD      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [1]  2.00000  3.00000
IQ      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [2]  3.00000  4.00000
DN      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [3]  4.00000  5.00000
GK      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [4]  5.00000  6.00000
JP      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [5]  6.00000  7.00000
MM      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [6]  7.00000  8.00000
HJ      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [7]  8.00000  9.00000
FF      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [8]  9.00000 10.00000
NL      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   [9] 10.00000 11.00000
HE      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   array struct of test_a size is 2
IG      0       23:03:14.015    StructArray (EURUSD,M15)        2020.08.21 00:00:00   array struct of overshoot is 10
RO      0       23:03:14.016    StructArray (EURUSD,M15)        2020.08.21 00:00:00   test.csv file is available for writing
NL      0       23:03:14.016    StructArray (EURUSD,M15)        2020.08.21 00:00:00   File path: C:\Users\Administrator\AppData\Roaming\MetaQuotes\Tester\BB16F565FAAA6B23A20C26C49416FF05\Agent-127.0.0.1-3000\Files\


 

Consult this (mql5 code add property strict if you use it in mql4)

struct shoots
{
bool set;
double value;
datetime time;
shoots(void){set=false;value=0;time=0;}
};
shoots ShootsArray[];
int OnInit()
  {
//---
  //fill up with random data 
    ArrayResize(ShootsArray,20,0);
    //fill half
    for(int rd=0;rd<10;rd++)
    {
    //irrelevant stuff to your issue just getting data ,ignore from here ...
      ResetLastError();
      int error_sum=0;
      double h=iHigh(_Symbol,_Period,rd+1);
      error_sum+=GetLastError();
      datetime t=iTime(_Symbol,_Period,rd+1);
      error_sum+=GetLastError();
      if(error_sum==0)
      {
    //...until here 
      //fill your struct array 
        ShootsArray[rd].set=true;//has data
        ShootsArray[rd].value=h;//high
        ShootsArray[rd].time=t;//time
      }  
    }
  //fill up with random data ends here  
  //save 
  int method=1;
    //method 1 Human Readable Format : [i dont know if the ea can load it,havent tested/needed it]
    if(method==1)
    {
    int fop=FileOpen("test_struct_array.csv",FILE_WRITE|FILE_ANSI|FILE_CSV,",");
    if(fop==INVALID_HANDLE){Alert("Cant create file");ExpertRemove();}
    if(fop!=INVALID_HANDLE)
    {    
      //header
      FileWrite(fop,"Set","Time","Value");
      for(int x=0;x<ArraySize(ShootsArray);x++)
      {
      FileWrite(fop,ShootsArray[x].set,ShootsArray[x].time,ShootsArray[x].value);
      }
      FileClose(fop);
    }
    }
    //method 1 Human Readable Format ends here 
    //method 2 ,save load capacity
    if(method==2)
    {
    int fop=FileOpen("test_struct_array.extention",FILE_WRITE|FILE_BIN);
    if(fop==INVALID_HANDLE){Alert("Cant create file");ExpertRemove();}
    if(fop!=INVALID_HANDLE)
    {    
      FileWriteArray(fop,ShootsArray,0,ArraySize(ShootsArray));
      FileClose(fop);
    }    
    }
    //method 2 ,save load capacity ends here 
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  ArrayFree(ShootsArray);
  }
 

Thank you kind stranger.

The main issue was that when I didn't use the struct, the file was correctly written to the Terminal Files folder (presumably as well as the Tester/Files folder), so I was expecting to look in there each time.

When I DID use the struct, the file was only written to the Tester folder. I don't know why. However your tracing lines of code really helped me isolate what was happening.

I also don't yet understand the last properties (methods?) of the structs you used (probably because I am coming from C# not Cpp), but I am going to look them up now to see whether they also make a difference or are not required.

Much appreciated.

 
peaveyyyy:

Thank you kind stranger.

The main issue was that when I didn't use the struct, the file was correctly written to the Terminal Files folder (presumably as well as the Tester/Files folder), so I was expecting to look in there each time.

When I DID use the struct, the file was only written to the Tester folder. I don't know why. However your tracing lines of code really helped me isolate what was happening.

I also don't yet understand the last properties (methods?) of the structs you used (probably because I am coming from C# not Cpp), but I am going to look them up now to see whether they also make a difference or are not required.

Much appreciated.

You are welcome , the method int is just for testing ,its not required .

 
Lorentzos Roussos:

Consult this (mql5 code add property strict if you use it in mql4)

Just out of curiosity, do you really indent your code like this or is your translator modifying your indentations?

 
nicholish en:

Just out of curiosity, do you really indent your code like this or is your translator modifying your indentations?

ehehe ,yeah ,its a silly leftover from coding with notepad .

Reason: