Wie erhält man die Länge von Enum und Item in MQL4/MQL5? - Seite 4

 
Ich denke, er sucht nach einer Möglichkeit, alle Indikatoreingaben
in einem EA zu erfassen und so die Notwendigkeit von Eingabewerten für jeden Indikator zu umgehen.
Die Alternative in seinem Backtester ist, jeden Indikator
mit einem Signalpuffer manuell zu bearbeiten.
 

Versuchen Sie es mit diesem etwas einfachen, aber bisher einzig möglichen Ansatz.

enum XXX {x1 = -10, x2 = 0, x3 = 11};

template<typename E>
int EnumToArray(E dummy, int &values[], const int start = INT_MIN, const int stop = INT_MAX)
{
  string t = typename(E) + "::";
  int length = StringLen(t);
  
  ArrayResize(values, 0);
  int count = 0;
  
  for(int i = start; i < stop && !IsStopped(); i++)
  {
    E e = (E)i;
    if(StringCompare(StringSubstr(EnumToString(e), 0, length), t) != 0)
    {
      ArrayResize(values, count + 1);
      values[count++] = i;
    }
  }
  return count;
}

int OnInit()
{
  Print("ENUM elements:");
  XXX a;
  int result[];
  int n = EnumToArray(a, result, -100, 100);
  Print("Count=", n);
  for(int i = 0; i < n; i++)
  {
    Print(i, " ", EnumToString((XXX)result[i]), "=", result[i]);
  }
  
  return 0;
}

Ausgaben:

ENUM-Elemente:

Anzahl=3

0 x1=-10

1 x2=0

2 x3=11

Es ist wichtig, vernünftige Werte für die Parameterstart undstop anzugeben, da der Zyklus vom minimalen zum maximalen ganzzahligen Wert (der standardmäßig verwendet wird, wenn die Parameter übersprungen werden) zu langsam ist, wenn man bedenkt, dass darin String-Funktionen verwendet werden.

 
   template<typename ENUMTYPE>
   bool              AddEnum(ENUMTYPE enumIn) {
      enumIn = 0;
      
      //iterate through enum and add as combo box
      for(int i = 0; i<sizeof(enumIn); i++, enumIn++) {
         m_list.AddItem(EnumToString(enumIn),i);
         PrintFormat("adding %i = %s", i, EnumToString(enumIn));            
       }
      return(0);  
   }


Ich habe dies der Klasse CComboBox hinzugefügt, damit ich einen beliebigen ENUM-Typ übergeben kann und er als Kombinationsfeld hinzugefügt wird.


Aber Sie können es so ändern, dass es das tut, was Sie brauchen.

Das Problem ist, wenn Sie kein ENUM übergeben und etwas wie ein Double oder Float übergeben, könnte Ihre Anwendung abstürzen.

Ich glaube nicht, dass es eine Möglichkeit gibt, den übergebenen Datentyp zu überprüfen.

 
dazamate:
   template<typename ENUMTYPE>
   bool              AddEnum(ENUMTYPE enumIn) {
      enumIn = 0;
      
      //iterate through enum and add as combo box
      for(int i = 0; i<sizeof(enumIn); i++, enumIn++) {
         m_list.AddItem(EnumToString(enumIn),i);
         PrintFormat("adding %i = %s", i, EnumToString(enumIn));            
       }
      return(0);  
   }


Ich habe dies der Klasse CComboBox hinzugefügt, so dass ich einen beliebigen ENUM-Typ übergeben kann und er als Kombinationsfeld hinzugefügt wird.


Aber Sie können es ändern, um das zu tun, was Sie brauchen.

Das Problem ist, wenn Sie kein ENUM übergeben und etwas wie ein Double oder Float übergeben, könnte Ihre Anwendung abstürzen.

Ich glaube nicht, dass es eine Möglichkeit gibt, den übergebenen Datentyp zu überprüfen.

Ich befürchte, dass sizeof(enumIn) immer gleich 4 ist.
 

Ja, das tut es, ups. Das ist mir gerade aufgefallen.

Zufälligerweise hatte die ENUM, die ich verwendet habe, 4 Eigenschaften:\

 

enum Combolist1{item1, item2, item3, item4, item5};

for(int i = 0; GetLastError()==0; i++) {
ComboBox1.ItemAdd(EnumToString(Combolist1(i)),Combolist1(0));
}
 
Xiangdong Guo: Wie erhält man die Länge von enum und item in MQL4/MQL5?

Zum Beispiel gibt es eine Enum-Definition:

enum ENUM_FRUIT {APPLE, BANANA, GRAPE};

Als nächstes möchte ich sie in einer Schleife verwenden:

for (int i = 0; i < length_of_enum; i++) {
  Print(EnumToString(get_enum_item(i)));
} 
Es gibt keine Möglichkeit, Sie müssen es codieren.
Wenn es sich nicht um eine Eingabe handelt, verwende ich dieses Muster
enum ENUM_FRUIT {APPLE, BANANA, GRAPE,
                 FRUIT_FIRST=APPLE, FRUIT_LAST=GRAPE};
for (ENUM_FRUIT i = APPLE; i <= FRUIT_LAST; ++i) {
  Print(EnumToString(i));
}
Die Verwendung mit einem Inkrement (++i) setzt voraus, dass sie numerisch benachbart sind.
Wenn es sich um eine Eingabe handelt, verwende ich dieses Muster
enum ENUM_FRUIT {APPLE, BANANA, GRAPE}
#define FRUIT_FIRST APPLE
#define FRUIT_LAST  GRAPE
for (ENUM_FRUIT i = APPLE; i <= FRUIT_LAST; ++i) {
  Print(EnumToString(i));
}
Wenn sie nicht numerisch benachbart sind
const ENUM_TIMEFRAMES  gcPeriods[]={   PERIOD_CURRENT,
   PERIOD_M1,  PERIOD_M2,  PERIOD_M3,  PERIOD_M4,  PERIOD_M5,  PERIOD_M6,
   PERIOD_M10, PERIOD_M12, PERIOD_M15, PERIOD_M20, PERIOD_M30, PERIOD_H1,
   PERIOD_H2,  PERIOD_H3,  PERIOD_H4,  PERIOD_H6,  PERIOD_H8,  PERIOD_H12,
   PERIOD_D1,  PERIOD_W1,  PERIOD_MN1};
ENUM_TIMEFRAMES  next(ENUM_TIMEFRAMES curr){
   for(int i=0; gcPeriods[i] != curr; ++i){}
   return gcPeriods[i+1];
}
 
Lorentzos Roussos:
Schlechtes Design von was?

es bedeutet, dass die Anzahl der Mitglieder in enum speichern?

 

Ich weiß, dieses Gespräch ist ziemlich alt, aber hier ist ein einfacher Weg, um ein Array von jedem enum Typ zu füllen.


void OnStart()
{
   ENUM_TIMEFRAMES array[];
   int total_elements = enumFillArray(array);
   printf("There are %d elements in the ENUM_TIMEFRAMES array.",
      total_elements
   );
   
   for(int i=0;i<total_elements;i++)
      Print(EnumToString(array[i]));
}
   
template<typename T>
int enumFillArray(T& res_array[])
{
   ArrayResize(res_array,0);
   int iter = 100000;
   for(int i=-iter;i<iter;i++)
      if(StringFind(EnumToString((T)i),"::")<0)
      {
         int index = ArrayResize(res_array,ArraySize(res_array)+1)-1;
         res_array[index] = (T)i;
      }
   return ArraySize(res_array);
}
 

Ich füge nur meine Lösung für zukünftige Generationen hinzu, wie ich das Problem gelöst habe.

Das Problem ist also, die Anzahl der Einträge in der Enum dynamisch mit der Fähigkeit zu wissen, Enum-Werte hinzufügen oder entfernen. Ich muss dies für die Erstellung von festen Größe Arrays mit enum Werte als Array-Index wissen. Ich neige dazu, einen reservierten Wert am Ende der Aufzählung hinzuzufügen, der immer nur als Längenwert verwendet wird. Hier ist ein Beispiel.

enum ENUM_ENTRIES
{
        SMALL_ENTRY = 0,
        MEDIUM_ENTRY,
        LARGE_ENTRY,
        VERY_LARGE_ENTRY,
        _ENUM_ENTRIES
};

ObjectType *entryArray[_ENUM_ENTRIES];

// Setting individual entries
entryArray[MEDIUM_ENTRY] = new ObjectType();
entryArray[LARGE_ENTRY] = new ObjectType();

// Looping through the array
for(int i = 0; i < _ENUM_ENTRIES; i++) {

        entryArray[i] = new ObjectType();       
}
Das ist schön und einfach, weil man nicht überall auf den letzten Eintrag fixiert sein muss wie
// Fixed to last entry +1
ObjectType *entryArray[VERY_LARGE_ENTRY + 1];

for(int i = 0; i <= VERY_LARGE_ENTRY; i++) {

}

Sie können auch weitere Einträge am Ende der Aufzählung hinzufügen und das Array und die Schleife funktionieren trotzdem.

/*
 *  Expanded enum entries
 */
enum ENUM_ENTRIES
{
        SMALL_ENTRY = 0,
        MEDIUM_ENTRY,
        LARGE_ENTRY,
        VERY_LARGE_ENTRY,
        EXTRA_LARGE_ENTRY,
        EXTREMELY_LARGE_ENTRY,
        _ENUM_ENTRIES
};

/* 
 * Previous code untouched and still works
 */

ObjectType *entryArray[_ENUM_ENTRIES];

// Setting individual entries
entryArray[MEDIUM_ENTRY] = new ObjectType();
entryArray[LARGE_ENTRY] = new ObjectType();

// Looping through the array
for(int i = 0; i < _ENUM_ENTRIES; i++) {

        entryArray[i] = new ObjectType();       
}
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
  • www.mql5.com
To obtain the current market information there are several functions: SymbolInfoInteger(), SymbolInfoDouble() and SymbolInfoString(). The first parameter is the symbol name, the values of the second function parameter can be one of the identifiers of ENUM_SYMBOL_INFO_INTEGER, ENUM_SYMBOL_INFO_DOUBLE and ENUM_SYMBOL_INFO_STRING. Some symbols...