Как получить длину перечисления и элемента в MQL4/MQL5? - страница 4

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

Попробуйте этот немного прямолинейный, но пока единственный возможный подход.

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

Выходные данные:

ENUM элементов:

Count=3

0 x1=-10

1 x2=0

2 x3=11

Важно указать разумные значения для параметровstart иstop, так как цикл от минимального до максимального целочисленного значения (который используется по умолчанию, когда параметры пропущены) выполняется слишком медленно, учитывая, что внутри используются строковые функции.

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


Я добавил это в класс CComboBox, так что я могу передать любой тип ENUM, и он добавит его как комбобокс.


Но вы можете изменить его, чтобы сделать то, что вам нужно.

Проблема в том, что если вы не передадите ENUM и передадите что-то вроде double или float, вы можете завалить свое приложение.

Я не думаю, что есть способ проверить переданный тип данных.

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


Я добавил это в класс CComboBox, так что я могу передать любой тип ENUM, и он добавит его как комбобокс.


Но вы можете изменить его, чтобы сделать то, что вам нужно.

Проблема в том, что если вы не передадите ENUM и передадите что-то вроде double или float, вы можете завалить свое приложение.

Я не думаю, что есть способ проверить переданный тип данных.

Я боюсь, что sizeof(enumIn) всегда равен 4.
 

Да, так и есть, упс. Я только что заметил это.

Просто так получилось, что когда я создавал это, ENUM, который я использовал, на самом деле имел 4 свойства:\

 

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

for(int i = 0; GetLastError()==0; i++) {
ComboBox1.ItemAdd(EnumToString(Combolist1(i)),Combolist1(0));
}
 
Xiangdong Guo: Как получить длину перечисления и элемента в MQL4/MQL5?

Например, есть определение перечисления:

enum ENUM_FRUIT {APPLE, BANANA, GRAPE};

Далее, я хочу использовать его в цикле:

for (int i = 0; i < length_of_enum; i++) {
  Print(EnumToString(get_enum_item(i)));
} 
Нет никакого способа, вы должны закодировать это.
Если это не будет входом, я использую этот шаблон.
enum ENUM_FRUIT {APPLE, BANANA, GRAPE,
                 FRUIT_FIRST=APPLE, FRUIT_LAST=GRAPE};
for (ENUM_FRUIT i = APPLE; i <= FRUIT_LAST; ++i) {
  Print(EnumToString(i));
}
Использование его с инкрементом (++i) предполагает, что они являются смежными численно.
Если он будет входом, я использую эту схему.
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));
}
Если они не являются числовыми соседями
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:
Плохой дизайн чего

это означает количество членов в перечислении?

 

Я знаю, что этот разговор довольно старый, но вот простой способ заполнить массив любого типа enum.


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

Просто добавляю свое решение для будущих поколений о том, как я решил эту проблему.

Итак, проблема заключается в том, чтобы знать количество записей в перечислении динамически с возможностью добавлять или удалять значения перечисления. Мне нужно знать это для создания массивов фиксированного размера со значениями перечисления в качестве индекса массива. Я обычно добавляю зарезервированное значение в конец перечисления, которое используется только как значение длины. Вот пример.

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();       
}
Это удобно и просто, потому что вам не нужно привязываться к последней записи повсюду, как, например, в примере
// Fixed to last entry +1
ObjectType *entryArray[VERY_LARGE_ENTRY + 1];

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

}

Или вы можете добавить больше записей в конец перечисления, и массив и цикл все равно будут работать.

/*
 *  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...
Причина обращения: