Использование массивов

Запись и чтение значений в элементы массива производится с помощью похожего синтаксиса с указанием требуемых индексов в квадратных скобках. Чтобы положить значение в элемент, используем операцию присваивания '='. Например, для замены значения 0-го элемента одномерного массива:

array1D[0] = 11;

Индексация ведется с 0. Индекс последнего элемента равен количеству элементов минус 1. Разумеется, в качестве индекса можно использовать не только константу, а любое выражение, приводимое к целому типу (подробнее о выражениях в следующей главе), например, целочисленную переменную, вызов функции или элемент другого массива с целыми (косвенная адресация).

int index;
// ... 
// index = ... // как-либо присваиваем index
// ...
array1D[index] = 11;

Для многомерных массивов требуется указать индексы для всех измерений.

array2D[index1][index2] = 12;

Допустимые целочисленные типы для индексов исключают long и ulong. При попытке использовать в качестве индекса значение "длинного целого", оно будет неявно конвертироваться в int, в связи с чем компилятор выдаст предупреждение "возможна потеря данных из-за конвертации" ("possible loss of data due to type conversion").

Доступ к элементам массива на чтение организуется по такому же принципу. Например, вот как можно вывести в журнал элемент массива:

Print(array2D[1][2]);

В скрипте GoodTimes мы уже видели описание локального статического массива messages со строками приветствий (внутри функции Greeting) и использование его элементов в операторе return.

string Greeting()
{
  static int counter = 0;
  static const string messages[3] = // определение
  {
    "Good morning""Good day""Good evening" // инициализация
  };
  return messages[counter++ % 3];   // использование
}

При выполнении return производится чтение элемента с индексом, определяемым выражением: counter++ % 3. Деление по модулю 3 (обозначаемое символом '%'), обеспечивает, что увеличиваемый каждый раз на 1 счетчик counter будет приведен в диапазон корректных значений индексов: 0, 1 или 2. Если бы деления по модулю не было, индекс запрашиваемого элемента превысил бы размер массива, начиная с 4-го вызова данной функции. В таких случаях происходит ошибка времени выполнения программы ("выход за пределы массива" — "array out of range"), и она выгружается с графика.

MQL5 API включает универсальные функции для многих операций с массивами: выделение памяти (под динамические массивы), заполнение, копирование, сортировка, поиск в массивах — они рассматриваются в разделе Работа с массивами. Но одну из них мы представим сейчас: ArrayPrint позволяет в удобном виде (с учетом измерений) вывести элементы массива в журнал.

Скрипт Arrays.mq5 демонстрирует некоторые примеры описания массивов и результаты выводятся в журнал. Манипуляции с элементами массивов мы разберем позднее, после знакомства с циклами и выражениями.

void OnStart()
{
  char array[100];      // без инициализации
  int array2D[3][2] =
  {
    {12},             // форматирование для наглядности
    {34},
    {56}
  };
  int array2Dt[2][3] =
  {
    {135},
    {246}
  };
  ENUM_APPLIED_PRICE prices[] =
  {
    PRICE_OPENPRICE_HIGHPRICE_LOWPRICE_CLOSE
  };
  // double d[5] = {1, 2, 3, 4, 5, 6}; // ошибка: too many initializers
  ArrayPrint(array);    // вывод произвольных "мусорных" значений
  ArrayPrint(array2D);  // показываем 2D-массив в журнале
  ArrayPrint(array2Dt); // "транспонированный" вид тех же данных 2D
  ArrayPrint(prices);   // узнаем значения элементов ценового перечисления
}

Один из вариантов записей в журнале представлен ниже.

[ 0]   0   0   0   0   0   0   0   0   0   0   0   0 -87 105  82 119   0
       0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
[34]   0   0   0 -32  -3  -1  -1   7   0   0   2   0   0   0   0   0   0
       0   2   0   0   0   0   0   0   0 -96 104  82 119   0   0   0   0
[68]   0   0   3   0   0   0   0   0  -1  -1  -1  -1   0   0   0   0 100
      48   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    [,0][,1]
[0,]   1   2
[1,]   3   4
[2,]   5   6
    [,0][,1][,2]
[0,]   1   3   5
[1,]   2   4   6
2 3 4 1

Массив array не имеет инициализации и потому выделяемая под него память может содержать случайные значения. При каждом запуске скрипта значения будут меняться. Рекомендуется всегда инициализировать локальные массивы, на всякий случай.

Массивы array2D и array2Dt выводятся в журнал в наглядном виде, как матрицы. Это никак не связано с тем, что мы отформатировали таким же образом списки инициализации в исходном коде.

Массив prices имеет тип встроенного перечисления ENUM_APPLIED_PRICE. В принципе, массивы могут быть любых типов, включая структуры, указатели на функции и другие вещи, которые нам еще предстоит изучить. Поскольку перечисления строятся на основе типа int, значения отображены цифрами, а не названиями элементов (для получения имени конкретного элемента перечисления есть функция EnumToString, но её режим не поддерживается в ArrayPrint).

В строке с описанием массива d — ошибка: количество начальных значений превышает размер массива.