10 · Массивы
Массивы
Если программе нужно хранить не одно значение, а набор однотипных, отдельные переменные быстро становятся неудобны: их приходится перечислять, а обработку повторять для каждого имени. Массив объединяет такие значения под общим именем и даёт доступ к каждому из них по индексу. В этой главе объясняются объявление, границы и размерность, изменение размера, представления и встроенная обработка массивов.
Для чего нужен массив
Оценки студентов удобно хранить в одном массиве scores и обрабатывать циклом, а не заводить переменную для каждой оценки. Число измерений зависит от задачи: последовательность задаёт одномерный массив, прямоугольную таблицу — двумерный, набор значений с несколькими независимыми координатами — массив большего ранга.
Нижняя граница массива
В Axiom нет общей нижней границы по умолчанию. Когда объявление выделяет элементы, программист сам задаёт нижнюю и верхнюю границы каждого измерения через TO, и обе границы входят в диапазон. Запись DIM a[0 TO 9] AS INTEGER создаёт десять элементов с индексами от 0 до 9, DIM b[1 TO 10] AS INTEGER — десять элементов с индексами от 1 до 10, а DIM c[-2 TO 2] AS INTEGER — пять элементов, у которых диапазон начинается с отрицательного индекса.
Границы могут быть числовыми выражениями: они вычисляются при выполнении объявления. Сокращённая форма DIM a[10] AS INTEGER с одной верхней границей не поддерживается: компилятор ожидает TO и сообщает MB1001. Объявление DIM a[] AS INTEGER создаёт динамический массив без элементов и не выбирает начало с нуля или единицы; границы появляются после REDIM с явным диапазоном либо после присваивания выделенного массива.
Когда массив возвращает встроенная функция, границы определяются правилами этой функции. Например, SPLIT возвращает массив с индексами от 1 до числа элементов, а ARRAYTOSORTED сохраняет границы исходного массива. Поэтому нельзя исходить из того, что все массивы Axiom начинаются с нуля или с единицы. Фактические границы выделенного массива возвращают LBOUND и UBOUND.
Именно поэтому обход элементов лучше строить не по предполагаемым числам, а по полученным границам:
DIM scores[1 TO 3] AS INTEGER
scores[1] = 10
scores[2] = 20
scores[3] = 30
FOR i = LBOUND(scores[]) TO UBOUND(scores[])
PRINT scores[i]
NEXTОжидаемый вывод:
10
20
30Цикл не содержит числа 1 и 3: если границы массива изменятся, программа продолжит обходить все элементы.
Тип, ранг и состояние
Объявление задаёт тип элемента и ранг — число измерений. Каждое измерение имеет включательные нижнюю и верхнюю границы, которые возвращают LBOUND и UBOUND. ARRAYLENGTH считает все видимые элементы, а ARRAYISALLOCATED отличает невыделенный массив от выделенного пустого.
Форма DIM scores[1 TO 3] AS INTEGER сразу создаёт элементы с нулевыми значениями. Форма DIM scores[] AS INTEGER объявляет массив ранга 1 без элементов: до обращения к элементам нужен REDIM или присваивание выделенного массива. Графический режим для работы с массивами не требуется.
Начальное значение массива
Массив можно получить при объявлении переменной: DIM fruits[] AS STRING = SPLIT("яблоко,банан", ","). Форма DIM fruits[] = SPLIT("яблоко,банан", ",") выводит тип элемента STRING по результату функции; суффикс [] после имени задаёт одно измерение и обязателен. Обе формы сохраняют границы и состояние полученного массива; присваивание существующего массива создаёт независимую копию, включая вложенные данные. Подробные формы, примеры и ограничения приведены на странице DIM.
Независимые копии
Присваивание массива другой переменной создаёт независимую копию с теми же границами и значениями. Вложенные записи и коллекции копируются вместе с массивом. Сохранение результата частичного индексирования или диапазона TO также создаёт самостоятельный массив с выбранными индексами. Явная функция ARRAYCLONE остаётся допустимой, но для независимости обычного присваивания не требуется:
DIM a[1 TO 2] AS INTEGER
a[1] = 5
DIM b[] AS INTEGER
b[] = a[]
b[1] = 9
PRINT a[1]; b[1]
DIM c[] AS INTEGER
c[] = ARRAYCLONE(a[])
c[1] = 7
PRINT a[1]; c[1]Программа выводит:
59
57В обоих случаях a[1] сохранил значение 5. Изменения b[1] и c[1] относятся к разным массивам. Для намеренного изменения исходной переменной в подпрограмме используется BYREF; BYVAL передаёт независимую копию.
Массив в редакторе
В четырёх темах IDE массивы, обычные переменные и пользовательские функции имеют разные цвета. Семантическая раскраска использует типы компилятора, в том числе при выведении типа, для параметров и полей. При наведении на имя массива подсказка называет его массивом, показывает тип элементов и число измерений. Значения элементов и текущие границы в подсказку редактирования не входят.
Пустые квадратные скобки в выражении fruits[] обозначают массив целиком. Они не означают отсутствие элементов. Массивное имя без [] недопустимо. Вызов функции записывается с круглыми скобками: MakeFruits(); отдельный элемент его результата — MakeFruits()[2].
Темы раздела
Прежние формы и их точные замены собраны в руководстве перехода на квадратные скобки.
Одномерные массивы · Двумерные массивы · Многомерные массивы · Выделение и изменение размера · Индексирование · Представления · Форма и размер · Обработка элементов · Диагностика