Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

_TPLab_My_Посібник

.pdf
Скачиваний:
20
Добавлен:
08.06.2015
Размер:
1.85 Mб
Скачать

ЛАБОРАТОРНА РОБОТА № 9 Проектування та відлагодження програм опрацювання файлових типів даних

МЕТА РОБОТИ: Навчитись проектувати алгоритми та програми опрацювання файлових типів даних з використанням вивчених операторів та процедур і функцій для роботи з файлами.

ЗАВДАННЯ:

Спроектувати алгоритми та програми розв’язання задач опрацювання файлових типів даних за варіантами завдань, номери яких визначає викладач.

МЕТОДИЧНІ ВКАЗІВКИ

1.Перед виконанням роботи необхідно пригадати:

логічну структуру програми на мові Turbo Pascal;

правила опису простих та структурованих типів даних;

правила запису виразів;

синтаксис основних операторів;

синтаксис опису та правила застосування стандартних (бібліотечних) процедур і функцій та підпрограм користувача.

2.Перед виконанням цієї роботи необхідно вивчити:

типи файлів та правила опису файлових змінних;

синтаксис опису та правила застосування процедури зв’язування логічного файлу з фізичним;

синтаксис опису та правила застосування процедур ініціації файлів;

допустимі операції над файлами;

синтаксис опису та правила застосування процедур і функцій опрацювання файлів.

3.Перевірка правильності роботи програми здійснюється шляхом аналізу отриманих результатів та порівняння вхідних даних і результатів опрацювання файлів.

ВІДОМОСТІ З ТЕОРІЇ

Означення 1. Файловий тип даних, або файл, визначає впорядковану сукупність довільного числа однотипних компонент (або елементів).

Кількість компонент файлу у тексті програми не визначається і може бути довільною (обмежується тільки об’ємом носія даних).

Для роботи з файлами у програмі необхідно визначити файлову змінну.

Означення 2. Оголошена в програмі змінна файлового типу називається логічним файлом.

Turbo Pascal підтримує три файлових типи: типізовані (компонентні) файли, нетипізовані (безтипові) файли та текстові файли.

Означення 3. Типізований (або компонентний файл) - це файл з оголошеним типом його компонент.

Компонентами файлу можуть бути всі прості та структуровані типи, крім файлів.

Означення 4. Нетипізовані описуються службовим словом File і для них не вказується тип компонент файлу.

Означення 5. Текстовий файл - це сукупність рядків змінної довжини.

Кожний рядок завершується ознакою кінця рядка - EOLN (end of line). Закінчується файл символом закінчення файлу – EOF (end of file) з кодом #26. Текстові файли описують за допомогою слова Text:

Приклад опису файлових змінних:

Туре Student = Record

Prizv, Name, Father: String[20]; Year: Word; Ngrup: String[5];

End;

Var F1: Text;

F2: File of Byte;

F3: File of Student; F4: File;

81

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)

У цьому фрагменті програми F1 - файлова змінна текстового типу, F2 і F3 – типізовані файлові змінні, причому F2 може містити тільки однобайтні елементи, а у файлі F3 кожний компонент є записом із трьох елементів, F4 - файлова змінна нетипізованого типу.

Означення 6. Фізичний файл - це іменована область зовнішньої пам’яті комп’ютера (жорсткого або гнучкого магнітного диску, оптичного диску чи будь-якого іншого носія) яка містить логічно пов’язані дані (програми) або логічний пристрій – потенційне джерело чи приймач інформації.

ЛОГІЧНІ ПРИСТРОЇ

Стандартні апаратні засоби ПК, такі як клавіатура, екран дисплея, пристрій друку (принтер) і комунікаційні канали введення-виведення, визначаються в Turbo Pascal спеціальними іменами, які називаються логічними пристроями. Всі вони в Turbo Pascal розглядаються як потенційні джерела або приймачі текстової інформації.

Con - логічне ім'я консолi - клавіатура або екран монітора.

Prn - логічне ім'я принтера. Якщо до комп’ютера підключено кілька принтерів, їх логічні імена

LPT1, LPT2 і LPT3.

Aux (СОМ1 і COM2) - логічні імена комунікаційних каналів (портів). Nul - логічне ім'я «порожнього» пристрою.

Зв’язок логічного файлу з фізичним файлом встановлюється динамічно, тобто в процесі виконання програми, в результаті звертання (виклику) до спеціальної стандартної процедури Assign.

Assign (<ф.зм.>, <ім’я_файлу_або_л.п.>); ,

де <ф.зм.> - файлова змінна, <ім’я_файлу_або_л.п.> - рядковий вираз, який визначає повне ім’я фізичного файлу або логічного пристрою.

Якщо ім’я файлу задається у вигляді порожнього рядка, наприклад, Assigns (f, ''), то залежно від напрямку обміну даними файлова змінна зв’язується зі стандартним файлом ІNPUT або OUTPUT.

Assign (F1, 'd:\catalog1\catalog2\catalog3\file_rez.dat');

Assign(F2, 'Inform.txt'); Assign(F, PRN);

Assign (Fо, LPT1);

Процедура Assign Crt (<ф.зм.>); зв’язує текстовий файл <ф.зм.> з пристроєм Crt (терміналом).

ІНІЦІАЦІЯ ФАЙЛУ.

Означення 7. Ініціювати файл означає вказати для цього файлу напрям передачі даних.

В Turbo Pascal можна відкрити файл для читання, для запису даних, а також для читання і запису одночасно.

Reset (<ф.зм.>); - ініціація файлу для читання.

Rewrite (<ф.зм.>); - ініціація нового файлу для запису даних.

Append (<ф.зм.>); - ініціація існуючого текстового файлу для додання («дозапису») нових даних.

ПРОЦЕДУРИ ТА ФУНКЦІЇ ДЛЯ РОБОТИ

ЗУСІМА ТИПАМИ ФАЙЛІВ.

процедура Close (<ф.зм.>) - закриває логічний файл <ф.зм.>.

процедура Rename (<ф.зм.>; NewName: String) - перейменовує фізичний файл, пов'язаний з логічним файлом <ф.зм.>.

процедура Erase (<ф.зм.>) - знищує фізичний файл, який пов'язаний з файловою змінною <ф.зм.>. Файл до моменту виклику процедури Erase має бути закритий;

функція IOResult : Integer - повертає ціле число, відповідне коду останньої помилки введеннявиведення. При нормальному завершенні операції функція поверне значення 0. Значення функції IOResult необхідно привласнювати деякій змінній, оскільки при кожному виклику функція обнулює своє значення. Функція IOResult працює тільки при вимкненому режимі перевірки помилок введеннявиведення або з ключем компіляції;

логічна функція EOF (<ф.зм.>) : Boolean - повертає True, коли при читанні досягнуто кінця файлу

<ф.зм.>.

82

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)

ПРОЦЕДУРИ ТА ФУНКЦІЇ ДЛЯ РОБОТИ

ЗТИПІЗОВАНИМИ ФАЙЛАМИ.

процедура Read (<ф.зм.>,<список_введення>) - зчитування компонент файлу <ф.зм.>. Тут < список_введення > - список, що містить одну або більше змінних такого ж типу, що й компоненти файлу;

процедура Write (<ф.зм.>,<список_виведення>) - запис даних у файл <ф.зм.>;

процедура Seek (<ф.зм.>, <N компоненти> : Longіnt) - зміщує покажчик файлу <ф.зм.> до компоненти номером <N компоненти>. Перша компонента файлу має номер 0;

процедура Truncate (<ф.зм.>) встановлює у поточній позиції ознаку кінця файлу і видаляє (стирає) всі наступні блоки.

функція Fіlesіze (<ф.зм.>): Longіnt - повертає кількість компонент файлу <ф.зм.>;

функція Fіlepos (<ф.зм.>): Longіnt - повертає порядковий номер компоненти файлу <ф.зм.>, що буде оброблятися наступною операцією введення-виведення.

ПРОЦЕДУРИ ТА ФУНКЦІЇ ДЛЯ РОБОТИ З НЕТИПІЗОВАНИМИ ФАЙЛАМИ.

При роботі з нетипізованими файлами можуть застосовуватися всі процедури й функції, доступні типізованим файлам, за винятком Read і Wrіte, які заміняються відповідно високошвидкісними процедурами:

BlockRead (<ф.зм.>; X; Count: Word; QuantBlock: Word); - зчитування з файлу <ф.зм.> в змінну Х кількості блоків, задану параметром Count. Значення Count не може бути меншим 1.

BlockWrite (<ф.зм.>; X; Count:Word; QuantBlock:Word); - запис у файл <ф.зм.> із змінної Х кількість блоків, задану параметром Count. Необов'язковий параметр QuantBlock повертає число блоків, записаних операцією BlockWrite.

ПРОЦЕДУРИ ТА ФУНКЦІЇ ДЛЯ РОБОТИ

ЗТЕКСТОВИМИ ФАЙЛАМИ.

процедура Read (<ф.зм.>, <список_введення>) - зчитування даних з текстового файлу <ф.зм.> у список введення – послідовність з однієї або кількох змінних цілого, дійсного, символьного або рядкового типу.

процедура Readln (<ф.зм.>) - пропускає рядок до початку наступного;

процедура Readln (<ф.зм.>, <список_введення>) - з файлу <ф.зм.> послідовно зчитуються рядки і присвоюються змінним із списку введення;

процедура Write (<ф.зм.>, <список_виведення>) - запис значень змінних із списку виведення у текстовий файл <ф.зм.>. Список виведення – послідовність з однієї або кількох змінних цілого, дійсного, символьного, логічного або рядкового типу.

процедура Writeln (<ф.зм.>) - завершує рядок файлу <ф.зм.>, в який проводиться запис, ознакою кінця рядка і переходить до початку наступного.

процедура Append (<ф.зм.>) – відкриває текстовий файл для дозаписування даних у кінець файлу;

процедура Flush (<ф.зм.>; Text) - записує у відкритий файл дані з буфера незалежно від ступеня його заповнення;

функція EOLn (<ф.зм.>) : Boolean - повертає значення TRUE, якщо досягнуто кінця рядка;

функція SeekEOLn (<ф.зм.>): Boolean - пропускає всі пропуски і знаки табуляції до маркера кінця рядка EOLN або до першого значущого символу і повертає значення True, якщо маркер виявлено (тобто, якщо до кінця рядка залишилися тільки пропуски).

функція SeekEOF (<ф.зм.>) : Boolean - пропускає всі пропуски, знаки табуляції і маркери кінця рядка EOLN до маркера кінця файлу або до першого значущого символу і повертає значення True, якщо маркер виявлено (тобто, якщо до кінця файлу залишилися рядки, заповнені пропусками).

Розглянемо програму, що вводить із клавіатури список прізвищ учнів, а потім роздруковує його, крім тих учнів, у яких прізвище починається з літери K. Так як заздалегідь кількість даних не відомо, то для їхнього зберігання використаємо файл. Тип елементів - рядковий.

Program L;

Var i, n: Integer;

83

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)

f: File Of String; s: String;

Begin

Assign (f, 'Spis.dat'); {Зв’язуємо змінну f з файлом Spis.dat}

Writeln (' Введіть кількість учнів ');

Readln (n);

{Вводимо кількість учнів}

Rewrite (f);

{Створюємо файл для запису в нього даних}

For i 1 To n Do {Для всіх учнів}

Begin

Writeln (' Введіть прізвище ');

Readln (s);

Write (f,s)

End;

Close (f);

Reset (f);

Writeln;

Writeln (' Список учнів:');

While Not (EOF (f)) Do

Begin

Read (f,s);

If s[1]<>'K' Then Writeln (s)

End;

Close (f)

End.

Розглянемо приклад програми, яка підраховує загальну кількість символів у файлі і результат ділить на 40000 - таким способом можна оцінити обсяг рукопису в так званих обліково-видавничих аркушах:

Const Sum=LongInt; {Тут буде кількість символів}

Var f: Text;

s: String;

 

Begin

 

Write (' Ім’я файлу:');

{Запитуємо ...}

Readln (s);

{і вводимо ім’я файлу}

Assign (f, s);

 

Reset (f);

{Відкриваємо файл}

While not EOF (f) Do {Кількість символів у файлі}

Begin

Readln (f, s); {Зчитуємо рядок}

Inc (Sum, Length (s));

{Збільшуємо Sum на кількість символів зчитаного рядка}

End ;

Close (f); {Закриваємо файл}

Writeln (' Об’єм = ', Sum/40000:6:2, ' обл.вид.арк. ')

End.

КОНТРОЛЬНІ ЗАПИТАННЯ:

1.В яких випадках зручно використовувати файли?

2.Як формується повне ім’я файлу?

3.Які типи файлів визначені в Turbo Pascal?

4.Які файли називаються «файлами прямого доступу»?

5.Як здійснюється доступ до компонент файлу?

6.Які операції визначені над файлами?

7.В чому полягає різниця між операторами Read і Readln?

8.В чому полягає різниця між операторами Write і Writeln?

9.Як визначити кількість компонент файлу?

84

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)

10. Як визначити наявність файлу із заданим іменем?

ЗАВДАННЯ ДЛЯ САМОСТІЙНОГО ВИКОНАННЯ.

Завдання 1: Модифікувати свою програму опрацювання записів (списків студентів) таким чином, щоб введені з клавіатури дані про студентів були записані у файл на диску; завдання свого варіанту виконати зчитуючи записи з файлу.

Завдання 2.

1.Створити файл, який n містить n натуральних чисел від 1 до 100. Парні числа записати в один (новий) файл, непарні – в інший.

2.Створити текстовий файл та скопіювати в нього вміст файлуautoexec.bat.

3.Створити текстовий файл, який містить прізвище, ім’я та по-батькові одного студентів. Дописати у файл дані ще про одного студента та поміняти їх прізвища.

4.Створити файл з результатами складання сесії – прізвище, оцінки з 3-5 предметів та файл-відомість нарахування стипендії (прізвище, сума) за середнім балом. Критерії нарахування стипендії та її розмір визначити самостійно.

5.Записати в текстовий файл 100 випадкових чисел від -100 до 100 в 5 стовпців з точністю 5 знаків після коми.

6.Додати літеру «а» на початок кожного рядка текстового файлу.

7.Вибрати з текстового файлу рядки довжиною <= 10 символів та записати їх в інший файл.

8.Переписати текст з одного файлу в інший продублювавши всі цифри.

9.Переписати текст з одного файлу в інший, видаливши всі зайві «пробіли» та щоб кожен рядок містив рівно 15 символів.

10.Переписати компоненти файлу цілих чисел в новий файл – спочатку від’ємні, а потім додатні.

11.В текстовому файлі замінити кожну цифру на наступну по величині (9 замінити на 0).

12.В текстовому файлі замінити останній символ кожного рядка на 1.

13.Переписати вміст символьного файлу в інший файл, замінивши всі знаки оклику на знак запитання.

14.У файлі масивів дійсних чисел обчислити середнє арифметичне кожного масиву та записати ці числа в новий файл з точністю 6 знаків після коми.

15.Вирізати з тексту програми на мові Turbo Pascal всі коментарі.

16.В текстовий файл з кількома прізвищами студентів додати за запитом («Бажаєте додати прізвища?») користувача ще кілька прізвищ.

17.Створити текстовий файл, який містить N рядків по M символів *(зірочка). M та N задає користувач.

18.Ввести в текстовий файл прізвища кількох студентів. В новий файл вивести ті прізвища, які починаються із заданої літери.

19.Створити типізований файл, який містить квадрати чисел від 1 до 20. За запитом користувача «Бажаєте записати числа за спаданням?» записати у новий файл квадрати чисел від 20 до 1.

20.Створити типізований файл, який містить числа від 1 до 100, кратні 3. За запитом користувача «Знайти середнє арифметичне?» створити текстовий файл, який містить середнє арифметичне чисел.

21.Створити текстовий файл, який містить прізвища студентів. За запитом користувача підрахувати загальну кількість введених літер (без пробілів).

22.Створити текстовий файл, який містить координати вершин кількох трикутників. Обчислити площі трикутників та записати їх в новий файл.

23.Створити текстовий файл, в який записати (ввести з клавіатури) довільне число. Визначити, яке число введене користувачем - дробове, ціле чи натуральне.

24.Створити текстовий файл, який містить назви трьох дисциплін. Дописати в початок файлу назви ще двох дисциплін.

25.Записати в один файл масив 50 дійсних чисел за спаданням, а в інший файл - за зростанням. Масив сформувати в діапазоні від -15 до +15 функцією Random.

Примітка: Початкові файли для завдань 6-16 можна підготувати в текстовому редакторі Блокнот.

85

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)

86

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)

ЛАБОРАТОРНА РОБОТА № 10 Проектування та відлагодження програм опрацювання посилальних типів даних (вказівників)

МЕТА РОБОТИ: Навчитись проектувати алгоритми та програми опрацювання посилальних типів даних.

ЗАВДАННЯ:

Спроектувати алгоритми та програми розв’язання задач опрацювання посилальних типів даних за варіантами завдань, номери яких визначає викладач.

МЕТОДИЧНІ ВКАЗІВКИ

1.Перед виконанням роботи необхідно пригадати:

логічну структуру програми на мові Turbo Pascal;

правила опису простих та структурованих типів даних;

правила запису виразів;

синтаксис основних операторів;

синтаксис опису та правила застосування стандартних (бібліотечних) процедур і функцій.

2.Перед виконанням цієї роботи необхідно вивчити:

правила розподілу пам'яті при виконанні програми;

правила опису вказівників;

способи ініціалізації вказівників;

способи доступу до змінної за вказівником;

допустимі операції над вказівниками;

процедури та функції керування динамічною пам'яттю;

процедури та функції створення, опрацювання та знищення динамічних змінних;

способи опису та опрацювання динамічних масивів великої розмірності.

3.Перевірка правильності роботи програми здійснюється шляхом аналізу отриманих результатів на основі порівняння вхідних та результатів обчислень.

ВІДОМОСТІ З ТЕОРІЇ. Організація (розподіл) пам'яті.

В ІВМ-сумісних комп’ютерахоперативна пам'ять умовно розділена на частини.

Під час виконання програми оперативна пам'ять комп'ютерарозподіляється на частини:

Означення 1. Сегмент даних (64Кб=65536 байт) - неперервна область пам'яті, в якій розміщується код виконуваної програми та глобальні змінні;

Означення 2. Сегмент стеку (від 1024 до 65520 байт, за замовчуванням 16384 байт) - область пам'яті, що виділяється для розміщення локальних змінних;

Означення 3. Динамічна пам'ять (heap – купа) – весь вільний (доступний) об'єм оперативної пам'яті комп'ютера – до 640Кб.

Тут мається на увазі оперативна пам'ять, яка може прямо адресуватися (адресний простір), об’ємом 1 Мбайт. Сучасні персональні комп’ютери, звичайно, мають значно більшу оперативну пам'ять. Наприклад, комп’ютери з 32-розрядними процесорами (80386 і вище) та 32-розрядна операційна система Windows (Windows 98 і вище) забезпечують пряму адресацію оперативної пам'яті об’ємом до 4 Гбайт. Однак, в Turbo Pascal (на відміну від Borland Pascal with Object 7.0) немає засобів підтримки роботи з додатковою пам’яттю.

Статичні і динамічні змінні.

Всі змінні, які описуються в розділі опису змінних (Var) і які позначаються ідентифікаторами, Н.Вірт назвав статичними змінними. Ці змінні використовуються тоді, коли пам'ять, використовувана програмою, відома (передбачувана) у момент її написання. Розподіл пам'яті для статичних змінних відбувається повністю автоматично і відповідно до стекової дисципліни. Але існує ряд задач, для яких неможливо передбачити розмір пам'яті в момент написання програми. В цих задачах необхідний інший підхід: змінні потрібно формувати динамічно, не пов'язуючи їх із структурою програми. Оскільки засобів для явних описів таких змінних не існує, то звертатися до них за їх іменами (ідентифікаторами) неможливо. Єдиним способом доступу (звернення) до таких змінних є використання спеціальних змінних посилального типу - вказівників, значеннями яких є адреси розміщення змінних в динамічній пам'яті. Сам вказівник є статичною змінною і займає 4 байти. Turbo Pascal дає можливість як утворювати,

87

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)

так і знищувати такі змінні у будь-який момент роботи програми, в залежності від потреб вирішуваної задачі. Змінні, створенням і знищенням яких може явно керувати програміст, називаються динамічними змінними.

Означення 4. Вказівник - це змінна посилального типу, яка містить адресу динамічної змінної базового типу.

При визначенні вказівника використовується ідентифікатор базового типу, перед яким ставиться ознака вказівника - символ ^.

Синтаксис опису посилального типу:

Туре<ім'я типу_вказівника> =^ <ім’я_базового_типу>;

Базовим типом для посилального типу може бути будь-який попередньо описаний або стандартний тип даних.

В стандартній змінній-вказівнику HeapOrg зберігається адреса початку купи, адреса її кінця - в змінній-вказівнику HeapEnd. Адреса поточної межі вільної динамічної пам'яті міститься в стандартній змінній-вказівнику HeapPtr.

Наприклад:

Туре

Mas = Array [1..20] Integer; {базовий тип}

Pmas=^Mas; {посилальний тип на масив} Pin= ^Integer; {посилальний тип на ціле число} Pr = ^Real; {посилальний тип на дійсне число}

Конкретні вказівники на динамічні змінніописуються в розділі описузмінних:

Var pb: ^Byte; pd: ^ Real; pd1: Pr; ps: ^String; pm1: ^Mas; pm2: Pmas; pi1: Pin;

a: Mas; i: Integer;

Всі вище описані вказівники називаються типізованими, так як вказують на об'єкти визначеного типу. В мові Turbo Pascal можна, також використовувати нетипізовані вказівники, які, на відміну

від типізованих, не зв'язані з конкретним типом. Такі вказівники описують, вживаючи службове слово

Pointer:

Var pl, p2: Pointer;

Ці вказівники сумісні з будь-якими типізованими вказівниками, тобто вказівник р1 може одержати, як значення вказівника на ціле число, так і значення вказівника на дійсне число.

Вказівник на вказівник.

Так як базовим типом для посилального типу може бути будь-який тип даних, в тому числі і посилальний, тому допустимо означення «вказівник на вказівник». Наприклад, для змінних оголошеного вище посилального типу Ріn можливий наступний опис:

Var рр1: ^Pin;

Ініціалізація вказівників.

Вказівник може отримати значення - адресу динамічної змінної, на яку він вказує, одним із наступних способів:

-взяття адреси за допомогою унарноїоперації @: @<ідентифікатор>;

-за допомогою оператора присвоювання (сумісні типи);

-за допомогою стандартної процедури New;

-за допомогою стандартної процедури GetMem.

Наприклад, в результаті виконання операторів

88

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)

pi1 @i; pm1 @a[2];

значенням змінної pі1 стане адреса змінної i, а змінної pm1 – адреса другого елемента масиву a. Схематично це зображено на рис. 1.

pi1

 

i

pm1

a

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Рисунок 1. Операція взяття адреси.

Значенням вказівника може бути адреса змінної, яка в свою чергу є вказівником. Тому допустимо присвоювання:

p2 @pd;

Значенням будь-якої посилальної змінної може бути не тільки адреса змінної базового типу, але і спеціальна константа – «нульовий» вказівник. Нульовий вказівник позначається службовим словом NIL і може бути присвоєний будь-якій змінній посилального типу. При виконанні операції присвоювання pl:= NIL значення р1 визначене і рівне NIL, що означає, що р1 не вказує ні на яку змінну базового типу.

Створення динамічних змінних.

Пам'ять під деяку динамічну змінну можна виділити (іншими словами - створити динамічну змінну) за допомогою стандартної процедури New (Var p: Pointer), параметром якої є посилальний тип. Тобто в процедуру New передається тип вказівника на динамічний об’єкт, але не сам вказівник.

При виконанні оператора New (pd):

1)в купі виділяється 6 байт для динамічної змінної дійсного типу;

2)посилальна змінна pd вказує на тільки що створену динамічну змінну і містить адресу виділеної ділянки (першого байту) пам'яті.

Таким чином ми одержуємо динамічну змінну, імені (ідентифікатора) у якої немає, тому пряме звернення до такої змінної просто неможливе. Єдиний спосіб доступу до неї – це непряме звернення шляхом розіменування (див. нижче «Операція розіменування») посилальної змінної рd, яка містить

вказівник на дану динамічну змінну:

рd ^ 77.7;

Процедуру New можна використовувати уфункціональній формі:

рd New(Pr);

У цьому варіанті параметром функції New є ім’я вказівного типу, а результатом функції є вказівник цього типу, який посилається на відведенуобласть для значення базового типу. В багатьохвипадкахтакий спосіб використання New є зручнішим.

Знищення динамічних змінних.

Динамічні змінні створюються в ході виконання програми, в залежності від потреб вирішуваної задачі. Як тільки необхідність в них відпадає, щоб уникнути переповнення динамічної пам'яті, їх потрібно знищувати. Знищення динамічних змінних здійснюється за допомогою процедури Dispose (Var р: Pointer), параметром якої є типізований вказівник, що вказує на динамічну змінну, якавидаляється:

Dispose (pd);

Процедуру Dispose не можна використовувати спільно з Mark чи Release. Після виконання даної процедури значення вказівника-параметра стає невизначеним і звертатись до нього не можна.

Операції над вказівниками.

Над посилальними змінними допустимі наступні операції: перевизначення адреси, перевірка на рівність і нерівність. Звичайно, ці операції допустимі для вказівників одного типу.

Якщо в програмі відбувається перевизначення адреси (переустановка вказівника) р1 2, то попередньо потрібно застосувати процедуру Dispose(р1), інакше в динамічній пам’яті утворюється область, до якої не можна звернутись – так назване «сміття».

При порівнянні вказівників різних типів необхідно використати явне перетворення типу.

За допомогою операцій порівняння можна, наприклад, перевірити, чи посилаються два вказівника на одну і ту ж змінну.

Наприклад:

р1 2;

89

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)

If p1=p2 Then...

If pi1<>nil Then ...

Операція розіменування.

Існує два способи доступу до змінних. Перший спосіб - звернення до змінної за її іменем (ідентифікатором), називається прямим способом. Другий - звернення до змінної за її адресою, що міститься в вказівнику. Такий спосіб доступу називається непрямим.

Для звернення до змінної за її адресою, яка знаходиться в посилальній змінній, використовують операцію «розіменування».

Означення 5. Операція розіменування - це запис, який дозволяє отримати доступ до змінної за вказівником.

Якщо до посилальної змінної звернутися за її іменем, то ми отримаємо адресу змінної базового типу. Якщо ж після імені вказівника поставити символ ^, то ми отримаємо доступ до тієї змінної, на яку посилається (вказує) даний вказівник. Тому оператори

 

 

і }

i

i + 1; {прямий доступ до змінної

pil^ рi1^ + 1; {непрямий доступ до змінноїі }

повністю аналогічні і виконують одну і ту ж дію.

У випадку використання «вказівника на вказівник» можливе багатократне розіменування, наприклад:

рр1^^ { непрямий доступ до змінної і}

Розіменування посилальної змінної, значенням якої є Nil є неприпустимим, оскільки в цьому випадку не існує змінної, на яку посилається вказівник.

Слід враховувати, що посилальний тип не є стандартним, тому значення змінних цього типу не можна роздрукувати за допомогою процедури Write чи Writeln.

Переглянути або вивести значення змінних посилального типу можна одним з наступних способів.

По-перше, значення вказівника можна переглянути, занісши його ім’я до вікна Watch IDE Turbo

Pascal.

По-друге, можна використати операцію перетворення вказівника у змінну стандартного типу. Всі адреси в системі IBM PC мають формат

< сегмент > : < зміщення >, де сегмент – номер сегмента оперативної пам’яті, зміщення – адреса стосовно початку сегмента. Обидві

складові адреси займають по два байти, томувказівник p1 можна привести до типу LongInt:

Writeln (LongInt (p1));

По-третє, можна інтерпретувати складові адреси як поля змінної типу запис:

Type Adress=Record Seg, Ofs: Word

End;

……

Begin

With Adress(p1) Do Writeln (Seg, ':', Ofs);

……

Керування динамічною пам'яттю.

Розмір купи можна регулювати за допомогою директиви компілятору $M або задати при налаштуванні середовища Turbo Pascal (Options Compiler Memory size).

Можливість організації динамічних змінних в ході виконання програми пов'язана з небезпекою «переповнення» купи. У випадку, якщо в купі не знайдеться місця для нової динамічної змінної, вона не створюється. Така ситуація може стати прихованою причиною збоїв програми. Тому, при інтенсивному використанні динамічних змінних об’єм купи необхідно контролювати за допомогою спеціальних процедур і функцій.

90

Print to PDF without this message by purchasing novaPDF (http://www.novapdf.com/)