Gán và khởi tạo, biểu thức và mảng
Mảng là một tập hợp các ô cùng loại được đặt tên nằm trong bộ nhớ liên tiếp, mỗi ô có thể truy cập được bằng chỉ mục của nó. Theo một nghĩa nào đó, nó là một biến hợp thành được đặc trưng bởi một mã định danh chung, loại giá trị được lưu trữ và số lượng các phần tử được đánh số.
Ví dụ, một mảng gồm 5 số nguyên có thể được mô tả như sau:
int array[5];
Kích thước mảng được chỉ định trong dấu ngoặc vuông sau tên. Các phần tử được đánh số từ 0 đến N-1, trong đó N là kích thước mảng. Chúng được truy cập, tức là các giá trị được đọc, bằng cú pháp tương tự. Ví dụ, để in phần tử đầu tiên của mảng trên vào nhật ký, chúng ta có thể viết câu lệnh sau:
Print(array[0]);
Xin lưu ý rằng chỉ số 0
tương ứng với phần tử đầu tiên. Để in phần tử cuối cùng, câu lệnh sẽ được thay thế bằng câu lệnh sau:
Print(array[4]);
Tất nhiên, người ta cho rằng trước khi in một phần tử của mảng, một giá trị hữu ích đã được ghi vào đó. Bản ghi này được tạo bằng một câu lệnh đặc biệt, tức là toán tử gán. Một tính năng đặc biệt của toán tử này là sử dụng ký hiệu '='
, bên trái của ký hiệu này là phần tử mảng (hoặc biến) được chỉ định, trong đó bản ghi được tạo, trong khi bên phải của ký hiệu này là giá trị cần ghi lại hoặc 'tương đương' của nó được chỉ định. Ở đây, 'tương đương' ẩn khả năng ngôn ngữ để tính toán các biểu thức số học, logic và các loại khác (chúng ta sẽ tìm hiểu chúng trong Phần 2). Cú pháp của các biểu thức chủ yếu tương tự như các quy tắc viết các phương trình đã học trong số học và đại số ở trường. Ví dụ, các phép toán cộng ('+'
), trừ ('-'
), nhân ('*'
) và chia ('/'
) có thể được sử dụng trong một biểu thức.
Dưới đây là ví dụ về các toán tử để điền vào một số phần tử của mảng ở trên.
array[0] = 10; // 10
array[1] = array[0] + 1; // 11
array[2] = array[0] * array[1] + 1; // 111
2
3
Các câu lệnh này minh họa nhiều phương pháp gán và xây dựng biểu thức khác nhau: Trong chuỗi đầu tiên, số 10
được viết vào phần tử array[0]
, trong khi ở dòng thứ hai và thứ ba, các biểu thức được sử dụng, tính toán dẫn đến việc thu được kết quả được chỉ định để rõ ràng hơn trong các bình luận.
Khi các phần tử mảng (hoặc biến, trong trường hợp chung) có trong một biểu thức, máy tính sẽ đọc giá trị của chúng từ bộ nhớ trong quá trình thực thi chương trình và thực hiện các hoạt động trên với chúng.
Cần phân biệt việc sử dụng các biến và phần tử mảng ở bên trái và bên phải ký tự '='
trong câu lệnh gán: Bên trái là 'bộ thu' dữ liệu đã xử lý (luôn là một), trong khi bên phải là các 'nguồn' dữ liệu ban đầu để tính toán (có thể có nhiều 'nguồn' trong một biểu thức, như trong chuỗi cuối cùng của ví dụ này, trong đó các giá trị của phần tử array[0]
và array[1]
được nhân với nhau).
Trong ví dụ của chúng ta, ký tự '='
được sử dụng để gán giá trị cho các phần tử của một mảng được xác định trước. Tuy nhiên, đôi khi thuận tiện hơn khi gán giá trị ban đầu cho các biến và mảng ngay sau khi xác định chúng. Đây được gọi là khởi tạo. Ký tự '='
cũng được sử dụng cho việc này. Hãy xem xét cú pháp này trong bối cảnh của nhiệm vụ được áp dụng của chúng ta.
Hãy mô tả mảng chuỗi có các tùy chọn chào mừng bên trong hàm Greeting
:
string Greeting(int hour)
{
string messages[3] = {"Good morning", "Good afternoon", "Good evening"};
return "Hello, ";
}
2
3
4
5
Trong câu lệnh được thêm vào, không chỉ mảng messages
với 3 phần tử được định nghĩa mà còn cả việc khởi tạo của nó, tức là điền các giá trị khởi tạo mong muốn. Việc khởi tạo làm nổi bật ký tự =
trên tên biến/mảng và mô tả kiểu. Đối với một biến, chỉ cần chỉ định một giá trị sau =
(không có dấu ngoặc nhọn), trong khi đối với một mảng, như chúng ta có thể thấy, chúng ta có thể viết nhiều giá trị được phân tách bằng dấu phẩy và được bao quanh trong dấu ngoặc nhọn.
Đừng nhầm lẫn giữa khởi tạo và gán. Khởi tạo được chỉ định khi định nghĩa một biến/mảng (và được thực hiện một lần), trong khi khởi tạo xảy ra trong các câu lệnh cụ thể (cùng một biến hoặc phần tử mảng có thể được gán các giá trị khác nhau nhiều lần). Các phần tử mảng chỉ có thể được gán riêng biệt: MQL5 không hỗ trợ gán tất cả các phần tử cùng một lúc, như trường hợp khởi tạo.
Mảng messages
, được định nghĩa bên trong hàm, chỉ khả dụng bên trong nó, giống như tham số hour
. Sau đó, chúng ta sẽ xem cách chúng ta có thể mô tả các biến khả dụng trong toàn bộ mã chương trình.
Làm thế nào chúng ta có thể chuyển đổi giá trị đầu vào của giờ với số giờ thành một trong ba phần tử?
Hãy nhớ rằng, theo ý tưởng của chúng ta, giờ có thể có giá trị từ 0 đến 23. Nếu chúng ta chia chính xác cho 8, chúng ta sẽ thu được các giá trị từ 0 đến 2. Ví dụ, chia 1 cho 8 sẽ cho chúng ta 0 và 7 cho 8 sẽ cho chúng ta 0 (trong phép chia chính xác, phần phân số bị bỏ qua). Tuy nhiên, chia 8 cho 8 là 1, vì vậy tất cả các số đến 15 sẽ cho chúng ta 1 khi chia cho 8. Các số từ 16 đến 23 sẽ tương ứng với kết quả chia là 2. Các số nguyên 0, 1 và 2 thu được sẽ được sử dụng làm chỉ mục để đọc phần tử mảng tin nhắn .
Trong MQL5, phép toán /
cho phép tính toán phép chia chính xác cho số nguyên.
Biểu thức để có được kết quả phép chia tương tự như những biểu thức chúng ta đã xem xét gần đây cho mảng, chỉ cần sử dụng tham số giờ và phép toán /
. Chúng ta sẽ sử dụng câu lệnh sau đây để minh họa cho một triển khai có thể có của phép biến đổi giờ thành chỉ số phần tử:
int index = hour / 8;
Tại đây, một biến số nguyên mới, index
, được định nghĩa và khởi tạo theo giá trị của biểu thức trên.
Tuy nhiên, chúng ta có thể bỏ qua việc lưu giá trị trung gian trong biến chỉ mục và ngay lập tức chuyển biểu thức này (bên phải dấu =
) vào trong dấu ngoặc vuông, nơi chỉ định số phần tử của mảng.
Sau đó, trong câu lệnh có toán tử return
, chúng ta có thể trích xuất lời chào có liên quan như sau:
string Greeting(int hour)
{
string messages[3] = {"Good morning", "Good afternoon", "Good evening"};
return messages[hour / 8];
}
2
3
4
5
Hàm này ít nhiều đã sẵn sàng. Tuy nhiên, sau một vài phần, chúng ta sẽ thực hiện một số chỉnh sửa. Cho đến nay, chúng ta hãy lưu dự án trong một tệp dưới một tên khác, GoodTime0.mq5
và thử gọi hàm của chúng ta. Vì lý do này, trong OnStart
, chúng ta sẽ sử dụng lệnh gọi Greeting
bên trong lệnh gọi Print
.
void OnStart()
{
Print(Greeting(0), ", ", Symbol());
}
2
3
4
Chúng ta đã lưu dấu phẩy phân cách (đặt bên trong "Hello, "
) giữa lời chào và tên biểu tượng. Bây giờ có ba đối số trong lệnh gọi hàm Print
: Đối số đầu tiên và đối số cuối cùng sẽ được tính toán ngay lập tức bằng cách sử dụng các lệnh gọi hàm Greeting
và Symbol
, trong khi dấu phẩy sẽ được gửi để in nguyên trạng.
Cho đến nay, chúng ta đang gửi hằng số 0
vào hàm Greeting
. Giá trị của nó sẽ được đưa vào tham số giờ. Sau khi biên dịch và khởi chạy chương trình, chúng ta có thể đảm bảo rằng nó in văn bản mong muốn trong nhật ký.
GoodTime0 (EURUSD,H1) Good morning, EURUSD
Tuy nhiên, trên thực tế, lời chào phải được chọn một cách linh hoạt, tùy thuộc vào thời gian do người dùng chỉ định. Như vậy, chúng ta đã giải quyết được nhu cầu sắp xếp dữ liệu đầu vào.