existe alguma função "StringToEnum" ou uma alternativa? - página 3

 
cyberglassed:

seu código acima é inútil porque ele sempre retornará "b = 0".

e as informações: "b = 0" toda vez que não dá nenhuma informação.

não retorna 3.


ou a última que encontra.

Acho que você me entendeu mal.

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

Eu entendi bem? você começa com um fio ??

você também pode embrulhá-lo ()

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

mas você tinha que ter certeza de que a corda é exatamente igual por razões óbvias, ou precisará de mais código para ter certeza de que não vai ficar funky.

 
Marco vd Heijden:

não, ela retorna 3.

ou o último que encontra.

Acho que você me entendeu mal.

sim, depois de escrever meu comentário notei que você não usou "senão se" e mudei para 3

Marco vd Heijden:

Eu entendi bem? você começa com um fio ??

você também pode embrulhá-lo ()

mas é preciso ter certeza de que a string é uma correspondência exata por razões óbvias, ou precisará de mais código para garantir que não fique funky.

sim, eu parto de um fio, é por isso que a assinatura da função que eu proponho é:

int StringToEnum(string strId);

de qualquer forma, como todos nós já analisamos, a única solução que temos até agora é usar múltiplos "se" ;)

 

"Então, em alguma parte, você quer especificar algum valor de algum enumero em formato de corda".

Não vejo nenhuma vantagem nisto. Você poderia mostrar um exemplo?


Método 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)); }

Método 2:

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

Você tem que saber apenas o nome da seqüência de caracteres em ambos os casos. Também seu código está errado, este enumero começa a partir de 0.


 
cyberglassed:

Oi Alain, eu satisfaço sua curiosidade :P

Imagine que você está usando múltiplos códigos mql5 externos, então você está lidando com múltiplos tipos de dados "enum" definidos neles, e é claro, como um humano, é melhor que você se lembre do nome da cadeia de cada valor de cada "enum". Então, em alguma parte você quer especificar algum valor de algum enum em formato de string, então você não pode fazê-lo diretamente, então você tem que usar algum trabalho como eu escrevi acima. Isto tem duas grandes desvantagens a primeira é que você tem que coletar todos os valores de todos os enumeros envolvidos e a segunda desvantagem é a manutenção, então se você atualizar algum código mql5 externo onde o desenvolvedor mudou o valor int associado a alguma representação constante, então você pode ter um comportamento inesperado, então você tem que continuar inspecionando por atualizações no código.

Obrigado, mas não é realmente o que eu pedi. Você pode postar um exemplo concreto de código?

Estou 100% certo de que todas as suas observações sobre a função StringToEnum() vêm de uma má prática de codificação. O objetivo de um enum é construir um código independente do valor inteiro subjacente, se este valor for alterado que não deve afetar seu código de forma alguma. Também não vejo porque você não se lembra de um identificador como MODE_SMA, mas você pode com uma string "MODE_SMA".

Sobre o tópico vazamento de segurança... Não estou totalmente de acordo com o que você disse sobre o assunto é uma porta aberta para o vazamento de segurança. Claro que poderia ser uma porta aberta, mas você como programador tem que definir os limites e cuidar de possíveis situações críticas, quero dizer que você pode gerenciar perfeitamente tais situações como em PHP, mesmo em SQL com injeção de código onde você tem que analisar alguns dados críticos possíveis de entrada dos usuários caso eles tenham acesso ao seu código.

Eu não disse que a segurança não pode ser gerenciada pelo codificador. Eu disse que as Metaquotas NÃO permitem que essa segurança confie nos programadores. Isso nunca acontecerá, sugiro que você os pergunte colocando seu pedido no ServiceDesk, eu já sei a resposta.

 
cyberglassed:

sim, depois de escrever meu comentário notei que você não usou "senão se" e mudei para 3

sim, eu parto de um fio, é por isso que a assinatura da função que eu proponho é:

de qualquer forma, como todos nós já analisamos, a única solução que temos até agora é usar múltiplos "se" ;)


sim, mas você também pode fazer isso em laço e fazê-lo em apenas uma linha.

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


mas ainda depois de quase 4 páginas ...whyyyy haha :)

 
Marco vd Heijden:

sim, mas você também pode fazer isso em uma linha.

mas ainda depois de quase 4 páginas ...whyyyy haha :)

Laszlo Tormasi:

"Então em alguma parte você quer especificar algum valor de algum enumero em formato de corda".

Eu não vejo nenhuma vantagem nisso. Você poderia mostrar um exemplo?

Você só precisa saber o nome do enumeral em ambos os casos. Além disso, seu código está errado, este enumero começa a partir de 0.

hahaha Marco e Laszlo desculpe, às vezes quando se tenta minimizar o problema a curiosidade do outro lado aumenta :P

aqui você tem um exemplo muito próximo do que eu quero obter (eu o minifiquei um pouco para evitar irritar a todos vocês). O seguinte é um roteiro de trabalho completo (copiar/colar/colar/correr):

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

o tipo de preço será definido no arquivo online dado em: "config_url" e seu conteúdo pode ser alterado a qualquer momento com um dos seguintes valores:

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

O tipo será dado em forma legível pelo ser humano, por exemplo: PRICE_MEDIAN (não uma int).

Laszlo, em mql5 o offset é 1 e não 0 (diferente de mql4), eu o verifiquei com um simples script e fiquei surpreso. É por isso que eu falo sobre o problema de manutenção -> possíveis confusões.
 
Alain Verleyen:

Obrigado, mas não é realmente o que eu pedi. Você pode postar um exemplo concreto de código?

Estou 100% certo de que todas as suas observações sobre a função StringToEnum() vêm de uma má prática de codificação. O objetivo de um enum é construir um código independente do valor inteiro subjacente, se este valor for alterado que não deve afetar seu código de forma alguma. Também não vejo porque você não se lembra de um identificador como MODE_SMA, mas você pode com uma string "MODE_SMA".

Eu não disse que a segurança não pode ser gerenciada pelo codificador. Eu disse que as Metaquotas NÃO permitem que essa segurança confie nos programadores. Isso nunca acontecerá, sugiro que você os pergunte colocando seu pedido no ServiceDesk, eu já sei a resposta.

Eu estava errado e sei que diante de uma situação em que precisaria de uma função StringToEnum() (genérica a não ser codificada para cada enumeração). Nunca é tarde demais para entender, eu nunca deveria estar 100% certo

 
Alain Verleyen:

Eu estava errado e sei que diante de uma situação onde eu precisaria de uma função StringToEnum() (genérica para não ser codificada para cada enumeração). Nunca é tarde demais para entender, eu nunca deveria estar 100% certo

Ok. Aqui está uma função genérica 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);
  }

Exemplo de uso :

//+------------------------------------------------------------------+
//| 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 função genérica StringToEnum() :

Exemplo de uso :

4,5 anos depois, mas encontrei este posto procurando uma solução para esta necessidade por mim mesmo. @Alain Verleyen Fico feliz que você tenha encontrado um uso para contrariar suas respostas iniciais de "não conseguimos ver porque precisamos disto" e "se você precisa desta função, então seu código é ruim". 😛

Encontrei várias circunstâncias diferentes onde isto seria útil, mas mesmo que você, nem eu, nunca tivesse encontrado uma necessidade, existe a pergunta: se não há nenhuma razão para StringToEnum() existir, por que haveria alguma razão para EnumToString() existir? Ou inversamente, se EnumToString() existe, então certamente não é descabido pensar que pode haver vezes em que converteríamos um enum para uma string usando essa função, e depois queremos convertê-lo de volta às vezes? 😉

Escusado será dizer, meu exemplo prático: tenho um EA que opera em múltiplas combinações símbolo/tempo, de uma só vez, independente do gráfico em que está rodando -- sem ter que rodá-lo em múltiplos gráficos de uma só vez. Há prós e contras a essa abordagem, mas no meu caso os prós definitivamente compensam os contras.

Assim... quando coloco uma troca, quero ver nos comentários da troca alguns detalhes sobre ela que as funções de Informação Comercial não fornecem, um dos quais é o prazo que foi usado para determinar a lógica de colocar a troca em primeiro lugar, já que essa lógica (algumas das quais dependem do prazo) às vezes afetará quando modificar (por exemplo, SL) ou fechar a troca. Portanto, quero ver essa informação de uma forma legível para o ser humano (por exemplo, H4, não 14400), mas é claro que também quero que a EA seja capaz de fazer uso do valor do enumero numérico ao tomar decisões sobre a modificação ou o fechamento do comércio.

Por isso, uso o EnumToString (prazo) para ter uma representação em cadeia do prazo no comentário. Mais tarde, posso obter o comentário da negociação usando oOrderComment() (ou a versão mql5 correspondente) e posso então analisar a representação em cadeia do período de tempo do comentário para obter, por exemplo, "PERÍODO_H4". Uma função StringToEnum("...") converteria isso de volta para o valor numérico, que no caso de períodos de tempo é o número de minutos (ou seja, o número de minutos). O enum não é sequencial de 0 para algo como a maioria dos enumeros, existem grandes lacunas, por exemplo, entre D1, W1 e MN1). Claro que eu poderia incluir o valor inteiro do enum também no comentário, mas isso é uma alternativa (que deveria ser desnecessária) à ausência do StringToEnum().

Sua solução parece ser tão boa quanto a atual, exceto que, neste caso, teríamos que aumentar o valor MAX para43200 para ser suficientemente abrangente para cobrir isso enquanto permanecermos genéricos(https://docs.mql4.com/constants/chartconstants/enum_timeframes).

É claro que uma função OrderTimeframe() ou OrderPeriod() atenderia a essa necessidade específica, mas como eu digo é apenas uma das poucas circunstâncias em que uma função StringToEnum() seria útil. Aparentemente você encontrou uma também. 😉

Obrigado por compartilhar sua solução. E elogio a você por sua humildade em admitir que estava errado. 😊

Pergunto-me se há alguma lista de todos os possíveis enumeros e valores enuméricos em algum lugar na documentação MQL4/5. Há o seguinte:https://www.mql5.com/en/docs/constant_indices e a versão mql4 correspondente daquela página, embora não liste nenhum dos valores numéricos. Suponho que eu poderia copiar o texto daquela página, analisar tudo numa lista de valores e escrever uma função para imprimir todos os valores possíveis. Mas é claro que isso é um pouco entediante, além de que não contabiliza nenhuma adição futura. Pelo menos me dirá o valor máximo possível de qualquer enumeração.

Para economizar velocidade, eu provavelmente poderia adaptar sua função para loopar todos os valores até um máximo de, digamos, 1440 em vez de 256 (para D1 no caso de prazos, e qualquer outra coisa no caso de outros enumeros), e então adicionar mais duas verificações específicas para W1 e MN1. Aumentar o máximo não adicionará nenhuma sobrecarga a todos os casos que ainda caberiam no máximo inferior, uma vez que qualquer coisa que caiba abaixo do máximo inferior sai do loop no mesmo tempo, de qualquer forma.

Existem outros enumeros com valores numéricos que vão além de 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