К структурным типам данных относятся: массивы, записи и множества.
МАССИВЫ ДАННЫХ
Массив — набор однотипных данных, расположенных в памяти, доступ к которым осуществляется по индексу (индексам). В самом простом случае массив имеет фиксированное количество элементов (статический массив), но бывают и динамические массивы, меняющие свою размерность в ходе выполнения задачи.
СТАТИЧЕСКИЕ МАССИВЫ.
Для того, чтобы объявить статический массив, необходимо в разделе описания переменных - VAR -сделать следующее объявление:
<имя массива>: array [<индекс первого элемента>.. <индекс последнего элемента>] of <тип данных>
Пример: Зададим массив данных с именем Mass, длинной в 11 элементов вещественного типа.
Var
mass: array [0..10] of real;
Данным объявлением мы выделили память под 11 переменных вещественного типа. Каждая переменная - значение массива, выбирается по ее индексу - порядковому номеру данных в массиве.
Предположим, что элементами массива являются следующие числа:
2.5 | 7.0 | 3.1 | 9.8 | 3.3 | 5.6 | 7.2 | 4.3 | 6.9 | 8.7 | 9.9 | 10.2 |
Но каждому числу в массиве соответствует свой индекс:
mass | ||||||||||||
индекс | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
значение | 2.5 | 7.0 | 3.1 | 9.8 | 3.3 | 5.6 | 7.2 | 4.3 | 6.9 | 8.7 | 9.9 | 10.2 |
Тогда, чтобы получить соответствующие данные из массива, необходимо к имени массива добавить (в квадратных скобках) индекс элемента.
Например, следующим элементам массива соответствуют данные:
mass[0] -> 2.5; mass[7] -> 4.3; mass[10] -> 9.9
Рассмотренный выше массив называется одномерным массивом.
Но массивы могут быть и многомерными:
Например, запись следующего типа задает двумерный массив:
Var
mass: array [0..10, 0..100] of real;
Массив описанный таким образом содержит 11 строк по 101 элементу (столбцов) данных вещественного типа в каждой строке
Предположим, что мы объявили массив, состоящий из двух строк и 11 столбцов
Var
mass: array [0..1, 0..10] of real;
Предположим, что данному массиву соответствуют следующие числа:
Строка 0 | 2.5 | 7.0 | 3.1 | 9.8 | 3.3 | 5.6 | 7.2 | 4.3 | 6.9 | 8.7 | 9.9 | 10.2 |
Строка 1 | 1.9 | 3.2 | 5.1 | 7.4 | 8.8 | 3.9 | 2.1 | 2.9 | 6.7 | 4.2 | 5.5 | 7.8 |
mass | ||||||||||||
столбец | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
Строка 0 | 2.5 | 7.0 | 3.1 | 9.8 | 3.3 | 5.6 | 7.2 | 4.3 | 6.9 | 8.7 | 9.9 | 10.2 |
Строка 1 | 1.9 | 3.2 | 5.1 | 7.4 | 8.8 | 3.9 | 2.1 | 2.9 | 6.7 | 4.2 | 5.5 | 7.8 |
Элементы массива в памяти ЭВМ следуют друг за другом так, что при переходе от младших адресов к старшим, наиболее быстро меняется самый правый индекс массива. Таким образом, в памяти ЭВМ будет записана сначала строка [0], а следом за ней - строка [1]
Для того, чтобы получить соответствующий элемент данного массива, необходимо сначала указать номер строки, а затем, через запятую, номер столбца.
Например, следующим элементам массива соответствуют данные:
mass[0,5] -> 5.6; mass[1,7] -> 2.9; mass[0,10] -> 9.9
Работа со статическими массивами не всегда удобна, поскольку количество данных в различных задачах может превышать размер памяти отведенной под статический массив. А это может привести к исключительной ситуации в процессе выполнения программы. Программа может "повиснуть". С другой стороны есть и плюс у статического массива. Программист не задумывается об освобождении выделенной памяти под массив в "общую кучу" памяти компьютера.
ДИНАМИЧЕСКИЕ МАССИВЫ.
В 1998 году разработчики Delphi реализовали достаточно гибкий механизм для работы с динамическими массивами. Динамические массивы не имеют фиксированного размера или длины. Для объявления такого массива достаточно записать:
Var
mass: array of < тип данных >;
например:
mass: array of real;
Данным объявлением мы "сказали дельфи", что хотим иметь одномерный динамический массив вещественного типа. При таком объявлении память не выделяется. Для выделения памяти динамическому массиву, используется процедура SetLength:
Например:
SetLength(mass,1);
После вызова этой процедуры будет выделена память для 1 элемента вещественного типа данных массива, индекс которого будет mass[0] (обратите внимание: индексирование начинается с нуля, а не с единицы!).
Стандартная функция Length возвращает длину массива (количество элементов массива).
Length(mass) --> 1;
Рассмотрим пример работы с одномерным динамическим массивом.
В данном примере мы будем читать исходные данные из текстового файла в динамический массив, с наращиванием его длины. (Более подробно, работа с файловой системой будет рассмотрена в следующем разделе)
unit Unit1;
Interface
.................................
.................................
Var
x: array of real;
t: textfile;
Procedure read_text; // объявили переменную процедурного типа
.................................
.................................
Implementation
{$R *.dfm}
Procedure read_text; // реализация переменной процедурного типа
Begin
SetLength(x,1);
i:=0;
while not eof(t) do begin
if length(x)<=i then setlength(x, length(x)+1);
readln(t, x[i]);
inc(i);
end; //while
closefile(t);
end; // Procedure read_text
.................................
.................................
if opendialog1.execute then begin
assignfile(t,opendialog1.filename);
reset(t);
read_text; // обращение к процедуре чтения
end;
.................................
.................................
End.
Рассмотрим подробно данный пример.
Имеется интерактивный Редактор Кода - unit1.
В области интерфейсной части, в разделе описания переменных VAR
объявлен динамический массив x: array of real; кроме этого объявлена переменная t: textfile для работы с текстовым файлом и объявлена переменная процедурного типа - Procedure read_text - без формальных параметров.
В разделе implementation -исполняемой части Редактора Кода - описано тело переменной процедурного типа - Procedure read_text;
При необходимости прочитать информацию из текстового файла, мы
используя компонент - Opendialog1, палитры компонентов DIALOG, выбираем и открываем файл с исходными данными - assignfile(t,opendialog1.filename).
Свойство компонента opendialog1 - filename - содержит адрес и имя выбранного файла. Свойство filename передается в файловую переменную t. В дальнейшем t является источником информации.
Функция reset(t) 'говорит дельфи', что файл будет читаться сначала. Затем
обращаемся к процедуре Procedure read_text по ее имени - read_text.
Далее в процедуре:
1. Устанавливаем минимальную длину динамического массива SetLength(x,1);
2. Поскольку заранее неизвестно количество данных в файле, для его чтения используем цикл с предусловием while not eof(t) do begin. Перед циклом задаем значение счетчика цикла (количества прочитанной информации) - i:=0;
3. Перед чтением файла проверяем длину динамического массива
if length(x)<=i then setlength(x, length(x)+1);
если условие = true то увеличиваем длину массива, как текущую длину length(x) и к ней добавляем 1 - setlength(x, length(x)+1);
4. После этого читаем данные из текстового файла в динамический массив - readln(t, x[i]);.
Индексом данных массива является переменная счетчика цикла i.
5. Затем увеличиваем переменную цикла на 1 - inc(i); и переходим на пункт 2 - while not eof(t) do begin. Если условие цикла дает true, то цикл продолжается далее, если false - цикл завершается, текстовый файл закрывается - closefile(t). Работа программы переходит к оператору, стоящему после оператора вызова процедуры чтения - read_text;
Для того, чтобы обрезать (укоротить) массив, используют процедуру setlength.
Предположим, длина динамического массива x=10, используя его повторно, нам потребуется всего 5 элементов. Установим новую длину: setlength(x,5);
Обрезанные элементы массива автоматически обнулятся и вернутся в общую кучу памяти.
Важно!!! При завершении работы программы На программиста возлагается задача освободить память, выделенную под динамический массив. Делает это функция Finalize.
Пример для массива X:
Finalize (x); // очистили память, занятую под массив X.
Мы рассмотрели принцип работы с одномерными динамическими массивами. Но, как и статические, динамические массивы могут быть многомерными.