- Знакомство c языком и средой разработки
- Редактирование, компиляция и запуск программ
- Мастер MQL и эскиз программы
- Инструкции, блоки кода и функции
- Первая программа
- Типы данных и значения
- Переменные и идентификаторы
- Присваивание и инициализация, выражения и массивы
- Ввод данных
- Работа над ошибками и отладка
- Вывод данных
- Форматирование, отступы и пробелы
- Подводим промежуточный итог
- Основы программирования
- Объектно-Ориентированное Программирование
- Общеупотребительные функции
- Создание прикладных программ
- Автоматизация торговли
- Расширенные средства языка
- Заключение
Присваивание и инициализация, выражения и массивы
Массив — это именованный набор однотипных ячеек, расположенных в памяти следом друг за другом, с возможностью доступа к каждой из них по индексу. В некотором роде, это составная переменная, характеризующаяся общим идентификатором, типом хранимых значений и количеством пронумерованных элементов.
Например, целочисленный массив из 5 элементов можно описать так:
int array[5]; |
Размер массива указывается в квадратных скобках после имени. Элементы нумеруются от 0 до N-1, где N — размер массива. Доступ к ним, то есть чтение значений, производится с помощью похожего синтаксиса. Например, чтобы вывести в журнал первый элемент указанного массива, можно было бы написать инструкцию:
Print(array[0]); |
Обратите внимание, что индекс 0 соответствует самому первому элементу. А для вывода последнего элемента инструкция поменялась бы на такую:
Print(array[4]); |
Конечно, предполагается, что перед печатью элемента массива в него когда-то было записано полезное значение. Такая запись выполняется с помощью специальной инструкции — оператора присваивания. Отличительной чертой этого оператора является использованием символа '=', слева от которого указывается элемент массива (или переменная), куда производится запись, а справа — записываемое значение или его "эквивалент". Под "эквивалентом" здесь скрывается возможность языка вычислять арифметические, логические и прочие типы выражений (мы изучим их во второй части книги). Синтаксис выражений во многом походит на правила записи уравнений из школьных курсов арифметики и алгебры. Например, в выражении можно использовать операции сложения ('+'), вычитания ('-'), умножения ('*'), деления ('/').
Вот, например, как могли бы выглядеть операторы для заполнения некоторых элементов указанного массива.
array[0] = 10; // 10
|
Эти инструкции демонстрируют разные способы присваивания и конструирования выражений: в первой строке в элемент array[0] записывается литерал 10, во второй и третьей — используются выражения, вычисление которых приводит к получению результатов, указанных для наглядности в комментариях.
Когда элементы массивов (или переменные, в общем случае) участвуют в выражении, компьютер в процессе выполнения программы считывает из памяти их значения и выполняет над ними указанные операции.
Следует различать использование переменных и элементов массивов слева и справа от знака '=' в инструкции присваивания: слева стоит "получатель" обработанных данных (он всегда один), а справа — "источники" исходных данных для вычислений ("источников" может быть много в выражении, как в этом примере в последней строке, где перемножаются значения элементов array[0] и array[1]).
В приведенных примерах знак '=' был применен для присвоения значений элементам массива, который определен заранее. Но зачастую бывает удобно присваивать начальные значения переменным и массивам непосредственно в момент их определения. Это называется инициализацией. Для неё также используется знак "равно". Рассмотрим этот синтаксис в контексте нашей прикладной задачи.
Опишем массив строк с вариантами приветствия внутри функции Greeting:
string Greeting(int hour)
|
В добавленной инструкции производится не только определение массива messages с 3 элементами, но и его инициализация, то есть заполнение нужными начальными значениями. Инициализацию выделяет знак равно '=' после описания типа и имени переменной или массива. В случае переменной после '=' необходимо указать одно единственное значение (без фигурных скобок), а в случае массива, как мы видим, можно написать несколько значений, разделенных запятыми и заключенных в фигурные скобки.
Не путайте инициализацию и присваивание. Первая указывается при определении переменной/массива (и производится единожды), а второе встречается в отдельных инструкциях (причем одной и той же переменной или элементу массива могут многократно присваиваться разные значения). Присваивать элементы массива можно только по отдельности: MQL5 не поддерживает присваивание сразу всех элементов по аналогии с инициализацией.
Массив messages, будучи определен внутри функции, доступен только внутри неё, как и параметр hour. Далее мы увидим, как можно описать переменные, доступные во всем коде программы.
Каким же образом, преобразовать входящее значение hour с номером часа в один из трех элементов?
Напомним, что по задумке hour может быть равен числу от 0 до 23 (включительно). Если разделить его на 8 без остатка, получим значения от 0 до 2 (включительно). Например, деление 1 на 8 даст 0 и 7 на 8 даст 0 (дробная часть при делении без остатка отбрасывается). А вот деление 8 на 8 — это уже 1, и вплоть до 15 все числа будут давать 1 при делении на 8. Числа с 16 по 23 будут соответствовать результату деления 2. Полученные целые значения 0, 1, 2 следует использовать как индексы для чтения элемента массива messages.
В MQL5 деление без остатка для целых чисел позволяет вычислять операция '/'.
Выражение для получения результата деления похоже на те, что мы недавно рассмотрели для массива array, только в вычислении должен использоваться параметр hour и операция '/'. В качестве демонстрации возможной реализации преобразования hour в индекс элемента приведем такую инструкцию:
int index = hour / 8; |
Здесь определяется некая новая целочисленная переменная index и инициализируется значением указанного выражения.
Однако, мы можем не сохранять промежуточное значение в переменной index, а сразу перенести данное выражение (справа от знака '=') внутрь квадратных скобок, где указывается номер элемента массива.
Тогда в инструкции с оператором return мы можем извлекать подходящее приветствие следующим образом:
string Greeting(int hour)
|
Функция в общих чертах готова. Кое-какие правки мы внесем через пару разделов. А пока сохраним наработки в файле под новым именем GoodTime0.mq5 и попробуем вызвать свою функцию. Для этого в OnStart используем обращение к Greeting внутри вызова Print.
void OnStart()
|
Мы оставили разделяющую запятую (стоявшую внутри литерала "Hello, ") между приветствием и названием инструмента. Теперь в вызове функции Print три аргумента: первый и последний будут вычислены "на лету" с помощью вызовов, соответственно, функций Greeting и Symbol, а запятая отправится на печать как есть.
В функцию Greeting мы пока передаем константу 0. Именно её значение попадет в параметр hour. Откомпилировав и запустив программу, мы можем убедиться, что она выводит в журнал требуемый текст.
GoodTime0 (EURUSD,H1) Good morning, EURUSD |
Однако, на практике выбор приветствия должен осуществляться динамически, в зависимости от времени, указанного пользователем.
Таким образом, мы подошли к необходимости организовать ввод данных.