StringToShortArray() issue

 

It took me a while to figure out the bug in my code,

but it boils down to StringToShortArray() function


this is the test:

void test_strings()
{
    ushort a[];
    int alen = 0;
    string s = "michael";
    StringToShortArray(s, a);
    printf("string '%s' has len %i    array a has len %i", s, StringLen(s), ArraySize(a));
    
    //result: string 'michael' has len 7    array a has len 8
}


What's going on?

The docs about this function, don't mention anything about the length change


Is this a bug? or is this really the decision of mql5 developers?

 
Terminal 0 will also be copied to the recipient array, in this case the size of a dynamic array can be increased if necessary to the size of the string.



I missed this part in function's docs.

As I see it, another bad decision of MQL5 team.
Why on earth add the terminal 0 character to the string, it's beyond me.

 
Florin Ionesko:

It took me a while to figure out the bug in my code,

but it boils down to StringToShortArray() function


this is the test:


What's going on?

The docs about this function, don't mention anything about the length change


Is this a bug? or is this really the decision of mql5 developers?

The debugger does not seem to allow one to inspect the array variables during runtime (unless I am missing a trick) so I added a printf loop to see what was in your array - there does seem to be a blank position at the end.

When I looked at help for StringToShortArray, I noticed there are extra arguments which specify the start and end of the string - in particular i t:

"count=-1

[in]  Number of array elements to copy. Defines length of a resulting string. Default value is -1, which means copying up to the array end, or till terminal 0.Terminal 0 will also be copied to the recipient array, in this case the size of a dynamic array can be increased if necessary to the size of the string. If the size of the dynamic array exceeds the length of the string, the size of the array will not be reduced."

Therefore by specifying this you can avoid the trailing blank(s):     StringToShortArray(s, a, 0, StringLen(s));

Here is the code if you wanna play around with it:


//+------------------------------------------------------------------+

void OnStart()

  {

//---

   test_strings();  

  }

//+------------------------------------------------------------------+


void test_strings()

{

    ushort a[];

    int alen = 0;

    string s = "michael";

    StringToShortArray(s, a, 0, StringLen(s));

    printf("string '%s' has len %i    array a has len %i", s, StringLen(s), ArraySize(a));

    //result: string 'michael' has len 7    array a has len 8

    

    for (int i=0; i < ArraySize(a); i++)

    {

      printf("a[%d] = %s Ascii Value (dec)= %s",  i, CharToStr (a[i]), string (a[i]) );

    }

    

}

 

thanks for point that out,

i tested your way too,

StringToShortArray(s, a, 0, StringLen(s));

and this way, ArraySize(a) shows 7, as expected

but this style defeats the purpose of what StringToShortArray() should do by default

Programmer should not take care of this detail, if by default, the intuitive way is for a[] to have 7 codes, for each digits

that's why i said: why on earth did they choose to add that 0 or blank at the end?

it's totally unintuitive, but MQL5 style since i am programming in it, they always insist to mess defaults, just because.

"noooo, we cannot follow best practices, we are unique" :D

yeah ok

power to Ctrader, I hope they will take over metatrader someday :D

 
Florin Ionesko:

why on earth did they choose to add that 0 or blank at the end?

https://en.wikipedia.org/wiki/Null-terminated_string

Null-terminated string - Wikipedia
  • en.wikipedia.org
The length of a C string is found by searching for the (first) NUL byte. This can be slow as it takes O(n) (linear time) with respect to the string length. It also means that a string cannot contain a NUL character (there is a NUL in memory, but it is after the last character, not "in" the string). Null-terminated strings were produced by the...
 
Florin Ionesko:

thanks for point that out,

i tested your way too,

and this way, ArraySize(a) shows 7, as expected

but this style defeats the purpose of what StringToShortArray() should do by default

Programmer should not take care of this detail, if by default, the intuitive way is for a[] to have 7 codes, for each digits

that's why i said: why on earth did they choose to add that 0 or blank at the end?

it's totally unintuitive, but MQL5 style since i am programming in it, they always insist to mess defaults, just because.

"noooo, we cannot follow best practices, we are unique" :D

yeah ok

power to Ctrader, I hope they will take over metatrader someday :D

Yes - every language has it peculiarities.

Some of the worst are the big software companies who ship code which is undocumented or failing... After many frustrating experiences over the years I find it just better to accept the imperfections and find ways to make it work the way you want :)

 
Very good point! Legacy rules!
 
Metatrader should help traders be better traders, not experts in clang

That was my whole point. 

But fair enough
Barking at the moon is not that efficient :d

To keep a sane code, easy to read afterwards, I'm always forced to make wrapper functions around these weird choices of mql5 team
 
Florin Ionesko:
Metatrader should help traders be better traders, not experts in clang

That was my whole point. 

But fair enough
Barking at the moon is not that efficient :d

To keep a sane code, easy to read afterwards, I'm always forced to make wrapper functions around these weird choices of mql5 team
Yes you are right - C is a legacy language and has its quirks but also its strengths.

Newer languages (eg. python, Golang, javascript, etc) make it so much easier in my experience - perhaps one day we will see implementations in newer languages...
 

The point is that a most dll's require null terminated strings. You'll see plenty of libraries that convert MQL strings to null terminate strings for DLL consumption using these techniques. Example:

https://github.com/dingmaotu/mql4-lib/blob/master/Lang/Native.mqh#L171:L177

void StringToUtf8(const string str,uchar &utf8[],bool ending=true)
  {
   if(!ending && str=="") return;
   int count=ending ? -1 : StringLen(str);
   StringToCharArray(str,utf8,0,count,CP_UTF8);
  }
dingmaotu/mql4-lib
dingmaotu/mql4-lib
  • dingmaotu
  • github.com
MQL4 Foundation Library For Professional Developers - dingmaotu/mql4-lib
Reason: