Массивы простые, многомерные и динамические
Динамический массив
В практике программирования иной раз случается работать с массивами, размерность которых заранее неизвестна - она может зависеть от данных, введенных пользователем, от текущих параметров, от объема обрабатываемой информации, да еще много от чего. Программист в этих случаях не может указать конкретные границы индексов массива. В таких случаях используют динамические массивы.
Объявляются динамические массивы также в разделе var, следующим образом:
var da: array of integer;
Как видите, мы указываем только тип массива, но не его размерность. Память под объявленный массив при этом не отводится. В дальнейшем с динамическим массивом мы можем производить различные операции: устанавливать размерность (длину) массива, увеличивать или уменьшать эту размерность (потому массив и динамический), узнавать высшие и низшие границы диапазона индексов массива, присваивать значения отдельным элементам или наоборот, считывать эти значения. Познакомьтесь с функциями, которые все это проделывают.
SetLength() - устанавливает размер массива. Синтаксис:
SetLength(<массив>, <длина>);
Пример:
SetLength(da, 5); //установили размер массива в 5 элементов
Тут следует оговориться, что в отличие от обычного массива, начальный индекс которого может быть любым, индексация динамического массива всегда начинается с нуля. То есть, индексация элементов массива в нашем примере будет от 0 до 4 - всего пять элементов. Как только мы установили размер массива, в памяти выделяется место под него. В нашем примере будет отведено по 4 байта (тип integer) для 5 элементов массива. Обращаться к этим элементам можно обычным образом:
da[0]:= 5; da[4]:= da[0];
Теперь мы можем прибавить элемент к массиву, установив для него новый размер:
SetLength(da, 6);
В этом случае, один пустой элемент будет добавлен в конец массива. Если же напротив, мы уменьшим его размер:
SetLength(da, 4);
то массив усекается. Если последний элемент содержал какие-то данные, они будут потеряны. Освободить память массива можно, присвоив ему нулевую размерность:
SetLength(da, 0);
Также освободить память можно, присвоив массиву значение nil (ничего, пусто):
da:= nil;
Впрочем, этого можно и не делать: по окончании процедуры, где данный массив был объявлен, память будет освобождена автоматически.
Динамические массивы могут быть и многомерными. Например, двухмерный массив целых чисел можно объявить так:
var a: array of array of integer;
Затем такому массиву можно присвоить размерность, например, 4 на 5:
SetLength(a, 4, 5);
Это будет, как если бы мы объявили простой массив:
var a2: array[0..3, 0..4];
Length() - возвращает размер динамического массива, то есть, количество его элементов. Например, нам нужно посмотреть размер массива, и если он пустой, то добавить в него один элемент:
if Length(da) = 0 then SetLength(da, 1);
Low() - возвращает нижний индекс массива, у динамических массивов это всегда ноль.
High() - возвращает верхний индекс массива, но это не то же самое, что количество элементов. Если у массива 5 элементов, то Length() вернет 5, а High() вернет 4, так как индексация начинается с нуля.
Пример обхода массива от первого до последнего элемента:
for i:= Low(da) to High(da) do da[i]:= i * i;
В примере мы каждому элементу присваиваем квадрат его индекса. Давайте поработаем с динамическими массивами на практике. Чтобы не портить наш конвертер температур, закройте его и откройте новый проект. Мудрить мы не будем - нам нужна только форма и простая кнопка на ней. Переименовывать тоже ничего не будем, это же просто пример. Сохраните новый проект в папку 13-02.
Сгенерируйте процедуру OnClick для кнопки, её код будет таким:
procedure TForm1.Button1Click(Sender: TObject); var s: string; //для запроса da: array of string; //динамический массив строк i: integer; //счетчик begin //узнаем у пользователя, сколько строк делать: s:= '0'; InputQuery('Привет!', 'Сколько строк желаете создать?', s); //если ноль, то ничего не делаем, выходим из процедуры: if StrToInt(s) = 0 then Exit; //иначе устанавливаем указанную размерность массива: SetLength(da, StrToInt(s)); //теперь обойдем весь массив, устанавливая в его элементы значения: for i:= Low(da) to High(da) do da[i]:= 'Строка №' + IntToStr(i + 1); //теперь снова обойдем массив и создадим сообщение из его строк: s:= ''; for i:= Low(da) to High(da) do s:= s + da[i] + #13; ShowMessage(s); end;
Код содержит достаточно подробные комментарии. Вначале в строковую переменную s мы получаем количество желаемых строк. Так как функция InputQuery() возвращает только строку, нам придется получать целое число в виде строки - никакой проверки мы здесь не делаем, это же только демонстрация работы с динамическим массивом. Поэтому правильность вводимого числа оставим на совести пользователя.
Далее, мы проверяем - не ноль ли это? Если строк создавать не нужно, мы просто выходим из процедуры, пропуская весь остальной код. Если же пользователь ввел какую-то цифру, причем она должна быть больше нуля, то мы устанавливаем указанную размерность массива:
SetLength(da, StrToInt(s));
Далее, с помощью цикла for мы обходим весь массив от первого до последнего элемента. В каждый элемент мы записываем строку: "Строка №", добавляем номер элемента и переход на новую строку. Обратите внимание, для первой строки i будет равно 0, поэтому мы указываем i + 1:
for i:= Low(da) to High(da) do da[i]:= 'Строка №' + IntToStr(i + 1);
Затем мы очищаем строковую переменную s, чтобы вторично воспользоваться ей, собрать в неё сообщение. Что и делаем в следующем цикле:
for i:= Low(da) to High(da) do s:= s + da[i] + #13;
Получается, в процедуре мы дважды обходили массив: сначала чтобы занести в него значения, затем чтобы считать их. Теперь сохраните проект, скомпилируйте его и запустите на выполнение. Имейте в виду, если вы укажете слишком большое число, то окно сообщения не уместится в экране - в этом случае закрыть его можно будет стандартными клавишами <Alt + F4>.