Лекция 29.pptx
- Количество слайдов: 46
Лекция 29 Тема № 6 АЛГОРИТМИЗАЦИЯ И ПРОГРАММИРОВАНИЕ Тип данных указатели. Динамическая память. Процедурные типы. Вариантный тип. Виды динамических структур. Совместимость и преобразование типов. Структура и состав модуля. Стандартные модули Pascal. Стандартные процедуры и функции Pascal. Директивы компилятора Pascal.
Ссылочный тип данных (указатели) 2 Ссылочный тип (указатель) определяет множество значений, которые указывают на динамические переменные определенного типа, называемого базовым типом. Если базовый тип является еще не описанным идентификатором, то он должен быть описан в той же самой части описания типов, что и тип-указатель. Переменная ссылочного типа содержит адрес динамической переменной в памяти. Основное свойство динамических переменных заключается в том, что они создаются, и память для них выделяется во время выполнения программы.
3 Пример var p 1, p 2 : ^real; p 3, p 4 : ^integer; Зарезервированное слово nil обозначает константу со значением указателя, которая ни на что не указывает. Встроенный тип Pointer обозначает нетипизированный указатель, т. е. указатель, который не указывает ни на какой определенный тип.
Операции с указателями Для указателей определены операции: присваивания; p 1 : = p 2; проверки на равенство и неравенство: if p 1 = p 2 then … Правила присваивания указателей • Любому указателю можно присвоить стандартную константу nil, которая означает, что указатель не ссылается на какую-либо конкретную ячейку памяти: p 1 : = nil; • Указатели стандартного типа pointer совместимы с указателями любого типа. • Указателю на конкретный тип данных можно присвоить только значение указателя того же или стандартного типа.
Операция разадресации применяется для обращения к значению переменной, адрес которой хранится в указателе: var p 1: ^integer; … p 1^ : = 2; inc(p 1^); writeln(p 1^); 2 p 1^ p 1 С величинами, адрес которых хранится в указателе, можно выполнять любые действия, допустимые для значений этого типа. 5
Мусор При присваивании указателю 2 4 другого значения старое p 2^ p 1^ значение теряется. Это приводит к появлению так называемого мусора p 1 p 2 (обозначен овалом), когда доступа к участку динамической памяти нет, а сам он помечен как занятый. new(p 1); new(p 2); p 1 : = p 2; 6
ДИНАМИЧЕСКАЯ ПАМЯТЬ 7 Вся динамическая память в Турбо Паскале рассматривается как сплошной массив байтов, который называется кучей. Память под любую динамически размещаемую переменную выделяется процедурой NEW. Параметром обращения к этой процедуре является типизированный указатель. В результате обращения указатель приобретает значение, соответствующее динамическому адресу, начиная с которого можно разместить данные, например: var i, j : ^Integer; r : ^Real; begin New(i); … end.
Процедуры и функции работы с динамической памятью 8 1. Процедура New(var p: Pointer). Выделяет место в динамической области памяти для размещения динамической переменной, и ее адрес присваивает указателю р. 2. Процедура Dispose(var p: Pointer). Освобождает участок памяти, выделенный для размещения динамической переменной процедурой New, и значение указателя р становится неопределенным. 3. Процедура Get. Mem(var p: Pointer; size: Word). Выделяет участок памяти, присваивает адрес его начала указателю р, размер участка в байтах задается параметром size. 4. Процедура Free. Mem(var p: Pointer; size: Word). Освобождает участок памяти, адрес начала которого определен указателем р, а размер – параметром size. Значение указателя р становится неопределенным.
9 5. Процедура Mark(var p: Pointer) Записывает в указатель р адрес начала участка свободной динамической памяти на момент ее вызова. 6. Процедура Release(var p: Pointer) Освобождает участок динамической памяти, начиная с адреса, записанного в указатель р процедурой Mark, т. е. очищает ту динамическую память, которая была занята после вызова процедуры Mark. 7. Функция Max. Avaik. Longint Возвращает длину в байтах самого длинного свободного участка динамической памяти. 8. Функция Mem. Avaik. Longint Возвращает полный объем свободной динамической памяти в байтах. 9. Вспомогательная функция Size. Of(X): Word Возвращает объем в байтах, занимаемый X.
Динамическую память можно возвращать обратно. Для этого используется процедура DISPOSE. Другая возможность состоит в освобождении целого фрагмента кучи. С этой целью перед началом выделения динамической памяти текущее значение указателя запоминается в переменной-указателе с помощью процедуры MARK. Теперь можно в любой момент освободить фрагмент кучи, начиная от того адреса, который запомнила процедура MARK, и до конца динамической памяти. Для этого используется процедура RELEASE. 10
Для работы с нетипизированными указателями используются процедуры: GETMEM (P, SIZE) - резервирование памяти; FREEMEM(P, SIZE) - освобождение памяти. Здесь Р - нетипизированный указатель; SLZE - размер в байтах требуемой или освобождаемой части кучи. Использование процедур GETMEM-FREEMEM как и вообще вся работа с динамической памятью, требует особой осторожности и тщательного соблюдения простого правила: освобождать нужно ровно столько памяти, сколько ее было зарезервировано, и именно с того адреса, с которого она была зарезервирована. 11
Функция MAXAVAIL. Возвращает размер в байтах наибольшего непрерывного участка кучи. Обращение: MAXAVAIL Результат имеет тип LONGINT. За один вызов процедуры NEW или GETMEM нельзя зарезервировать памяти больше, чем значение, возвращаемое этой функцией. Функция MEMAVAIL. Возвращает размер в байтах общего свободного пространства кучи. Обращение: MEMAVAIL Результат имеет тип LONGINT. 12
Длинные строки Переменная этого типа является указателем на динамически выделяемую область памяти, в которой хранится строка. Если длина строки равно нулю, то указатель также равен nil и память под строку не выделяется. Если же строка не пустая, то в выделенной для нее области памяти хранится сама строка, терминальный нуль и число ссылок на данную строку (счетчик ссылок – 4 байта).
Для обработки текстов в Object Pascal используются следующие типы: · · короткая строка short. String (string) или string [n], где n <= 255; длинная строка Ansi. String (string); широкая строка Wide. String; нуль-терминальная строка pchar.
ПРОЦЕДУРНЫЕ ТИПЫ 15 В Турбо Паскале существует два процедурных типа: тип-процедура и тип-функция. ПРИМЕР: type Proc 1 = Procedure (a, b, c : integer; x: real); Proc 2 = Procedure (var a, b); Proc 3 = Procedure; Func 1 = Function : real; Func 2 = Function (n: integer) : boolean; var p 1, p 2: Proc 1; f 1, f 2: Func 2;
16 Переменным процедурных типов можно присваивать в качестве значений имена соответствующих подпрограмм. При этом нельзя использовать стандартные процедуры и функции. После такого присваивания имя переменной становится синонимом имени подпрограммы. Переменные процедурного типа можно, также передавать в подпрограммы в виде параметров. Благодаря этому, имеется возможность создания более гибких вспомогательных алгоритмов.
Вариантные типы 17 Вариантные типы используются для представления значении, которые могут интерпретироваться различными способами. Переменная вариантного типа может содержать значения различных типов и обычно применяется в случаях, когда тип ее значения при компиляции неизвестен или может изменяться в процессе выполнения программы. Для описания переменной вариантного типа служит ключевое слово variant. Пример использования вариантного типа var v 1, v 2: Variant; К: integer;
Совместимость типов Турбо Паскаль - это типизированный язык, т. е тип переменной определяется при ее описании и не может быть изменен. (Только в современных версиях Pascal-Delphi стало возможным динамическое – во время выполнения – определение типа). Переменная может участвовать только в операциях допустимых ее типом. Выполнение операций в выражениях, а также операции сравнения требуют, чтобы операнды имели совместимые типы. Два типа считаются совместимыми, если выполняется хотя бы одно из следующих условий: 1) оба они есть один и тот же тип; 2) оба они вещественные; 3) оба они целые; 4) один тип есть тип - диапазон второго типа; 5) оба они являются типами - диапазонами одного и того же базового типа; 6) оба они являются множествами, составленными из элементов одного и того же базового типа. 18
Совместимость по присваиванию Этот вид совместимости требуется присваивании значений, например в операторе присваивания или при передаче значений в подпрограмму. Значение типа Т 1 является совместимым по присваиванию с типом Т 2 (то есть допустим оператор Т 1 : =Т 2), если выполняется одно из следующих условий. q. Т 1 и Т 2 — тождественные типы (кроме файловых или типов, содержащих элементы файлового типа). q. Т 1 и Т 2 — совместимые порядковые типы, при этом значения типа Т 2 попадают в диапазон возможных значений Т 1. q. Т 1 и Т 2 — вещественные типы, при этом значения типа Т 2 попадают в диапазон возможных значений Т 1. q. Т 1 — вещественный тип, а Т 2 — целочисленный. q. Т 1 и Т 2 — строковые типы. q. Т 1 — строковый тип, а Т 2 — символьный (char). q. Т 1 и Т 2 — совместимые множественные типы, при этом все значения типа Т 2 попадают в диапазон возможных значений Т 1. q. Т 1 и Т 2 — совместимые типы указателей. 19
Приведение типов Ch: =Char(N); N: =Byte(ch); ! !! Переменные занимают одинаковое количество памяти. Исключение составляют преобразования более длинных целых типов в более короткие: в этом случае лишние биты просто отбрасываются. 20
Виды динамических структур В программах чаще всего используются: линейные списки стеки • очереди • бинарные деревья Элемент динамической структуры состоит из двух частей: 1. информационной; 2. указателей: 21
Линейные списки односвязные двусвязные кольцевые Каждый элемент списка содержит ключ, идентифицирующий этот элемент. Односвязный список обеспечивает возможность продвижения лишь в одном направлении — от начала к концу — при просмотре списка. Линейный двусвязный список дает возможность двигаться в одном из двух направлений. Содержит два логических указателя, один из которых (прямой указатель) адресует, как и в односвязном списке, следующий элемент, а другой указатель (обратный) адресует предыдущий элемент списка. type pnode = ^node; node = record d s d : word; { информационная } s : string; { часть} p : pnode; { указатель на следующий элемент } 22 end; p
Двусвязный линейный список TYPE ptr=^Node; Node=record x: <базовый тип>; next: ptr; prev: ptr; end; var b, e: ptr; Операции со списком: • начальное формирование списка (создание первого элемента); • добавление элемента в конец списка; • чтение элемента с заданным ключом; • вставка элемента в заданное место списка (до или после элемента с заданным ключом); • удаление элемента с заданным ключом; • упорядочивание списка по ключу. 23
Стеки 24 Стеком называется динамическая структура данных, добавление компоненты в которую и исключение компоненты из которой производится из одного конца, называемого вершиной стека. Стек работает по принципу LIFO(Last-In, First-Out) – «Поступивший последним, обслуживается первым» . Обычно над стеками выполняется три операции: 1) начальное формирование стека (запись первой компоненты); 2) добавление компоненты в стек; 3) выборка компоненты (удаление). Для формирования стека и работы с ним необходимо иметь две переменные типа «указатель» , первая из которых определяет вершину стека, а вторая – вспомогательная.
Очереди 25 Очередью называется динамическая структура данных, добавление компоненты в которую производится в один конец, а выборка осуществляется с другого конца. Очередь работает по принципу FIFO (First-In, First-Out) – «Поступивший первым, обслуживается первым» . Для формирования очереди и работы с ней необходимо иметь три переменные типа указатель, первая из которых определяет начало очереди, вторая – конец очереди, третья – вспомогательная.
Бинарное дерево — динамическая структура данных, состоящая из узлов, каждый из которых содержит кроме данных не более двух ссылок на различные бинарные деревья. На каждый узел имеется ровно одна ссылка. Начальный узел называется корнем дерева. 26
Операции для бинарных деревьев Для бинарных деревьев определены операции: включения узла в дерево; поиска по дереву; обхода дерева; удаления узла. Элемент дерева: type pnode = ^node; node = record data : word; { ключ } left : pnode; { указатель на левое поддерево } right : pnode { указатель на правое поддерево } end; 27
Модуль unit имя; { заголовок модуля } interface { интерфейсная секция модуля } { описание глобальных элементов} {модуля (видимых извне) } implementation { секция реализации модуля } { описание локальных (внутренних)} { элементов модуля } begin { секция инициализации } { может отсутствовать } end. . tpu В интерфейсной секции модуля определяют константы, типы данных, переменные, а также заголовки процедур и функций. В секции реализации описываются подпрограммы, заголовки которых приведены в интерфейсной части. Кроме того, в этой секции можно определять константы, типы данных, переменные и внутренние подпрограммы. Секция инициализации предназначена для присваивания начальных значений переменным, которые используются в модуле. 28
Пример модуля unit Average; interface const n = 10; type mas = array[1. . n] of real; procedure aver_mas(x : mas; var av : real); implementation procedure aver_mas(x : mas; var av : real); var i : integer; begin av : = 0; for i : = 1 to n do av : = av + x[i]; av : = av / n; end. 29 Использование модуля в программе: program dif_average; uses Average; var a, b : mas; i : integer; dif, av_a, av_b : real; begin for i : = 1 to n do read(a[i]); for i : = 1 to n do read(b[i]); aver_mas(a, av_a); aver_mas(b, av_b); dif : = av_a – av_b; writeln('Разность: ', dif: 6: 2); end.
Стандартные модули Паскаля 30 System Crt Dos и Win. Dos Graph Strings
Модуль System 31 содержит базовые средства языка, которые поддерживают ввод-вывод, работу со строками, операции с плавающей точкой и динамическое распределение памяти содержит все стандартные и встроенные процедуры, функции, переменные Паскаля автоматически константы и используется во всех программах, его не требуется указывать в операторе uses
Примеры переменных System 32 var Heap. Org: Pointer Указывает на конец динамической памяти. var Heap. Ptr: Pointer Указывает на начало динамической памяти. var In. Out. Res: Integer Содержит код последней операции ввода-вывода. Его можно получить с помощью вызова функции IOResult. var Input: Text Назначает стандартный файл ввода. var Rand. Seed: Longint Содержит начальное значение встроенного генератора случайных чисел.
Примеры подпрограмм System var Rand. Seed: Longint 33 function Abs(x) procedure Assign(var f; Name) procedure Continue function Cоpy(s: String; Indx: Integer; Count: Integer): String procedure Dec(var x: <порядковый тип> [; n: Longint]) function Eof[ (var f) ]: Boolean procedure Exit function Exp(x: Real): Real procedure Моvе(var Src, Dst; Count: Word) procedure Mk. Dir(s: String) procedure Randomize procedure Writeln([var f: Text; ] v 1, [, v 2, . . . , vn] )
Модуль Crt 34 позволяет: выполнять вывод в заданное место экрана заданным цветом символа и фона; открывать на экране окна прямоугольной формы и выполнять вывод в пределах этих окон; очищать экран, окно, строку и ее часть; обрабатывать ввод с клавиатуры; управлять встроенным динамиком.
Подпрограммы модуля Crt 35 procedure Clr. Scr; procedure Delay(Msec: word) procedure Go. To. XY(X, Y: Byte) function Key. Pressed: Boolean procedure No. Sound function Read. Key: Char function Sound(Herz: Word) procedure Text. Back. Groud(Color: byte) procedure Text. Color(Color: Byte) function Where. X: Byte function Where. Y: Byte procedure Window(X 1, Y 1, X 2, Y 2: Byte)…
Модули Dos и Win. Dos 36 содержат подпрограммы, реализующие возможности операционной системы MS-DOS — например, переименование, поиск и удаление файлов, получение и установку системного времени, выполнение программных прерываний. Для поддержки этих подпрограмм в модулях определены константы и типы данных.
Модуль Graph 37 обеспечивает: вывод линий и геометрических фигур заданным цветом и стилем; закрашивание областей заданным цветом и шаблоном; вывод текста различным шрифтом, заданного размера и направления; определение окон и отсечение по их границе; использование графических спрайтов и работу с графическими страницами. Спрайты (от англ. Sprite – «дух, привидение» ) представляют собой небольшие графические изображения, перемещаемые по экрану для имитации движущихся фигур или предметов.
Использование графики 38 1. подключение модуля Graph; 2. перевод экрана в графический режим; 3. установка параметров изображения; 4. вывод изображения; 5. возврат в текстовый режим.
Примеры подпрограмм модуля Graph 39 procedure Arс(Х, Y: Integer; Angle 1, Angle 2, R: Word) procedure Circlе(Х, Y: Integer; R: Word) procedure Close. Graph procedure Fill. Poly(N : Word; var S) function Get. Color: Word function Get. Max. X: Integer function Graph. Result: Integer procedure Init. Graph(var Gr. Driver: Integer; var Mode: Integer; Path : String) procedure Line(X 1, Y 1, X 2, Y 2: Integer) procedure Out. Text. XY(Х, Y: Integer; S: String) procedure Put. Image(X, Y: Integer; var Mass; Oper: Word) procedure Rectangle(X 1, Y 1, X 2: Integer) procedure Set. Bk. Color(Color: Word) procedure Set. Line. Style(SType: Word; Pattern: Word; S: Word) procedure Set. Visual. Page(Page: Word)
Модуль Strings 40 предназначен для работы со строками, заканчивающимися нуль- символом (ASCIIZ-строки) и содержит функции копирования, сравнения, слияния строк, преобразования их в строки типа string, поиска подстрок и символов. В модуле System определен тип p. Char, представляющий собой указатель на символ (^Char). Этот тип можно использовать для работы с ASCIIZ-строками. Эти строки располагаются в динамической памяти, и программист должен сам заниматься ее распределением. Кроме того, для хранения ASCIIZ-строк используются массивы символов с нулевой базой, например: var str : array[0. . 4000] of char; Массивы символов с нулевой базой и указатели на символы совместимы.
Модуль OVERLAY 41 Модуль OVERLAY позволяет уменьшить требования к памяти программы DOS реального режима. Фактически можно разрабатывать программы, превышающие общий объем доступной памяти, поскольку в каждый момент в памяти будет находиться только часть программы.
Директивы компилятора 42 Директивы компилятора – это особым образом оформленные комментарии, которые вставляются в текст программы и модифицируют те или иные возможности компилятора в процессе компиляции. Все директивы оформляются фигурными скобками, а за открывающей скобкой должен без пробелов следовать знак доллара (десятичный код 36). Например, {$I-} Как только в процессе разбора исходного текста программы компилятор встретит такого рода последовательность символов, он воспримет их как директиву и нужным образом изменит свою работу. Директивы могут быть переключающими, условными и параметрическими
Некоторые директивы компилятора могут действовать только на часть текста программы, такие директивы называются локальными; в отличие от этого глобальные директивы располагаются в самом начале текста программы (модуля) и действуют сразу на всю программу (модуль) в целом 43 Переключающая директива содержит букву, обозначающую опцию, и знак «+» или «-» . Знак «+» означает установку опции в активное состояние, знак «-» - в пассивное состояние. Например, директива ($I-} означает временное отключение контроля ошибок ввода-вывода, директива ($R+) - включение контроля границ диапазона В одной директиве можно перечислить несколько опций. Следует учесть, что директивы компилятора действуют от момента своего появления в тексте до конца текущего модуля, те локализуются в теле модуля, в то время как опции, установленные в самой среде, распространяются на все модули и основную программу.
{SA+} - выравнивать данные на границу слова (байта), {$В+}* - вычислять логические выражения полностью (до получения результата), ($D+} - разрешить (запретить) работу со встроенным отладчиком, {$Е+} - включить (отключить) режим программной эмуляции сопроцессора, {$F+} - использовать дальнюю (ближнюю) модель вызова, {$G+}* - использовать (не использовать) полный набор команд микропроцессора Intel 80286 микропроцессора Intel 8088), {$I+}* - включить (отключить) контроль операций ввода-вывода, ($L+) - включить (не включать) локальные символы в информацию для отладчика, {$N+} - использовать числовой сопроцессор (реализовать операции с плавающей точкой программно), {$О+} - разрешить (не разрешать) создание оверлейной структуры, {$R+}* - включить (отключить) контроль границ диапазона, {$S +}* - включить (отключить) контроль возможного переполнения стека, {$V+}* - включить (отключить) контроль длины строк при обращении к процедуре или функции, {$Х+} - использовать (не использовать) расширенный синтаксис 44 * - локальные директивы.
Условные директивы определяют условия, при которых компилируются те или иные фрагменты программы. 45 {$DEFINE<условный символ>} - установить условный символ, {$IFDEF<условный символ>} - проверить установку условного символа; если символ установлен, будет компилироваться вся следующая за директивой часть программы вплоть до директив {$ELSE} или {$ENDIF}, в противном случае этот фрагмент программы будет пропущен компилятором, {$IFNDEF <условный символ>} - проверить установку локального символа, обратна директиве {$IFDEF} , т. e действует только в том случае, когда условный символ не установлен, {$ELSE} - определяет начало альтернативного фрагмента программы, этот фрагмент будет компилироваться в том случае, если условный символ, проверенный предыдущей по тексту программы директивой {$IFDEF} или ($IFNDEF} нe установлен, альтернативная часть вместе с директивой {$ELSE} может опускаться, {$ENDIF} ограничивает область действия директив {$IFDEF}, {$IFNDEF} или {$ELSE}.
Параметрические директивы задают параметры, которые должен учитывать компилятор. 46 {$M <стек>, <нижн>, <верх>} - установить требуемые размеры памяти (глобальная директива), здесь <стек> - размер стека; <нижн> - нижняя граница динамической памяти, <верх> - верхняя граница динамической памяти, {$I<имя файла>} - включение PAS-файла: <имя файла> - имя включаемого файла, {$L <имя файла>} - включение ОВJ файла, <имя файла> - имя включаемого файла.