существует ли какая-то функция "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)); }

Метод 2:

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

Вы должны знать только строковое имя перечисления в любом случае. Также ваш код неверен, перечисление начинается с 0.


 
cyberglassed:

Привет Алена, я удовлетворил твое любопытство :P

Представьте, что вы используете несколько внешних mql5-кодов, то вы имеете дело с несколькими типами данных "enum", определенными на них, и, конечно, как человеку, вам лучше помнить строковое имя каждого значения каждого "enum". Затем в какой-то части вы хотите указать значение какого-то перечисления в строковом формате, но вы не можете сделать это напрямую, поэтому вам придется использовать обходной путь, как я писал выше. Это имеет два больших недостатка, первый - вам нужно собрать все значения всех перечислений, и второй недостаток - это обслуживание, так что если вы обновите какой-то внешний код mql5, где разработчик изменил значение int, связанное с некоторым константным представлением, то вы можете получить неожиданное поведение, поэтому вам нужно постоянно проверять обновления кода.

Спасибо, но это не совсем то, о чем я просил. Можете ли вы выложить конкретный пример кода?

Я на 100% уверен, что все ваши замечания по поводу функции StringToEnum() исходят из плохой практики кодирования. Цель перечисления - построить код, не зависящий от базового целочисленного значения, если это значение изменяется, это никак не должно влиять на ваш код. Также я не понимаю, почему вы не можете запомнить идентификатор типа MODE_SMA, но можете запомнить строку "MODE_SMA".

Что касается темы утечки безопасности... Я не совсем согласен с тем, что вы сказали о том, что это открытая дверь для утечки безопасности. Конечно, это может быть открытой дверью, но вы как программист должны установить границы и позаботиться о возможных критических ситуациях, я имею в виду, что вы можете прекрасно справиться с такими ситуациями, как в PHP, даже в SQL с инъекцией кода, где вы должны разобрать некоторые критические возможные входные данные от пользователей в случае, если они имеют доступ к вашему коду.

Я не говорил, что безопасность не может управляться кодером. Я сказал, что Metaquotes не позволит этой безопасности полагаться на программистов. Этого никогда не произойдет, я предлагаю вам спросить их, разместив запрос в ServiceDesk, я уже знаю ответ.

 
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.

хахаха Марко и Ласло извините, иногда, когда пытаешься минимизировать проблему, любопытство с другой стороны возрастает :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).

Ласло, на mql5 смещение равно 1, а не 0 (отличается от mql4), я проверил это с помощью простого скрипта и был удивлен. Вот почему я говорю о проблеме обслуживания -> возможной путанице.
 
Alain Verleyen:

Спасибо, но это не совсем то, о чем я просил. Можете выложить конкретный пример кода?

Я на 100% уверен, что все ваши слова о функции StringToEnum() исходят из плохой практики кодирования. Цель перечисления - построить код, не зависящий от базового целочисленного значения, если это значение изменяется, это никак не должно влиять на ваш код. Также я не понимаю, почему вы не можете запомнить идентификатор типа MODE_SMA, но можете запомнить строку "MODE_SMA".

Я не говорил, что безопасность не может управляться кодером. Я сказал, что Metaquotes не позволит этой безопасности полагаться на программистов. Этого никогда не произойдет, я предлагаю вам спросить их, разместив запрос в ServiceDesk, я уже знаю ответ.

Я ошибался и столкнулся с ситуацией, когда мне понадобится функция StringToEnum() (общая, чтобы не кодировать для каждого перечисления). Никогда не поздно понять, я никогда не должен быть уверен на 100%.

 
Alain Verleyen:

Я ошибался и знаю, что столкнусь с ситуацией, когда мне понадобится функция StringToEnum() (общая, не кодируемая для каждого перечисления). Никогда не поздно понять, я никогда не должен быть уверен на 100%.

Хорошо. Вот общая функция 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 функция StringToEnum() :

Пример использования :

4,5 года спустя, но наткнулся на этот пост в поисках решения этой потребности для себя. @Alain Verleyen Я рад, что вы нашли применение в противовес вашим первоначальным ответам "не понимаю, зачем нам это нужно" и "если вам нужна эта функция, значит ваш код плох". 😛

Я столкнулся с целым рядом различных обстоятельств, когда это было бы полезно, но даже если бы ни вы, ни я не нашли в этом необходимости, возникает вопрос: если нет причин для существования StringToEnum(), то почему должны быть причины для существования EnumToString()? Или, наоборот, если EnumToString() существует, то, конечно, нет ничего удивительного в том, что могут возникнуть ситуации, когда мы будем преобразовывать перечисление в строку с помощью этой функции, а затем иногда захотим преобразовать его обратно? 😉.

Излишне говорить, что мой практический пример: у меня есть советник, который работает на нескольких комбинациях символов/таймфреймов одновременно, независимо от графика, на котором он запущен - без необходимости запускать его на нескольких графиках сразу. В таком подходе есть свои плюсы и минусы, но в моем случае плюсы определенно перевешивают минусы.

Итак... когда я размещаю сделку, я хочу видеть в комментариях к ней несколько деталей, которые не предоставляют функции Trade Info, одна из которых - таймфрейм, который использовался для определения логики размещения сделки, поскольку эта логика (часть которой зависит от таймфрейма) иногда влияет на то, когда модифицировать (например, SL) или закрыть сделку. Поэтому я хочу видеть эту информацию в человекочитаемой форме (например, H4, а не 14400), но, конечно, я также хочу, чтобы советник мог использовать числовое значение перечисления при принятии решений о модификации или закрытии сделки.

Поэтому я использую EnumToString(timeframe), чтобы иметь строковое представление таймфрейма в комментарии. Затем позже я могу получить комментарий к сделке с помощьюOrderComment() (или соответствующей версии mql5) и затем могу разобрать строковое представление таймфрейма из комментария, чтобы получить, например, "PERIOD_H4". Функция StringToEnum("...") преобразует его обратно в числовое значение, которое в случае таймфреймов является количеством минут (т.е. перечисление не является последовательным от 0 до чего-то, как большинство перечислений, есть большие промежутки, например, между D1, W1 и MN1). Конечно, я мог бы также включить целочисленное значение перечисления в комментарий, но это (что должно быть ненужным) обходной путь отсутствия 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
Причина обращения: