«УТВЕРЖДАЮ»
Ректор университета
_________________А.В. Лагерев
«________»_____________2006г.
Алгоритмические языки и программирование Работа с динамическими массивами
Методические указания к выполнению лабораторной работы №13
для студентов дневной формы обучения
специальностей 075300 – "Организация и технология
защиты информации",
220300 – "Системы автоматизированного проектирования"
Брянск 2006
УДК 004.43
Алгоритмические языки и программирование. Работа с динамическими массивами: методические указания к выполнению лабораторной работы №13 для студентов дневной формы обучения специальностей 075300 – "Организация и технология защиты информации", 220300 – "Системы автоматизированного проектирования".– Брянск: БГТУ, 2006. - 12 с.
Разработал: Ю.А. Леонов, асс.
Научный редактор Ю.М. Казаков
Редактор издательства Л.И. Афонина
Компьютерный набор Ю.А. Леонов
Рекомендовано кафедрой «Компьютерные технологии и системы» БГТУ (протокол № от )
Темплан 2006г., п.
Подписано в печать Формат 60х84 1/16. Бумага офсетная. Офсетная печать. Усл. печ. л. 1,45 Уч. – изд. л. 1,45 Тираж 50 экз. Заказ Бесплатно |
Брянский государственный технический университет.
Брянск, бульвар 50-летия Октября, 7, тел. 55-90-49.
Лаборатория оперативной полиграфии БГТУ, ул. Институтская, 16
Цель работы
Овладеть практическими навыками работы с динамическими массивами, научиться выполнять основные операции над ними.
Продолжительность работы – 6ч.00мин.
Теоретическая часть
При объявлении данных динамической структуры в разделе описаний указывается не сама переменная какого – либо типа, а указатель на неё.
Указатель – это переменная, объявленная в разделе описаний программы, значение которой и представляет собой адрес одного байта памяти. Указатели бывают типизированные (содержат адрес данных, тип которых оговаривается при объявлении данных указателей) и нетипизированные (переменные, содержащие адрес данных произвольного типа).
Нетипизированные указатели объявляются следующим образом:
Var
pp: pointer;
Описание типизированных указателей выглядит следующим образом:
Var
px: ^char;
py: ^integer;
Для работы с динамическими переменными в программе должны быть предусмотрены:
выделение памяти под динамическую переменную;
присвоение динамической переменной адреса выделенной памяти (инициализация указателя);
освобождение памяти после использования динамической переменной.
Выделение и освобождение памяти под динамические переменные выполняется стандартными процедурами New, Dispose, GetMem, FreeMem во время работы программы.
Описание основных процедур и функций предназначенных для работы с динамической памятью
Процедура New выделяет область памяти соответственно тому типу, который описан для указателя p и записывает адрес выделенной памяти в указатель
Procedure New (var p: pointer);
Процедура Dispose освобождает область памяти, на которую указывает указатель p, после чего эта область памяти становится доступной для распределения под другие динамические переменные.
Procedure Dispose (var p: pointer);
Процедура GetMem создаёт новую динамическую переменную указанного размера, и помещает адрес блока в переменную – указатель.
Procedure GetMem (var p: pointer; Size: Word);
Size – выражение, определяющее размер выделяемой области памяти в байтах.
Процедура FreeMem уничтожает переменную, на которую указывает p, и освобождает занятую ей область памяти в динамической распределяемой области.
Procedure FreeMem (var p: pointer; Size: Word);
Функция SizeOf возвращает число байт, занимаемых аргументом, указанным в качестве параметра функции.
Function SizeOf (x): integer;
Функция MaxAvail возвращает размер самого большого непрерывного свободного участка в «куче» (динамически распределяемая область памяти). Возвращаемый функцией результат представляет собой значение, принадлежащее типу LongInt.
Function MaxAvail: LongInt;
Функция MemAvail возвращает общее количество свободной памяти в «куче» с учетом фрагментации.
Function MemAvail: LongInt;
Особенности работы с одномерными динамическими массивами
К сожалению, на языке Pascal нет удобных стандартных средств для работы с динамическими массивами, но существует обходные пути для реализации динамических массивов в языке Pascal.
Напомним, что массивом называется, независимо от того статический он или динамический, упорядоченная совокупность однотипных данных. Из этого следует, что элементы массива должны располагаться непрерывно в области памяти. Разница между статическим и динамическим массивом в том, что память под статический массив выделяется автоматически и существует до тех пор, пока не будет совершен выход из того блока, в котором он был объявлен, например, если массив был объявлен глобально то память, выделенная под статический массив, освободится при выходе из программы. Память под динамический массив можно выделять и освобождать в любой точке выполнения программы. При сравнении свойств статических и динамических массивов видны существенные преимущества динамических массивов над статическими.
В языке Pascal имеются инструменты для работы со статическими массивами, а также инструменты для выделения динамической памяти, если грамотно сложить достоинства этих возможностей, то получится вполне удобный инструмент для работы с динамическими массивами. Для того чтобы пользоваться удобным инструментом доступа к элементам массива, т.е. обращение к элементам массива через указание индекса [индекс], необходимо для создания динамического массива объявить статический массив, состоящий из одного элемента.
Например: TMass=array [1..1] of integer;
Также для работы с инструментом динамического выделения памяти необходимо ввести указательный тип данных на ранее объявленный статический массив.
Например: TPMass=^TMass;
Далее воспользуемся стандартной процедурой выделения нужного объема памяти, заранее объявив указательную переменную типа TPMass.
…
Var PMass: TPMass;
…
GetMem (PMass, sizeof (TMass)* size);
…
Процедуре GetMem передается указательная переменная, в которую будет записан адрес на начало выделенной памяти и размер памяти в байтах. Для того чтобы подсчитать необходимое количество памяти для создания динамического массива нужно перемножить размер памяти, занимаемый одним элементом на количество элементов массива. Размер памяти под один элемент можно подсчитать с помощью стандартной функции sizeof (результат в байтах).
При работе с динамическими массивами необходимо помнить, что выделенная память под массив автоматически не будет освобождена, следовательно, при выходе из программы вся динамически выделенная память должна быть освобождена.
…
FreeMem (PMass, sizeof (TMass)* size);
…
Освобождается память, выделенная под динамический массив аналогично выделению памяти.
Для того чтобы обратится к элементу динамического массива необходимо воспользоваться операцией разыменования (обращение к данным по адресу) и инструментом обращения к элементам статического массива (через указание индекса массива с помощью квадратных скобок [ ]).
Например, присвоим переменной k значение, находящееся в динамическом массиве в ячейке с индексом 3:
K:=PMass^[3];
Несмотря на то, что статический массив содержит всего лишь один элемент, именно из этих «кирпичиков» строится динамический массив, обращаться в динамическом массиве можно к любому его элементу. Для того чтобы в ходе выполнения программы не возникала ошибка при событии выхода за пределы массива необходимо отключить в настройках среды программирования опцию «Range checking» (контроль выхода за диапазон) Option | Compiler | Runtime errors. При отключении данной опции компилятор не вставит в машинный код обработчик данной ошибки, т.е. в этом случае можно выходить за пределы объявленного массива. Другой вариант в начале программы вставить директиву компилятора {$R-}, данная директива сообщает компилятору, что в получаемый в результате компилирования машинный код не надо вставлять обработчик контроля выхода за диапазон, т.е. этот вариант аналогичен описанному ранее.
Особенности работы с двумерными динамическими массивами
Так же как и в случае с одномерными динамическими массивами стандартных инструментов для работы с двумерными динамическими массивами отсутствуют. Существует очень красивое решение для реализации динамических массивов на языке Pascal. Построим схему данных, которая будет давать представление о том, как распределяются данные двумерного динамического массива.
Схема данных двумерного динамического массива размерностью 3х3 выглядит следующим образом:
** |
|
|
|
|
* |
|
4 |
5 |
1 |
* |
|
3 |
2 |
3 |
* |
|
8 |
4 |
3 |
На данной схеме набором из двух звездочек ** обозначен двойной указатель, т.е. переменная указатель, в которой хранится адрес на данные указательного типа (адрес на адрес). Одной звездочкой * обозначается адрес на целочисленные данные. В нашем случае двойной указатель ссылается на столбец указателей. Каждый из элементов этого столбца указывает на строку данных, в нашем случае набор целых чисел. Пользуясь приведенной схемой можно выделить память под двумерный динамический массив.
Можно представить следующий алгоритм выделения памяти под двумерный динамический массив:
объявление двойного указателя;
выделение памяти под столбец указателей;
выделение памяти под каждую строку динамического массива и занесения адреса выделенной памяти в каждую ячейку столбца указателей.
Для работы с динамическим массивом нужно объявить необходимые типы данных.
…
TMass=array [1..1] of integer; {тип массив для представления данных целого типа}
TPMass=array [1..1] of ^TMass; {тип массив для представления данных указательного типа}
TPPMass=^TPMass; {тип данных двойного указателя}
…
Выделим память под двумерный динамический массив.
GetMem(PPMass, sizeof(TPMass) * row); {выделяем память под столбец указателей}
for i:=1 to row do GetMem(PPMass^[i], sizeof(TMass) * col); {выделяем память под данные целого типа с занесением адреса в каждую ячейку столбца указателей}
Обратиться к ячейке двумерного динамического массива можно аналогичным образом, как и в случае с одномерным динамическим массивом.
Например, присвоим переменной k значение, находящееся в динамическом массиве в ячейке с индексом 3, 4:
k:=PMass1^[3]^[4];
Для полного понимания работы с двумерным динамическим массивом необходимо подробно ознакомиться с особенностями работы с одномерными динамическими массивами.