是否有一些 "StringToEnum "的函数或替代方法? - 页 3

 
cyberglassed:

你上面的代码是没用的,因为它总是返回 "b = 0"

和信息。每次 "b = 0 "都不能提供任何信息。

不,它返回3。


或者它遇到的最后一个信息。

我想你确实误解了我的意思。

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);
 

我没听错吧,你是用一个字符串开始的吗?

你也可以把它包起来()

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;}
 }

但你必须确保字符串是完全匹配的,原因显而易见,否则将需要更多的代码来确保它不会变得很糟糕。

 
Marco vd Heijden:

不,它返回3。

或它所遇到的最后一个人。

我想你确实误解了我的意思。

是的,在写完我的评论后,我注意到你没有使用 "else if",所以我改成了3。

Marco vd Heijden:

我说的对吗? 你用一个字符串开始?

你也可以把它包起来()。

但你必须确保字符串是完全匹配的,原因显而易见,否则将需要更多的代码来确保它不会变得很糟糕。

是的,我从一个字符串开始,这就是为什么我提议的函数 的签名是。

int StringToEnum(string strId);

总之,正如我们所分析的,到目前为止,我们唯一的解决办法是使用多个 "if";)

 

"然后在某些部分,你想以字符串格式 指定一些枚举的一些值。"

我看不出这有什么好处。你能举个例子吗?


方法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)); }

方法二。

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

在这两种情况下,你只需要知道枚举的字符串名称。你的代码也是错误的,这个枚举从0开始。


 
cyberglassed:

嗨,Alain,我满足你的好奇心 :P

想象一下,你正在使用多个外部mql5代码,然后你正在处理多个 "enum "数据类型的定义,当然,像人一样,你最好记住每个 "enum "的每个值的字符串名称。然后在某些部分,你想用字符串格式指定某个枚举的某些值,那么你不能直接这样做,所以你必须使用我上面写的一些变通方法。这有两个很大的缺点,第一个是你必须收集所有涉及到的枚举的所有值,第二个缺点是维护,所以如果你更新了一些外部的mql5代码,开发人员改变了与一些常数表示相关的int值,那么你可能会得到意想不到的行为,所以你必须不断检查代码的更新。

谢谢,但这并不是我所要求的。你能贴出一个具体的代码例子吗?

我100%肯定你关于StringToEnum()函数的观点来自于错误的编码实践。枚举的目的是建立独立于底层整数值的代码,如果这个值被改变,不应该以任何方式影响你的代码。我也不明白为什么你不能记住像MODE_SMA这样的标识符,但你可以用一个字符串 "MODE_SMA"。

关于安全漏洞的话题...我并不完全同意你所说的它是一扇安全漏洞的大门。当然,它可能是一扇开放的大门,但作为程序员,你必须设定限制,并照顾到可能的关键情况,我的意思是你可以完美地管理这种情况,如在PHP中,甚至在SQL中的代码注入,你必须解析一些可能来自用户的关键输入数据,以防他们访问你的代码。

我没有说安全问题不能由编码者管理。我说的是Metaquotes不会让安全问题依赖于程序员。这永远不会发生,我建议你向服务台提出请求,我已经知道答案。

 
cyberglassed:

是的,在写完我的评论后,我注意到你没有使用 "else if",所以我改成了3。

是的,我从一个字符串开始,这就是为什么我提议的函数的签名是。

总之,正如我们所分析的,到目前为止,我们唯一的解决办法是使用多个 "if";)


是的,但你也可以将其循环起来,只用 一行 能完成。

 //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);}} 
}


但在将近4页之后,仍然......为什么呢,哈哈 :)

 
Marco vd Heijden:

是的,但你也可以把它循环起来,只用 一行 来做。

但在将近4页之后,仍然......为什么呢,哈哈 :)

Laszlo Tormasi:

"然后在某些部分,你想以字符串格式指定一些枚举的一些值。"

我看不出这有什么好处。你能举个例子吗?

在这两种情况下,你必须只知道枚举的字符串名称。另外你的代码是错误的,这个枚举从0开始。

哈哈哈,MarcoLaszlo,对不起,有时候当我们试图将问题最小化的时候,另一方的好奇心就会增加 :P

这里有一个非常接近我想要得到的东西的例子(为了防止烦扰你们所有人,我把它缩小了一点)。以下是一个完整的工作脚本(复制/粘贴/运行)。

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);
}

价格的类型将被设置在在线文件上。"config_url",其内容可以在任何时候用以下值之一来改变。

{price_close, price_open, price_high, price_low, price_median, price_typical, price_weighted}。

该类型将以人类可读的形式给出,例如。PRICE_MEDIAN(不是一个int)。

Laszlo,在mql5上,偏移量是1而不是0(与mql4不同),我用一个简单的脚本检查过,结果很惊讶。这就是为什么我说维护的问题------可能的混乱。
 
Alain Verleyen:

谢谢,但这并不是我所要求的。你能发一个具体的代码例子吗?

我100%肯定你关于StringToEnum()函数的观点来自于错误的编码实践。枚 举的目的是建立独立于底层整数值的代码,如果这个值被改变,不应该以任何方式影响你的代码。我也不明白为什么你不能记住像MODE_SMA这样的标识符,但你可以用一个字符串 "MODE_SMA"。

我没有说安全问题不能由编码者管理。我说的是Metaquotes不会让安全问题依赖于程序员。这永远不会发生,我建议你向服务台提出请求,我已经知道答案。

我错了,我知道我面临的情况是需要一个StringToEnum()函数(通用的,不需要为每个枚举编码)。理解永远不会太晚,我不应该100%确定。

 
Alain Verleyen:

我错了,我知道在这种情况下我需要一个StringToEnum()函数(通用的,不需要为每个枚举编码)。理解永远不会太晚,我不应该100%确定。

Ok.这里有一个通用的StringToEnum()函数

#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);
  }

使用实例。

//+------------------------------------------------------------------+
//| 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 函数。

使用实例。

4.5年后,却看到了这个帖子,为自己的这个需求寻找一个解决方案。@Alain Verleyen 我很高兴你找到了一个用途来反驳你最初的 "看不出我们为什么需要这个 "和 "如果你需要这个函数,那么你的代码就很糟糕 "的反应。

我遇到过许多不同的情况,在这些情况下,这个函数会很有用,但即使你和我都没有发现需要,还有一个问题:如果没有理由让StringToEnum()存在,为什么应该有理由让EnumToString()存在?或者反过来说,如果EnumToString()存在,那么我们可能会在某些时候使用该函数将枚举转换为字符串,然后有时又想将其转换回来,这肯定不是没有道理的。 😉

不用说,我的实际例子:我有一个EA,可以同时在多个符号/时间框架组合上操作,与它所运行的图表无关--无需同时在多个图表上运行它。这种方法有利有弊,但在我看来,利大于弊。

所以......当我进行交易时,我想在交易的评论中看到交易信息功能没有提供的一些细节,其中之一是用来确定是否首先进行交易的逻辑的时间框架,因为这种逻辑(其中一些取决于时间框架)有时会影响到何时修改(例如SL)或关闭交易。所以我想以人类可读的形式看到这些信息(例如H4,而不是14400),当然我也希望EA在做出修改或关闭交易的决定时能够利用数字枚举值。

所以我使用EnumToString(timeframe),在注释中用字符串表示时间框架。然后,我可以使用OrderComment()(或相应的mql5版本) 从交易中获得评论,然后可以从评论中解析出时间框架的字符串表示,以获得例如 "PERIOD_H4"。 StringToEnum("...")函数会将其转换为数值,在时间框架的情况下是分钟数(即, enum不是从连续的角度看的)。当然,我也可以在注释中包含枚举的整数值,但这是一个没有StringToEnum()的(应该是不必要的)解决方法。)

你的解决方案目前看来已经很好了,只是在这种情况下,我们必须把MAX值增加到43200,才能在保持通用性的前提下全面覆盖(https://docs.mql4.com/constants/chartconstants/enum_timeframes)

当然,OrderTimeframe()或OrderPeriod()函数可以满足这一特定需求,但正如我所说,这只是StringToEnum()函数有帮助的几种情况之一。 显然,你也找到了一个。

谢谢你分享你的解决方案,也感谢你谦虚地承认自己的错误。

我想知道在MQL4/5文档中是否有一些所有可能的枚举和枚举值的列表。有这个:https://www.mql5.com/en/docs/constant_indices 和该页面的相应的mql4版本,尽管它没有列出任何数字值。我想我可以复制那个页面的文本,把它全部解析成一个值的列表,然后写一个函数来打印所有可能的值。 但当然这有点繁琐,而且没有考虑到未来的任何增加。 至少它可以告诉我任何枚举的最大可能值。

为了节省速度,我也许可以改编你的函数,使其循环处理所有的值,比如说,1440,而不是256(在时间框架的情况下是D1,在其他枚举的情况下是其他什么),然后为W1和MN1增加两个特定的检查。 增加最大值不会给所有仍然适合较低最大值的情况增加任何开销,因为无论如何,任何适合较低最大值的东西都会在相同的时间内走出循环。

是否有任何其他的枚举的数值高于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