is there some "StringToEnum" function or an alternative? - page 3

 
cyberglassed:

your code above is useless because it will always return "b = 0"

and the info: "b = 0" every time doesn't give any information.

no it returns 3.


or the last one it encounters.

i guess you do misunderstand me.

sinput string e_string="MODE_SMMA";// Input Ma Method

int b;
if(e_string==EnumToString(MODE_SMA)){b=0;}
if(e_string==EnumToString(MODE_EMA)){b=1;}
if(e_string==EnumToString(MODE_SMMA)){b=2;}
if(e_string==EnumToString(MODE_LWMA)){b=3;}

Print(b);
 

did i get that right? you start with a string ??

you can also wrap it up ()

int b;
sinput string e_string;// Input Ma Method here AS A STRING 

void OnTick(){StringToEnum();Print(b);} 
  
void StringToEnum()
 {
 if(e_string==EnumToString(MODE_SMA)){b=0;}
 if(e_string==EnumToString(MODE_EMA)){b=1;}
 if(e_string==EnumToString(MODE_SMMA)){b=2;}
 if(e_string==EnumToString(MODE_LWMA)){b=3;}
 }

but you had to make sure the string is an exact match for obvious reasons, or it will need more code to make sure it doesn't go funky.

 
Marco vd Heijden:

no it returns 3.

or the last one it encounters.

i guess you do misunderstand me.

yes, after write my comment I noticed you didn't use "else if" and I changed to 3

Marco vd Heijden:

did i get that right? you start with a string ??

you can also wrap it up ()

but you had to make sure the string is an exact match for obvious reasons, or it will need more code to make sure it doesn't go funky.

yes, I start from an string, that's why the signature of the function I propose is:

int StringToEnum(string strId);

anyway, as we all have analyzed, the only workaround we have until now is by using multiple "if" ;)

 

"Then on some part you wanna specify some value of some enum in string format."

I don't see any advantage of this. Could you show an example?


Method 1:

int StringToEnum(string strId) {         if (false) {}         else if (strId == "PRICE_CLOSE")     return 1;         else if (strId == "PRICE_OPEN")      return 2;         else if (strId == "PRICE_HIGH")      return 3;         else if (strId == "PRICE_LOW")       return 4;         else if (strId == "PRICE_MEDIAN")    return 5;         else if (strId == "PRICE_TYPICAL")   return 6;         else if (strId == "PRICE_WEIGHTED")  return 7;         // ...         return -1; } void OnStart() {         string strId = "PRICE_MEDIAN";         printf("%s: %d ", strId, StringToEnum(strId)); }

Method 2:

void OnStart() {
        ENUM_APPLIED_PRICE b=PRICE_MEDIAN;
        
        printf("%s: %d ", EnumToString(b), b);
}

You have to know only the string name of the enum in either case. Also your code is wrong this enum starts from 0.


 
cyberglassed:

Hi Alain, I satisfy your curiosity :P

Imagine you are using multiple external mql5 code, then you are dealing with multiple "enum" data types defined on them, and of course, like a human, it is better for you to remember the string name of each value of each "enum". Then on some part you wanna specify some value of some enum in string format, then you can't do it directly, so you have to use some workaround as I wrote above. This have two big disadvantages the first one is you have to collect all values of all enums involved and the second disadvantage is the maintenance, so if you update some external mql5 code where the developer changed the int value associated to some constant representation then you could get unexpected behaviour so you have to keep inspecting for updates on the code.

Thanks but it's not really what I asked for. Can you post a concrete code example ?

I am 100% sure all your point about StringToEnum() function come from a bad coding practice. The goal of an enum is to build code independent of the underlying integer value, if this value is changed that should not impact your code in any way. Also I don't see why you can't remember an identifier like MODE_SMA but you can with a string "MODE_SMA".

About the security leak topic... I'm not totally agree with what you said about it is an open door to security leak. Of course it could be an open door, but you as programmer has to set the limits and take care of possible critical situations, I mean you can manage perfectly such situations like in PHP, even on SQL with code injection where you have to parse some critical possible input data from users in case they have access to your code.

I didn't say the security can't be managed by the coder. I said that Metaquotes WON'T allow that security to rely on the programmers. That will never happen, I suggest you to ask them by posting your a request to the ServiceDesk, I already know the answer.

 
cyberglassed:

yes, after write my comment I noticed you didn't use "else if" and I changed to 3

yes, I start from an string, that's why the signature of the function I propose is:

anyway, as we all have analyzed, the only workaround we have until now is by using multiple "if" ;)


yes but you can also loop that up and do it in just one line.

 //string in="MODE_SMA";  //uncheck either one
 //string in="MODE_EMA";
 string in="MODE_SMMA";
 //string in="MODE_LWMA";    

void OnTick()

{
 int out;
 
 for(int i=0;i<=3;i++){ENUM_MA_METHOD mode=i;if(in==EnumToString(mode)){out=i;Print("out: ",out);}} 
}


but still after almost 4 pages ...whyyyy haha :)

 
Marco vd Heijden:

yes but you can also loop that up and do it in just one line.

but still after almost 4 pages ...whyyyy haha :)

Laszlo Tormasi:

"Then on some part you wanna specify some value of some enum in string format."

I don't see any advantage of this. Could you show an example?

You have to know only the string name of the enum in either case. Also your code is wrong this enum starts from 0.

hahaha Marco and Laszlo sorry, sometimes when trying to minify the problem the curiosity on the other side increases :P

here you have a very near example of what I want to get (I have minified it a little to prevent annoying all you). The following is a complete working script (copy/paste/run):

string get_price_type() {
        string
                config_url = "http://tempsend.com/D56DA3A9EA/CBB5/config.txt", /* available for 30 days from now */
                cookie = NULL,
                headers,
                ret;
        char
                post[],
                result[];               

        // WebRequest needs the following configuration:
        // 1- check: Tools/Options/Expert Advisors/Allow WebRequest for listed URL
        // 2- add url: http://tempsend.com  [this is the domain name on: config_url]
        int res = WebRequest("GET", config_url, cookie, NULL, 5000,  post, 0, result, headers);
        
        if (res == -1) {
                Print("Error in WebRequest. Error code: ", GetLastError());
                ret = "Error";
        }
        else {
                ret = CharArrayToString(result);
                StringTrimRight(ret);
        }
        return ret;
}

int StringToEnum(string strId) {
        if (false) {}
        else if (strId == "PRICE_CLOSE")     return 1;
        else if (strId == "PRICE_OPEN")      return 2;
        else if (strId == "PRICE_HIGH")      return 3;
        else if (strId == "PRICE_LOW")       return 4;
        else if (strId == "PRICE_MEDIAN")    return 5;
        else if (strId == "PRICE_TYPICAL")   return 6;
        else if (strId == "PRICE_WEIGHTED")  return 7;
        return -1;
}

void OnStart() {
        string price_type = get_price_type();
        int price_type_int = StringToEnum(price_type);
        printf("price_type -> %s: %d", price_type, price_type_int);
        
        ChartSetInteger(0, CHART_SCALE, 3);
        ChartSetInteger(0, CHART_MODE, CHART_CANDLES);

        int handle = iMA("EURUSD", PERIOD_CURRENT, 10, 0, MODE_SMA, price_type_int);
        ChartIndicatorAdd(0, 0, handle);
}

the type of price will be set on the online file given on: "config_url" and its content can be changed at any time with one of the following values:

{PRICE_CLOSE, PRICE_OPEN, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED}

The type will be given in human readable form, for example: PRICE_MEDIAN (not an int).

Laszlo, on mql5 the offset is 1 and not 0 (different to mql4), I have checked it with a simple script and got surprised. That's why I talk about the problem of maintenance -> possible confussions.
 
Alain Verleyen:

Thanks but it's not really what I asked for. Can you post a concrete code example ?

I am 100% sure all your point about StringToEnum() function come from a bad coding practice. The goal of an enum is to build code independent of the underlying integer value, if this value is changed that should not impact your code in any way. Also I don't see why you can't remember an identifier like MODE_SMA but you can with a string "MODE_SMA".

I didn't say the security can't be managed by the coder. I said that Metaquotes WON'T allow that security to rely on the programmers. That will never happen, I suggest you to ask them by posting your a request to the ServiceDesk, I already know the answer.

I was wrong and I am know facing a situation where I would need a StringToEnum() function (generic not to be coded for each enum). Never too late to understand, I should never be 100% sure

 
Alain Verleyen:

I was wrong and I am know facing a situation where I would need a StringToEnum() function (generic not to be coded for each enum). Never too late to understand, I should never be 100% sure

Ok. Here is a generic StringToEnum() function :

#define MIN_ENUM_VALUES 0
#define MAX_ENUM_VALUES 255
//+------------------------------------------------------------------+
//| StringToEnum : Convert a string to an ENUM value,                |
//|   it loop between min(0) and max(255), adjustable if needed.     |
//|   Non existing enum value defined as -1. If -1 is used as an     |
//|   enum value, code need to be adjusted to an other default.      |
//| Parameters :                                                     |
//|   in       - string to convert                                   |
//|   out      - ENUM value                                          |
//|   @return  - true if conversion succeed, false otherwise         |
//+------------------------------------------------------------------+
template<typename ENUM>
bool StringToEnum(string in,ENUM &out)
  {
   out=-1;
//---
   for(int i=MIN_ENUM_VALUES;i<=MAX_ENUM_VALUES;i++)
     {
      ENUM enumValue=(ENUM)i;
      if(in==EnumToString(enumValue))
        {
         out=enumValue;
         break;
        }
     }
//---
   return(out!=-1);
  }

Usage example :

//+------------------------------------------------------------------+
//| testing enums                                                    |
//+------------------------------------------------------------------+
enum ENUM_TEST
  {
   FIRST_CASE=1,
   SECOND_CASE=2

  };
//---
enum ENUM_ANOTHER_TEST
  {
   CASE_ONE,
   CASE_TWO,
   CASE_THREE
  };
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void  OnStart()
  {
   ENUM_TEST which;
   if(!StringToEnum("SECOND_CASE",which)) return;

   ENUM_ANOTHER_TEST which_other;
   if(!StringToEnum("CASE_ONE",which_other)) return;

   ENUM_TEST wrongwhich;
   if(!StringToEnum("blah blah",wrongwhich)) return;

//---
  }
 
Alain Verleyen #:

Ok. Here is a generic StringToEnum() function :

Usage example :

4.5 years later, but came across this post looking for a solution to this need for myself. @Alain Verleyen I'm glad you found a use to counter your initial "can't see why we need this" and "if you need this function, then your code is bad" responses. 😛

I have come across a number of different circumstances where this would be useful, but even if you, nor I, had never found a need, there is the question: if there's no reason for StringToEnum() to exist, why should there be any reason for EnumToString() to exist?  Or conversely, if EnumToString() exists, then surely it's not unreasonable to think that there might be times we'd convert an enum to a string using that function, and then want to convert it back sometimes? 😉 

Needless to say, my practical example:  I have an EA that operates on multiple symbol/timeframe combinations, at once, independent of the chart it's running on -- without having to run it on multiple charts at once. There are pros and cons to that approach, but in my case the pros definitely outweigh the cons.

So... when I place a trade I want to see in the comments of the trade a few details about it that the Trade Info functions don't provide, one of which is the timeframe that was used to determine the logic of whether to place the trade in the first place, as that logic (some of which depends on the timeframe) will sometimes affect when to modify (eg. SL) or close the trade. So I want to see that info in a human-readable form (eg. H4, not 14400), but of course I also want the EA to be able to make use of the numeric enum value when making decisions about modifying or closing the trade.  

So I use EnumToString(timeframe) to have a string representation of the timeframe in the comment. Then later I can get the comment from the trade using the OrderComment() (or the corresponding mql5 version) and can then parse out the string representation of the timeframe from the comment to get eg. "PERIOD_H4".  A StringToEnum("...") function would convert that back to the numerical value, which in the case of timeframes is the number of minutes (ie. the enum is not sequential from 0 to something like most enums, there are large gaps, eg. between D1, W1 and MN1).  Of course I could also include the enum integer value in the comment as well, but that's a (what should be unnecessary) workaround of the absence of StringToEnum().

Your solution seems to be as good as it gets at the moment, except that in this case, we'd have to increase the MAX value to 43200 to be comprehensive enough to cover that while remaining generic (https://docs.mql4.com/constants/chartconstants/enum_timeframes).

Of course an OrderTimeframe() or OrderPeriod() function would meet that specific need, but as I say it's just one of a few circumstances where a StringToEnum() function would be helpful.  Apparently you found one also. 😉 

Thanks for sharing your solution.  And kudos to you for your humility in admitting you were wrong. 😊 

I wonder if there's some list of all possible enums and enum values somewhere in the MQL4/5 documentation.  There's this: https://www.mql5.com/en/docs/constant_indices and the corresponding mql4 version of that page, although it doesn't list any of the numeric values.  I suppose I could copy the text of that page, parse it all out int a list of the values, and write a function to print all the possible values.  But of course that's a bit tedious, plus doesn't account for any future additions.  At least it'll tell me the maximum possible value of any enum.

To save speed I could probably adapt your function to loop through all values up to a max of, say, 1440 instead of 256 (for D1 in the case of timeframes, and whatever else in the case of other enums), and then add two more specific checks for W1 and MN1.  Increasing the max won't add any overhead to all cases that would still fit in the lower max, since anything that fits under the lower max gets out of the loop in the same time either way, anyway.

Are there any other enums with numerical values that go higher than 1440?

Chart Timeframes - Chart Constants - Constants, Enumerations and Structures - MQL4 Reference
Chart Timeframes - Chart Constants - Constants, Enumerations and Structures - MQL4 Reference
  • docs.mql4.com
Chart Timeframes - Chart Constants - Constants, Enumerations and Structures - MQL4 Reference
Reason: