Liệt Kê (Enumerations)
Trong API MQL5, một giá trị liệt kê có thể được chuyển đổi thành chuỗi bằng hàm EnumToString
. Không có sẵn một phép chuyển đổi ngược lại.
string EnumToString(enum value)
Hàm này chuyển đổi giá trị (tức là ID của phần tử được truyền vào) của một liệt kê thuộc bất kỳ kiểu nào thành chuỗi.
Hãy sử dụng nó để giải quyết một trong những nhiệm vụ phổ biến nhất: tìm ra kích thước của liệt kê (nó chứa bao nhiêu phần tử) và chính xác các giá trị nào tương ứng với tất cả các phần tử. Để làm điều này, trong tệp tiêu đề EnumToArray.mqh
, chúng ta triển khai một hàm mẫu đặc biệt (nhờ kiểu mẫu E, nó sẽ hoạt động với bất kỳ enum nào):
template<typename E>
int EnumToArray(E dummy, int &values[],
const int start = INT_MIN,
const int stop = INT_MAX)
{
const static string t = "::";
ArrayResize(values, 0);
int count = 0;
for(int i = start; i < stop && !IsStopped(); i++)
{
E e = (E)i;
if(StringFind(EnumToString(e), t) == -1)
{
ArrayResize(values, count + 1);
values[count++] = i;
}
}
return count;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Khái niệm hoạt động của nó dựa trên cơ sở sau. Vì các liệt kê trong MQL5 được lưu trữ dưới dạng số nguyên kiểu int
, nên hỗ trợ ép kiểu ngầm từ bất kỳ liệt kê nào sang (int)
, và cũng cho phép ép kiểu rõ ràng từ int
trở lại bất kỳ kiểu liệt kê nào. Trong trường hợp này, nếu giá trị tương ứng với một trong các phần tử của liệt kê, hàm EnumToString
trả về một chuỗi với ID của phần tử đó. Nếu không, hàm trả về một chuỗi có dạng ENUM_TYPE::value.
Do đó, bằng cách lặp qua các số nguyên trong phạm vi chấp nhận được và ép kiểu chúng một cách rõ ràng sang kiểu liệt kê, sau đó có thể phân tích chuỗi đầu ra từ EnumToString
để tìm sự hiện diện của ::
nhằm xác định xem số nguyên đã cho có phải là một phần tử của liệt kê hay không.
Hàm StringFind
được sử dụng ở đây sẽ được trình bày trong chương tiếp theo, cùng với các hàm chuỗi khác.
Hãy tạo script ConversionEnum.mq5
để kiểm tra khái niệm này. Trong đó, chúng ta triển khai một hàm phụ trợ process
, hàm này sẽ gọi hàm mẫu EnumToArray
, báo cáo số lượng phần tử trong liệt kê và in mảng kết quả với các sự khớp giữa các phần tử liệt kê và giá trị của chúng.
template<typename E>
void process(E a)
{
int result[];
int n = EnumToArray(a, result, 0, USHORT_MAX);
Print(typename(E), " Count=", n);
for(int i = 0; i < n; i++)
{
Print(i, " ", EnumToString((E)result[i]), "=", result[i]);
}
}
2
3
4
5
6
7
8
9
10
11
Để nghiên cứu, chúng ta sẽ sử dụng liệt kê tích hợp với các kiểu giá áp dụng ENUM_APPLIED_PRICE. Bên trong hàm OnStart
, trước tiên hãy đảm bảo rằng EnumToString
tạo ra các chuỗi như đã mô tả ở trên. Vì vậy, đối với phần tử PRICE_CLOSE, hàm sẽ trả về chuỗi "PRICE_CLOSE", còn đối với giá trị (ENUM_APPLIED_PRICE)10, rõ ràng nằm ngoài phạm vi, nó sẽ trả về "ENUM_APPLIED_PRICE::10".
void OnStart()
{
PRT(EnumToString(PRICE_CLOSE)); // PRICE_CLOSE
PRT(EnumToString((ENUM_APPLIED_PRICE)10)); // ENUM_APPLIED_PRICE::10
process((ENUM_APPLIED_PRICE)0);
}
2
3
4
5
6
7
Tiếp theo, chúng ta gọi hàm process
cho bất kỳ giá trị nào được ép kiểu thành ENUM_APPLIED_PRICE (hoặc một biến thuộc kiểu đó) và nhận được kết quả sau:
ENUM_APPLIED_PRICE Count=7
0 PRICE_CLOSE=1
1 PRICE_OPEN=2
2 PRICE_HIGH=3
3 PRICE_LOW=4
4 PRICE_MEDIAN=5
5 PRICE_TYPICAL=6
6 PRICE_WEIGHTED=7
2
3
4
5
6
7
8
Ở đây, chúng ta thấy rằng có 7 phần tử được định nghĩa trong liệt kê, và việc đánh số không bắt đầu từ 0 như thông thường, mà từ 1 (PRICE_CLOSE). Việc biết các giá trị liên quan đến các phần tử đôi khi cho phép tối ưu hóa việc viết các thuật toán.