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

どちらの場合でも、enumの文字列名だけを知っている必要があります。また、この列挙型は0から始まるので、あなたのコードは間違っています。


 
cyberglassed:

こんにちは、アラン、私はあなたの好奇心を満たす:P

あなたが複数の外部ML5コードを使用していると仮定して、あなたはそれらに定義されている複数の "enum "データ型を扱っています。しかし、ある部分において、あるenumの値を文字列形式で指定したい場合、直接指定することができないため、上に書いたような回避策を取らなければなりません。この方法には2つの大きな欠点があります。1つは、関係するすべてのenumの値を収集しなければならないこと、もう1つはメンテナンスの問題で、外部のmql5コードを更新したときに、開発者がint値をある定数表現に関連付けるのを変更すると、予期しない動作になることがあるので、コードの更新を調査し続けなければならないのです。

ありがとうございます、しかしそれは私が求めたものではありません。具体的なコード例を投稿できますか?

StringToEnum()関数に関するあなたの指摘は、100%悪いコーディング手法から来ていると確信しています。enum の目的は、基礎となる整数値から独立したコードを構築することであり、この値が変更されても、あなたのコードには何の影響もないはずです。また、MODE_SMAのような識別子を記憶できないのに、"MODE_SMA "という文字列を記憶できる理由もわかりません。

セキュリティリークの話ですが...私は、あなたが言った「セキュリティリークへのオープンドア」については、完全に同意しているわけではありません。もちろん、オープンドアになる可能性はありますが、プログラマは制限を設け、起こりうる危機的状況に対処しなければなりません。つまり、PHPや、SQLのコードインジェクションのように、ユーザがあなたのコードにアクセスできる場合に備えて、重要な入力データを解析しなければならないような状況を完全に管理できるのです。

私は、セキュリティがコーダーによって管理できないとは言っていません。Metaquotesはそのセキュリティをプログラマーに依存することを許さないと言ったのです。そのようなことは決して起こらないので、ServiceDeskにリクエストを 投稿して彼らに尋ねることをお勧めします。

 
cyberglassed:

はい、コメントを書いた後で、あなたが "else if "を使っていないことに気づいたので、3.に変更しました。

はい、文字列から始めます、だから私が提案する関数のシグネチャは

とにかく、私たちが分析したように、今までの唯一の回避策は、複数の "if "を使用することです;)


でも、これをループさせて、1 行で 済ますこともできます。

 //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:

でも、それをループさせて、1 行で 済ますこともできます。

しかし、それでも4ページ近くもあるのですが...なぜでしょう?)

Laszlo Tormasi:

"そして、ある部分では、あるenumの値を文字列形式で指定したい。"

これの利点がわからないのですが。例を示していただけますか?

どちらの場合でも、enumの文字列名だけを知っていればよいのです。また、この列挙型は0から始まるので、あなたのコードは間違っています。

Marcoと Laszloは、問題を最小化しようとすると、反対側の好奇心が強くなることがあるんだ :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ではオフセットは0ではなく1です(mql4とは異なります)。私は簡単なスクリプトで確認 しましたが、驚きました。というわけで、メンテナンスの問題→混乱の可能性という話をしました。
 
Alain Verleyen:

ありがとうございます、しかし、それは私が尋ねたものではありません。具体的なコード例を投稿できますか?

StringToEnum()関数に関するあなたの指摘は、すべて悪いコーディング手法からきていることは100%間違いありません。 enum の目的は、基礎となる整数値から独立したコードを構築することであり、この値が変更されても、あなたのコードには何の影響もないはずです。また、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 関 数を以下に示します。

使用例 :

4.5年後、しかし自分自身のためにこの必要性の解決策を探してこの投稿に出会いました。@Alain Verleyen 「なぜこれが必要なのかわからない」「この関数が必要なら、あなたのコードはダメだ」という最初の反応に対抗する使い方を見つけたようでうれしいです😛。

私はこれが有用であろう様々な状況に出くわしましたが、あなたや私が必要性を見つけなかったとしても、疑問があります:StringToEnum()が存在する理由がないのなら、EnumToString()が存在する理由はあるのでしょうか?逆に、EnumToString()が存在するなら、その関数を使って列挙型を文字列に変換し、時にはそれを元に戻したいと考えるのは無理からぬことでしょう😉。

言うまでもなく、私の実例は、複数のシンボルと時間枠の組み合わせで動作するEAを持っています。この方法には長所と短所がありますが、私の場合は長所が短所を確実に上回ります。

その一つは、最初に取引を行うかどうかのロジックを決定するのに使われたタイムフレームで、そのロジック(一部はタイムフレームに依存します)は、取引を修正(例:SL)または決済するタイミングに影響を与えることがあるからです。そのため、私はその情報を人間が読める形(例えば14400ではなくH4)で見たいのですが、もちろん、EAが取引の修正または決済を決定する際に、数値の列挙値を利用できるようにしたいとも思っています。

そこで、EnumToString(timeframe)を使って、コメントに時間枠の文字列表現を持たせています。その後、OrderComment() (または対応するmql5バージョン) を使用して取引からコメントを取得し、コメントから時間枠の文字列表現を解析して例えば「PERIOD_H4」を得ることができます。 StringToEnum("...") 関数はこれを数値に戻し、時間枠の場合は分数(すなわち、"PERIOD")に変換することができます。もちろん、コメントに列挙することもできますが、これはStringToEnum()がないことによる(本来は不要な)回避策です。)

この場合、MAX値を43200に増やして、汎用性を保ちつつ、それをカバーするために十分に包括的 でなければならないことを除いて、あなたの解決策は、今のところ、同じくらい良いように思います(https://docs.mql4.com/constants/chartconstants/enum_timeframes)

もちろん、OrderTimeframe() や OrderPeriod() 関数はそのような特定のニーズを満たしますが、私が言うように、これは StringToEnum() 関数が役立ついくつかの状況のうちの1つです。 どうやらあなたもそれを見つけたようですね😉。

解決策を教えてくれてありがとう。 そして、自分が間違っていたと認めたあなたの謙虚さに拍手です😊。

MQL4/5のドキュメントのどこかに、すべての可能なenumとenum値のリストがないでしょうか。 このページhttps://www.mql5.com/en/docs/constant_indices、そのページの対応するmql4バージョンがあります。ただし、数値のリストはありません。このページのテキストをコピーして、それをすべて解析して値のリストを作成し、可能なすべての値を表示する関数を書くことができると思います。 しかし、もちろんそれは少し面倒ですし、将来の追加を考慮していません。 少なくとも、どのenumの可能な最大値も教えてくれるはずです。

最大値が256ではなく1440(タイムフレームの場合はD1、他の列挙型の場合はそれ以上)までのすべての値をループするように関数を調整し、W1とMN1についてさらに2つの特定のチェックを追加します。 最大値を増やしても、最大値の下に収まるものはいずれにしても同じ時間でループから外れるので、すべてのケースにオーバーヘッドを追加するわけではありません。

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
理由: