- •Содержание
- •Раздел 1.Подпрограммы Общие сведения
- •Процедуры Описание процедур
- •Вызов процедур
- •Процедуры без параметров
- •Процедуры с параметрами
- •Параметры-значения
- •Параметры-переменные
- •Параметры-константы
- •Параметры-переменные без типа
- •Параметры процедурного типа
- •Использование производных типов в качестве параметров подпрограмм
- •Принцип локализации имен
- •Функции Описание функций
- •Вызов функции
- •Рекурсивные подпрограммы
- •Директивы
- •Библиотечные модули пользователя Общие сведения
- •Структура модуля Unit
- •Особенности работы с модулями
- •Подключение к программе внешнего файла
- •Раздел 2.Простейший ввод-вывод Процедуры ввода из стандартного текстового файла Input
- •248 15 4 70 Значения 1-й строки
- •11 Значения 2-й строки
- •Процедуры вывода в стандартный текстовый файл Output
- •Раздел 3.Записи Структура записи
- •Записи без вариантной части
- •Записи с вариантами
- •Оператор присоединения With
- •Константа-запись
- •Раздел 4.Множества Общие сведения
- •Конструктор множества
- •Задание множественного типа
- •Операции над множествами
- •Ввод / вывод значения множественной переменной
- •Типизованные константы-множества
- •Раздел 5.Файлы Общие сведения
- •Процедура Assign
- •Файлы с типом
- •Процедура Assign
- •Процедура Rewrite (f)
- •Процедура Write (f, v1 [, v2, … , vn])
- •Процедура Reset (f)
- •Процедура Read (f, V [, v2, …, vn])
- •Функция Eof(f)
- •Процедура Seek (f, n)
- •Функция Filepos (f)
- •Функция Filesize(f)
- •Процедура Close (f)
- •Текстовые файлы
- •Процедура Assign (f, Name)
- •Процедура AssignСrt(f)
- •Процедура Append (f)
- •Процедура Rewrite (f)
- •Процедура Reset (f)
- •Процедура Read ([f,] v1 [, v2, …, vn])
- •Процедура Readln [([f] [,] [v1, v2, …, vn])]
- •Процедура Write ([f,] e1 [, e2, …, en])
- •Процедура Writeln([f,][e1,e2, …,en])
- •Процедура Close(f)
- •Процедура SetTextBuf (f, Buf [, Size])
- •Процедура Flush (f)
- •Сравнительная характеристика представления информации в файлах с типом и текстовых файлах
- •I. Представление числовой информации.
- •II. Представление текстовой информации.
- •Файлы без типа
- •Процедуры Reset и Rewrite
- •Процедура Blockread
- •Процедура Blockwrite
- •Проверка операций ввода-вывода
- •Раздел 6.Ссылочный тип (тип указатель) Общие сведения
- •Методы работы с динамическими переменными
- •Процедуры New и Dispose
- •Процедуры Getmem и Freemem
- •Процедуры Mark и Release
- •Раздел 7.Динамические структуры данных Динамические цепочки Структура динамической цепочки
- •Формирование цепочки
- •Поиск элемента в цепочке
- •Удаление элемента из цепочки
- •Вставка элемента в цепочку
- •Линейный однонаправленный список
- •Двунаправленные списки
- •Вставка элемента
- •Создание двунаправленного кольцевого списка с заглавным звеном
- •Удаление элемента
- •Поиск элемента
- •Очереди и стеки
- •Очередь lifo
- •Очередь fifo
- •Общие сведения
- •Способы организации таблиц
- •Однонаправленный список.
- •Однонаправленный список с упорядоченными записями.
- •Однонаправленный список с отдельным хранением текста записи.
- •Представление в виде массива.
- •Двоичное дерево.
- •Двоичные деревья Структура двоичного дерева
- •Построение дерева
- •Поиск записи в дереве
- •Включение записи в дерево
- •Удаление записи из дерева
- •Раздел 8.Оверлеи Общие сведения
- •Правила оформления оверлейных программ
- •Инициализация работы оверлеев
- •Включение администратора оверлеев
- •Обработка ошибок администратора
- •Размещение оверлейного файла в ems-памяти
- •Управление оверлейным буфером
- •Литература Основная и дополнительная литература
- •Перечень наглядных пособий, методических указаний, методических материалов и используемых в учебном процессе технических средств
Методы работы с динамическими переменными
В Паскале существует три метода работы с динамическими переменными:
с помощью процедур New и Dispose;
с помощью процедур Getmem и Freemem;
с помощью процедур Mark и Release.
Процедуры New и Dispose
Для порождения динамической переменной используется стандартная процедура New(P). Здесь P – это ссылочная переменная любого типа.
Данная процедура размещает динамическую переменную типа указателя. Переменной выделяется память, достаточная для хранения наиболее длинного значения типа указателя. Адрес начала данного места памяти присваивается заданной ссылочной переменной P.
Пример 6.2.
Использование процедуры New.
Var
P: ^Integer; {Р – указатель на динамическую переменную типа
... Integer}
Begin
New (P);
...
В данном примере процедура New(P) пораждает динамическую переменную типа Integer, адрес этой переменной присваивается указателю P.
Для динамической переменной процедура New играет ту же роль, что раздел описаний Var для автоматической переменной. Никакого значения процедура New динамической переменной не присваивает.
Для обращения к динамической переменной используется переменная с указателем, синтаксис которой представляет Рисунок 6 .48.
Рисунок 6.48 – Синтаксическая диаграмма переменной с указателем
Символ ^ называется знаком карата.
Например, (в применении к примеру 6.2) обращение к динамической переменной, связанной с указателем Р, осуществляется с помощью переменной с указателем:
P^ := 15; {Р^ - переменная с указателем; динамической
переменной типа Integer, связанной с указателем P,
присвоено значение 15}
Над переменными с указателями определены любые операции, допустимые для переменных того типа, что и тип динамической переменной.
Пример 6.3.
Пусть имеются объявления, сделанные в примерах 1 и 2. Операции над динамическими переменными.
Var
...
X: Integer;
Begin
New (P);
P^ := 15;
...
X := X + P^;
P^ := P^ Mod 5;
Adrm^[P^ + 2] := 14;
Пример 6.4.
Организация массивов указателей. Пусть имеются объявления, сделанные в примере 6.1.
Var
...
А: Array[1..20] Of P1; {A – массив ссылок на динамические
переменные типа Integer}
Begin
...
For I:=1 To 20 Do
Begin
New (A[I]); {Порождение динамической переменной,
связанной с указателем A[I]}
A[I]^ := I; {Обращение к динамической переменной}
End
...
В данном примере каждая из ссылок A[I] обеспечивает доступ к соответствующей переменной с указателем A[I]^.
Идентификатор типа в определении ссылочного типа может быть объявлен как до его использования, так и после (в отличие от всех других типов идентификаторов).
Например, в примере 6.1 идентификатор Mas был объявлен до его использования в типе указателя Admas. Возможно и обратное объявление:
Type
Admas = ^Mas;
Mas = Array [1..10] Of Integer;
Пример 6.5.
Работа с указателями и с динамическими переменными.
Var
X, Y: ^Integer; {X, Y – указатели на динамические переменные
типа Integer}
Begin
New (X); {Порождение динамической переменной типа
Integer, адрес которой помещен в Х}
New (Y); {Порождение динамической переменной типа
Integer, адрес которой помещен в Y}
X^ := 5; {В динамическую переменную, связанную
с указателем Х, занесено значение 5}
Y^ := 10; {В динамическую переменную, связанную
с указателем Y, занесено значение 10}
X := Y; {Указателю Х присвоено значение указателя Y}
Y := Nil; {Указателю Y присвоено значение пустой ссылки}
…
Схематично действия операторов программы представляет Рисунок 6 .49.
Рисунок 6.49 – Действия операторов программы по примеру 6.5
Если вместо оператора присваивания X := Y (см. Рисунок 6 .49) будет выполнен оператор X^:=Y^, то результат его выполнения будет выглядеть так, как изображает Рисунок 6 .50.
Рисунок 6.50 – Результат выполнения оператора X^ := Y^
Переменная типа указатель может являться параметром функции Ord. Результатом этой функции является целое значение, равное адресу динамической переменной, на которую ссылается данный указатель. Обратное преобразование (Integer указатель не допускается).
В примере 6.5 после выполнения оператора
X := Y
динамическая переменная со значением 5 стала недоступна программе. Однако она продолжает занимать отведенное ей место в памяти. Данное место не может использоваться для хранения других динамических переменных.
Для уничтожения динамических переменных (освобождения занимаемой ими памяти) используется стандартная процедура Dispose (P).
В результате выполнения процедуры Dispose(P) динамическая переменная, связанная с указателем P, уничтожается, занимаемая ею память считается свободной, значение P считается неопределенным (равным Nil).
Процедура Dispose уничтожает только саму динамическую переменную, но не указатель на нее.
Пример 6.6.
Освобождение памяти, занятой динамической переменной X^ (модифицированный фрагмент программы, приведенной в предыдущем примере 6.5).
...
New (X);
New (Y);
X^ := 5;
Y^ := 10;
Dispose (X); {Освобождается область памяти, занятая
динамической переменной X^}
X := Y;
Y := Nil;
...
Пример 6.7.
В заданном тексте найти слово максимальной длины. Слова разделяются одним пробелом. Признак конца текста – точка. Максимальная длина слова – 50 символов.
Program Slovo;
Type
Mas = Array [1..50] Of Char;
Ykaz = ^Mas; {Тип указателя на массив}
Var
Vspom, Rez, Tek: Ykaz; {Переменная типа указателя на массив}
Max, I: Integer;
Byk: Char;
Begin
Max := 0;
I :=0;
New (Tek); {Порождение динамической переменной,
предназначенной для хранения текущего
слова текста}
{1} New (Rez); {Порождение динамической переменной,}
предназначенной для хранения
максимального из уже прочитанных слов}
Repeat
Read (Byk);
If (Byk <> ‘ ‘) And (Byk <> ‘.’)
Then
Begin
I := I+1; {I – счетчик длины текущего слова}
Tek^[I] := Byk
End
Else
If I > Max Then
Begin
Max := I;
{2} Vspom := Rez;
{3} Rez := Tek;
{4} Tek := Vspom;
I := 0
End
Until Byk = ‘.’;
Dispose (Vspom);
Dispose (Tek);
Writeln;
For I := 1 To Max Do
Write (Rez^[I]);
Dispose (Rez)
End.
В данном примере выполнение оператора {3} не требует пересылки компонент массива типа Mas из динамической переменной Tek^ в динамическую переменную Rez^. В указатель Rez заносится адрес динамического массива Tek^. Таким образом, указатель Rez “перебрасывается” на другой массив. В указатель Tek с помощью операторов {2}, {4} заносится адрес предыдущего динамического массива максимальной длины. Фактически массивы как бы меняются местами, но физически этого не требуется.
На следующем цикле чтения в массив Tek^ будет заноситься очередное текущее слово.
Время выполнения программы, приведенной в данном примере, существенно уменьшается по сравнению с аналогичной программой, использующей только автоматические переменные, за счет отсутствия физической пересылки массивов.
Пояснения к программе, приведенной в данном примере, схематически представляют Рисунок 6 .51 – Рисунок 6 .54.
После выполнения оператора {1}:
Рисунок 6.51 – Результат выполнения оператора New (Rez)
После выполнения оператора {2}:
Рисунок 6.52 – Результат выполнения оператора Vspom := Rez
После выполнения оператора {3}:
Рисунок 6.53 – Результат выполнения оператора Rez := Tek
После выполнения оператора {4}:
Рисунок 6.54 – Результат выполнения оператора Tek := Vspom