- •Історична довідка
- •Характеристика й особливості мови
- •Алфавіт мови
- •Службові (зарезервовані) слова.
- •Структура програми мови Turbo Pascal
- •Процедури введення-виведення. Деякі вбудовані функції Турбо-Паскаля.
- •Функції числових параметрів.
- •Базові управляючі конструкції Турбо-Паскаля Оператори умовного переходу.
- •Оператори циклів у Паскалі
- •Концепція типів даних. Типи даних в мові Pascal
- •Дійсні типи
- •Бульовий (логічний) тип
- •Символьні і рядкові змінні
- •1. Символьний тип
- •2. Рядковий тип
- •Перерахований та обмежений типи
- •1. Перерахований тип
- •2. Обмежений тип
- •1. Поняття масиву. Одномірні масиви
- •2. Багатомірні масиви
- •3. Сортування і пошук
- •Множинний тип
- •Тип запис
- •Процедури і функції
- •Формальні і фактичні параметри. Механізм параметрів
- •Параметри - значення
- •Параметри-змінні
- •Безтипові параметри
- •Приведення типів.
- •Процедурні типи
- •Рекурсія Рекурсивні визначення
- •Рекурсивні підпрограми
- •Алгоритми з поверненням. Розв’язок задачі про рух коня
- •Алгоритми з поверненням. Розв’язок задачі про вісьмох ферзів
- •Модулі в Турбо Паскалі
- •Модуль crt
- •1. Керування екраном
- •2. Робота з клавіатурою
- •3. Інші можливості
- •Графіка в Турбо Паскалі
- •1. Включення і вимикання графічного режиму.
- •2. Побудова елементарних зображень
- •3. Виведення текстової інформації.
- •Файли в мові програмування Pascal
- •Установчі і завершальні операції
- •Операції введення-виведення
- •Обробка помилок введення-виведення
- •Переміщення по файлу
- •Спеціальні операції
- •Текстові файли
- •Двійкові файли
- •Статичні і динамічні змінні
- •Покажчики
- •Стан покажчика
- •Установка розмірів динамічної пам'яті
- •Сумісність і перетворення посилкових типів
- •Динамічні структури даних
- •Динамічні змінні: інші види списків, стек і черга.
- •1. Інші види списків
- •2. Стек і черга
- •Дерева і пошук у деревах
- •1. Визначення й описи структур даних
- •2. Алгоритми
- •Змішані таблиці
- •Об’єктно-орієнтоване програмування. Що таке об’єктно-орієнтоване програмування
- •Інкапсуляція
- •Спадкування
- •Віртуальні методи і поліморфізм
- •Конструктори, динамічні об'єкти і деструктори
- •Поля і методи: сховані і загальнодоступні
- •Системно- залежні розширення
- •Налагодження змінних
- •Оверлеї
- •Переривання і системні виклики
- •Доступ до пам'яті і портів
- •Перевизначення переривань
Сумісність і перетворення посилкових типів
Усі посилкові типи вважаються різними відповідно до загальних правил. Так наприклад, два типи, оголошені як
type
TP1 = ^integer,
TP2 = ^real;
визначають неспівпадаючі множини значень, хоча фізична природа посилкових типів у всіх випадках це адреси в оперативній пам'яті. Тому наступні змінні:
var
P1 : TP1; P2 : TP2;
не можуть передавати один одному значення (наприклад, у присвоюванні). Для посилкових змінних одного типу, зрозуміло, припустимі подібні дії, наприклад:
var
P1, P2 : TP1;
begin
P1 := P2;
Для посилкових типів, так само, як і для скалярних типів, допускаються конструкції явного перетворення. Нехай маються наступні описи:
type
R = record
Hi, Lo : word
end;
PR = ^R;
PL = ^longint;
var
VI : PR; V2 : PL; X : longint;
Змінні VI і V2 є покажчиками на значення різних типів, однак за допомогою конструкції приведення їх можна трактувати як покажчики на той самий тип; наприклад, можливі наступні оператори:
PR(V2)^.Нi := 5;
PL(V1) := @Х; X := PL(V1)^;
Перший оператор перетворить покажчик на довге ціле в покажчик на комбінований тип і використовує його в такій якості для присвоювання значення старшим розрядам числа, на яке посилається V2.
Два наступних оператори, навпаки, інтерпретують запис як іншу форму представлення довгого цілого, присвоюючи покажчик на тип longint покажчику на комбінований тип і поміщаючи значення запису в довге ціле.
Помітимо, що в подібних перетвореннях базові типи покажчиків можуть мати різні розміри; ніяких перевірок на цей рахунок не робиться. Наприклад, для наступного фрагмента:
type
PB = ^byte;
PS - ^string;
var
P1 : PB;
P2 : PS;
В: byte;
begin
P1 := @B;
синтаксично коректної є змінна виду PS(Pl)^[10] яка має тип char як 10-ий елемент рядка, на яку посилається покажчик PS(Pl). Однак, у цій якості дана змінна не зв'язана ні з якою статичною (оголошеною в програмі) змінною, ні з динамічною змінною; P1 посилається на один байт у пам'яті (змінну в), а покажчик PS(P1) - на область з 256 елементів, початок який збігається з адресою змінної В; ця область ні автоматично, ні явно не була виділена програмі, її вміст не визначений, однак мається можливість, власне кажучи, довільного доступу до неї описаним способом. Тому використовувати перетворення посилкових типів потрібно з відомою обережністю і тільки якщо це дійсно необхідно; у будь-якому випадку варто уникати формування покажчиків на області пам'яті, характер умісту яких невідомий.
Динамічні структури даних
Повернемося тепер до питання про економію пам'яті при збереженні табличних даних. З використанням покажчиків можна відмовитися від масиву і використовувати динамічні структури. Найпростіший з них є список, що схематично зображується так:
П рямокутники на цій схемі — динамічні змінні типу запис, Data ( поле (чи поля), що містять корисну інформацію (наприклад прізвища і номери телефонів), поле, що зображене нижче Data — це покажчик на наступну запис. Змінна List також є покажчиком на запис. Жирна крапка в поле «наступний елемент» у самому останньому записі означає, що там лежить значення nil, щоб показати, що цей запис останній в списку.
Для опису списку на Паскалs досить описати тип покажчика на запис і тип самого запису. Виглядає все це так:
type tItemPtr = ^tItem; {покажчик на елемент}
tItem = record
Data: tData; {корисні дані}
Next: tItemPtr; {покажчик на наступний елемент списку}
end;
Оголосити сам список можна як покажчик на елемент:
var List : tItemPtr;
поки наш список порожній, List варто пприсвоїти значення nil. При створенні першого елемента будемо виконувати дії New(List); List^.Next:=nil.
У списках завжди зберігається рівно стільки елементів, скільки потрібно; якщо який-небудь елемент даних утратив свою цінність, то його завжди можна видалити зі списку; якщо з'явилися нові дані, то можна додати новий елемент.
Напишемо тепер модуль для роботи зі списками. У ньому містяться процедури первісної підготовки списку; додавання елемента в початок списку; видалення елемента, що стоїть за зазначеним; пошук елемента з заданим номером; підрахунку елементів і очищення списку.
unit Lists;
interface
type tData = record
Name: string[50];
Phone: longint;
end;
tItemPtr = ^tItem;
tItem = record
Data: tData;
Next: tItemPtr;
end;
procedure InitList(var l: tItemPtr);
procedure AddItemToHead(var l: tItemPtr; d: tData);
function DeleteItemAfter(var l: tItemPtr; num: word): boolean;
function Count(l: tItemPtr): word;
function GetItem(l: tItemPtr; num: word; var d: tData): boolean;
procedure ClearList(var l: tItemPtr);
{--------------------------------------------------------------}
implementation
procedure InitList(var l: tItemPtr);
begin l:=nil end;
procedure AddItemToHead(var l: tItemPtr; d: tData);
var p: tItemPtr;
begin
new(p);
p^.data:=d;
p^.next:=l;
l:=p;
end;
function DeleteItemAfter(var l: tItemPtr; num: word): boolean;
var p,q: tItemPtr;
i: word;
begin
i:=1;
p:=l;
while (i<>num)and(p<>nil) do begin
i:=i+1;
p:=p^.next;
end;
if p<>nil then begin
if p^.next<>nil then begin
q:=p^.next^.next;
dispose(p^.next);
p^.next:=q;
DeleteItemAfter:=true;
end
else DeleteItemAfter:=false; {не вилучений}
end
else DeleteItemAfter:=false;
end;
function Count(l: tItemPtr): word;
var p: tItemPtr;
i: word;
begin
i:=0;
p:=l;
while p<>nil do begin
i:=i+1;
p:=p^.next;
end;
count:=i;
end;
function GetItem(l: tItemPtr; num: word; var d: tData): boolean;
var p: tItemPtr;
i: word;
begin
i:=1;
p:=l;
while (i<>num)and(p<>nil) do begin
i:=i+1;
p:=p^.next;
end;
if p<>nil then begin
d:=p^.data;
GetItem:=true;
end
else GetItem:=false;
end;
procedure ClearList(var l: tItemPtr);
var p: tItemPtr;
begin
while (l<>nil) do begin
p:=l^.next;
dispose(l);
l:=p;
end;
end;
end.