"Информатика (базовый и углублённый уровни) (в 2 частях)", Поляков К.Ю., Еремин Е.А.
Динамический массив хранит однотипные элементы, но его размер не нужно выбирать заранее: память выделяют и меняют во время работы программы. Это удобно, когда количество входных данных неизвестно или меняется. Для задания размера используют SetLength, а Length возвращает число элементов. При увеличении массива прежние значения обычно сохраняются, при уменьшении часть данных удаляется. Чтобы не выйти за границы, учитывают: последний индекс равен длине минус один.
Текст подготовлен нейронной сетью по теме параграфа и не заменяет учебник — важные факты и формулировки сверяйте с ним.
Динамический массив — массив, размер которого можно задать или изменить во время выполнения программы. Иными словами, число хранимых значений не обязательно решать до запуска программы. Это нужно, когда данные поступают постепенно или их количество заранее неизвестно.
Тип динамического массива — объявление вида array of ТипЭлементов, без фиксированных границ индексов. Например, array of Integer задаёт массив целых чисел, но не сообщает, сколько их будет. Такое объявление описывает, какие значения можно хранить, а размер задают отдельно.
Процедура SetLength задаёт или изменяет количество элементов динамического массива. Ей передают имя массива и нужную длину, например SetLength(a, 10). Вызов выделяет память для элементов, поэтому без него обращаться к элементам ещё нельзя.
Функция Length возвращает текущее количество элементов массива. Например, если Length(a) равно 10, то в массиве десять элементов, обычно с индексами от 0 до 9. Значение функции удобно использовать в циклах и проверках границ.
При объявлении динамического массива указывают тип элементов, но не их количество: иначе программе пришлось бы заранее резервировать память для возможного максимума. Вместо этого память выделяется тогда, когда становится известен нужный размер. Такой подход экономит место при работе с небольшими наборами данных и позволяет подстроиться под объём входной последовательности.
Чтобы создать массив из n элементов, вызывают SetLength(a, n). В распространённых языках Pascal индексация динамического массива начинается с нуля: первый элемент имеет индекс 0, а десятый — 9. Поэтому количество элементов равно n, а допустимые индексы — от 0 до n − 1; у пустого массива обращаться не к чему.
После выделения памяти к элементу обращаются по имени массива и индексу: например, a[i]. Значение индекса должно оставаться в допустимых границах, иначе программа может выдать ошибку или получить неверный результат. Количество элементов возвращает Length(a), поэтому цикл перебора обычно заканчивают индексом Length(a) − 1.
Если увеличить размер, уже существующие значения обычно остаются на прежних индексах, а в конце появляются новые элементы. Если размер уменьшить, значения за новой границей удаляются; вернуть их одним лишь повторным увеличением длины нельзя. Поэтому перед уменьшением нужно убедиться, что данные за границей больше не нужны.
Динамический массив подходит для обработки последовательностей, длина которых заранее неизвестна: например, чисел из файла или значений, вводимых пользователем. Размер можно увеличивать по мере поступления элементов, а после чтения обработать собранные данные обычным циклом. Статический массив, напротив, имеет заранее заданные границы и не меняет размер во время выполнения.
| Характеристика | Статический массив | Динамический массив |
|---|---|---|
| Способ объявления | С указанием типа и границ | Указывают тип элементов, без границ |
| Момент задания размера | При объявлении | Во время выполнения |
| Возможность изменения размера | Нет | Да, с помощью SetLength |
| Индексы элементов | Определяются объявленными границами | Обычно от 0 до Length − 1 |
| Получение количества элементов | Зависит от заданных границ | Функцией Length |
| Сохранение данных при изменении размера | Размер не меняется | При увеличении значения обычно сохраняются, при уменьшении лишние удаляются |
| Применение | Известное заранее количество значений | Количество значений может меняться или неизвестно заранее |
Сравнивай прежде всего момент задания размера и возможность его менять: эти признаки помогают выбрать подходящий вид массива. Если количество элементов известно и не изменится, достаточно статического массива. Если объём данных определяется во время работы программы, удобнее динамический.
Условие. Объявить динамический массив целых чисел, выделить место для 10 элементов, записать в каждый квадрат его индекса и вывести массив. Поскольку индексы начинаются с нуля, значения будут квадратами чисел от 0 до 9. Для перебора подойдёт цикл по всем допустимым индексам.
Ответ. На экране появятся числа 0, 1, 4, 9, 16, 25, 36, 49, 64, 81. Длина массива равна 10, а последний индекс — 9. Использование Length в границе цикла позволяет не задавать количество элементов повторно.
Условие. Считать целые числа, заранее не зная их количества, и вывести среднее арифметическое. В примере конец последовательности обозначается концом входного потока, например условием EOF. Число прочитанных значений нужно хранить отдельно либо определять через длину массива.
Ответ. Среднее равно сумме всех считанных чисел, делённой на их количество. Проверка ненулевой длины не позволяет делить на ноль, если вход оказался пустым. Для длинных последовательностей частое изменение длины может быть неэффективным, но здесь оно показывает принцип накопления.
Условие. Удалить все элементы, равные заданному числу, сохранив порядок остальных. Просто уменьшить длину недостаточно: нужно сначала уплотнить оставшиеся значения, чтобы внутри массива не образовались пропуски. Для этого используют индекс чтения и индекс записи.
Ответ. В массиве остаются все значения, не равные заданному числу, в первоначальном порядке. Уменьшать длину следует только после переноса нужных элементов. Если совпадений не было, новый размер будет равен прежнему.
Обращаться к элементам сразу после объявления массива нельзя: память ещё не выделена, поэтому доступных позиций нет. Ошибку допускают, принимая объявление типа за создание массива нужной длины. Сначала вызови SetLength, а затем проверь, что длина больше нуля.
Индекс, равный Length(a), не принадлежит массиву: при длине 5 допустимы индексы 0–4. Такое обращение возникает, когда количество элементов путают с номером последнего. Для проверки подставь небольшую длину, например 1: единственный индекс будет 0, а не 1.
Уменьшение размера до завершения обработки может удалить нужные значения. Так бывает, если SetLength воспринимают как команду «убрать один элемент», не подготовив данные к сдвигу. Перед вызовом проверь, что нужные элементы уже перенесены в начало массива и известен новый размер.
Length возвращает количество элементов, а не максимальный индекс. Путаница появляется потому, что оба числа описывают границу массива, но отличаются на единицу при индексации с нуля. Проверяй себя формулой «последний индекс = Length(a) − 1» и не используй индекс длины в цикле.
Для работы с динамическими массивами нужны знания об обычных массивах, индексах и циклах: именно ими перебирают и изменяют элементы. При обработке последовательностей пригодится умение читать данные и накапливать результат. Объявление массива связано с переменными, а изменение его размера — с выделением и освобождением памяти. Такой способ хранения используют при чтении файлов, списков данных и любых последовательностей неизвестной заранее длины.
Чем динамический массив отличается от обычного массива?
У статического массива размер и границы индексов задают при объявлении, а у динамического размер можно установить или изменить во время выполнения программы. Поэтому динамический массив удобен для данных неизвестной длины.
Можно ли обратиться к элементу динамического массива сразу после его объявления?
Нет: после объявления память под элементы ещё не выделена, поэтому доступных элементов нет. Сначала вызови SetLength(массив, нужный_размер), а затем обращайся к элементам в допустимом диапазоне индексов.
Что произойдёт с данными при изменении размера массива?
При увеличении размера уже записанные элементы обычно сохраняются, а для новых элементов выделяется память. При уменьшении значения, оказавшиеся за новой границей, удаляются.
Почему нельзя использовать Length(массив) как индекс последнего элемента?
Length возвращает количество элементов, а индексация обычно начинается с нуля. Поэтому последний индекс равен Length(массив) − 1; индекс, равный длине, уже находится за границами массива.
Как удалить один элемент из динамического массива?
Сначала сдвинь влево все следующие элементы, чтобы сохранить порядок, затем уменьши длину на единицу с помощью SetLength. Если одинаковых значений несколько, удобно одновременно переносить только те элементы, которые нужно оставить.
§ 40. Динамические массивы