Б С Бусигін - Прикладна інформатика - страница 48

Страницы:
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83 

кількість протоколів на вузлі; p -номер протоколу}

Begin

FillChar(A,  SizeOf(A),  0);  {Убудована процедура заповнення

масиву (A) числом ( SizeOf(A) , де SizeOf - убудована функція, що повертає розмір типу з ім'ям A ) значенням (0 )}

cnt  := 0;  {Ініціалізація cnt}

for i:=1 to n do {Цикл по числу n вузлів мережі, прочитаних в

основній програмі з файлу e.dat}

begin

Read(f,   sc);   {Читаємо з файлу e.dat кількість протоколів

sc на вузлі i } for j:=l to sc do {Цикл по числу sc протоколів}

begin

read(f,     p);     {Читаємо   з   файлу   e.dat номера

протоколів}

include(A[i],       p);       {Включаємо убудованою

процедурою include номера протоколів у    i -ту множину

TProtocolSet}

end;

end

End;   {Proc Init}

Begin {Початок основної програми} ClrScr;  {Очищаємо екран}

Assign    (f,    'e.dat');    {Установлюємо зв'язок між логічним

файлом f і фізичним файлом e.dat} Reset(f);  {Відкриваємо логічний файл f для читання} Read(f, N);  {Читаємо з файлу e.dat кількість вузлів мережі N} Init;   {Викликаємо процедуру зчитування даних про протоколи з файлу e.dat}

Rec(1);    {Передаємо   пакет  у   перший   вузол.   Рекурсивно він

поширюється в усі інші, якщо це можливо} WriteLn(cnt);  {Друкуємо результат - кількість вузлів} Close(f);  {Закриваємо фізичний файл e.dat} End.

При застосуванні рекурсії варто піклуватися про те, щоб можна з неї було вийти. Рекурсія в цьому прикладі не нескінченна, вихід з неї передбачений: ми перевіряємо факт відвідування (обробки) вузла оператором:

if was[p]   then exit;

і якщо вузол вже був оброблений, виходимо з рекурсії.

1. Створіть рекурсивну програму «Ханойська Вежа (рос.-башня)». Умова наступна: мається дошка з трьома кілочками (рис. 8.88). На першому з них нанизано кілька дисків зростаючого до низу діаметра. Потрібно розташувати ці диски в такому ж порядку на третьому кілочку. Диски можна перекладати тільки по одному, а класти більший на менший не можна.

1 2 3

Рис. 8.88. Вигляд гри «Ханойська Вежа»

Алгоритм рішення головоломки наступний:

1.1. Перемістити верхні п-1 дисків на 2-ий кілочок.

1.2. Нижній диск із першого кілочка перемістити на третій.

1.3. Перемістити п-1 дисків на третій кілочок, використовуючи перший у якості допоміжного.

1.4. Повторювати, поки на третьому кілочку не буде сформована нова піраміда.

Вихідна задача зводиться до двох про перенос п-1 диска й одній задачі про перенос одного диска. Для п=1 потрібно одне переміщення.

2. Розробіть програму з застосуванням множин для рішення наступної задачі: користувачу пропонується ввести одну з букв А, Ь, Р чи Т, причому байдуже в якому регістрі - прописному чи рядковому. Якщо те, що введе користувач, буде відмінно від кожної з зазначених літер, програма повинна надрукувати повідомлення, що запрошує до повторного введення.

3. У текстовому файлі містяться довжини сторін 20 прямокутних паралелепіпедів. Обчислити обсяги цих паралелепіпедів. Результати розрахунку записати у файл у виді таблиці, що містить стовпчики: довжина першої сторони паралелепіпеда, довжина другої сторони паралелепіпеда, довжина третьої сторони паралелепіпеда, об'єм паралелепіпеда. Подбайте про відповідні заголовки для стовпчиків.

Файл із вихідними даними сформуйте за допомогою текстового редактора.

4. Трансформуйте текст програми про доставку пакетів у мережі (мал. 76) так, щоб у процедури глобальні параметри передавалися через формальні параметри.

8.27. Записи, Посилання, динамічні змінні й структури

8.27.1. Тип "запис" (record) й оператор приєднання with

Для компактного представлення комбінацій різнотипних даних у Турбо Паскалі їх можна об'єднувати в структурі-записи. Кожен запис складається з оголошеного числа полів і визначається конструкцією:

Var

InfRec  : Record;

Пoле1 : Тип пoля1; Пoле2   :  Тип пoля2;

ПoлеN  : Tип_пoляN

End;

Де Тип_юля^ це деякий тип даних ТП. Зверніть увагу, що після службового слова Var перед описом типу даних Record ставиться знак (:), а після Type - знак (=) (дивись наступний приклад).

Якщо типи декількох полів збігаються, то імена полів можуть бути просто перераховані (рос.-перечислены), наприклад - x,y :

Type

PointRecType = record x,y  :   Integer end; Var

Point  : PointRecType; Px,   Py  : Integer;

{Звертання до полів запису:} Px  := Point.x; Py := Point.y;

Оскільки імена полів «сховані» у середині типу, то вони можуть дублювати «зовнішні» змінні і поля в інших описах записів:

Type

PointRecType = record x,  y  :  integer end; ColorPointType = record

x,  y  : integer; color  : word end;

Var

X,  Y  : integer; Point  : pointRecType; ColorPoint  : ColorPointRecType;

Зверніть увагу також на те, що у цьому прикладі х, Point.x і ColorPoint.x - зовсім різні значення.

Наприклад, Ви можете розробити свої користувальницькі типи даних (рис. 8.89). Зв'язок значення у операторі варіантної частини запису з певними значеннями компілятором ніяк не відстежується. Запис з варіантами може використовуватися, наприклад, для читання полів різних типів з файлів бази даних у одну й ту ж область пам'яті. Type

OS =   (MS_DOS,   CPM,  MPM, Unix);

CPU =   (I8088,   I8086,   I80186,   I80286, I80386);

Computer = Record

OperatingSystem

Processor

Price

MadeIn

Array[1

CPU;

Real;

String[80];

4] of OS;

End;

Var

Users Type

List = : Array[1..50]   of Computer;

record

Name : String[40];

BirthDay  : Word;

Case Citizen  :  Boolean Of

True  :   (BirthPlace  : String[40] False: (Country Port

ExitDate EntryDate

end;

String[20]; String[18];

Word; Word);

Рис. S.S9. Приклад конструювання типів "запис"

Змінна типу "запис" може брати участь тільки в операціях присвоювання. Але поле запису може брати участь у всіх операціях, які відносяться до типу цього поля. Для доступу до полів запису застосовується кваліфікаційне ім'я

(рис. 8.89):

Users[3].Processor Для полегшення роботи з полями записів вводиться оператор приєднання (рос. - присоединения) With:

With <Ім'яЗмінноїЗапису> do <Оператор>;

Усередині оператора With (він може бути складеним) звертання до полів запису виробляється прямо (рис. S.90). Усередині області дії оператора приєднання With можуть вказуватися і змінні, що не мають відношення до запису, але необхідно дотримуватись наступних правил (рис. 8.91).

У випадку, якщо одне з полів запису саме є записом і знову містить поля запису, оператор приєднання можна поширити на декілька полів усередину, перелічивши їх через кому. Але усередині тіла оператора можна звертатися тільки до останніх полів:

With Им'яЗапису.ПолеЗапис do

Begin

{Звертання до полів Поле Запис, тобто до тих, яким передувала конструкція "Им'яЗапису.ПолеЗапис"} End; {With}

{ Два еквівалентних способу звертання до полів запису рис. S.S9} { Перший:}

Users.OperatingSystem Users.Processor Users.Price Users.MadeIn

{Другий:}

With Users Do Begin

OperatingSystem

Processor

Price

MadeIn End;

MS_DOS; I80286;

=2250; = 'Taiwan'

=MS_DOS;

I80286; 2250;

= 'Taiwan';

Рис. S.90. Два еквівалентних способу звертання до полів запису

Program Main; Var

X,  y,   z  : integer;

RecXY  :  record x,  y  :   Integer end; Begin

X  := 10;    Y  := 2 0;

With RecXY do

Begin

X := 3.14 * Main.X І Z;  {«Main» - квалификатор} Y := 3.14 * Main.Y І Z;  {для «розв'язки» співпадаючих

ідентифікаторів. Для Z не потрібно}

End; {With}

End.

Рис. 8.91. Змінні, що не мають відношення до запису у операторі With

8.27.2. Система адресації MS-DOS

Адресуємий простір пам'яті в MS-DOS організовано сегментами: послідовними блоками пам'яті по 64Кб кожний. Якщо Вам відомий сегмент, то подальше уточнення адреси відбувається по його зсуву (рос - смещению), тобто номеру байта від початку сегмента. Таким чином, будь-яка ячейка адресуємого простору пам'яті визначається парою чисел:

<СЕГМЕНТ> : <ЗСУВ>,

який займає чотири байти: 2 байти <СЕГМЕНТ> і 2 байти <ЗСУВ>. Такий спосіб дозволяє адресувати більший простір оперативної пам'яті меншими числами. Щоб Вам простіше було це представити, наведемо такий приклад. У деякому районі побудовано 20 будинків по 99 квартир. Потрібно знайти спосіб адресації, щоб не виходити за межи двозначних чисел, бо наскрізна нумерація всіх квартир потребує можливості представляти максимальне число:

20x99 = 1980,

яке займає чотири розряди. Вихід з такої ситуації полягає у подвійній адресації:

<БУДИНОК> : <КВАРТИРА>

Тоді будь-яку квартиру Ви можете знайти по номеру будинку та номеру квартири у цьому будинку. Наприклад, будинок 10, квартира 67:

<10> : <б7>,

тоді як при наскрізній нумерації було б потрібно три розряди: 10x67 = 670.

8.27.3. Тип Pointer

Основним механізмом для організації динамічних даних у ТП є виділення в спеціальній області пам'яті, називаною «купою» (рос. - куча), ділянки (блоку) необхідного розміру і збереження адреси початку цієї ділянки в спеціальній змінній у форматі <СЕГМЕНТ> : <ЗСУВ>.

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

Var

p : Pointer; {Змінна-указник}

Значення цього типу займають 4 байти пам'яті і містять адресу початку будь-якого об'єкту ТП. Адреса зберігається як два слова, тобто дві змінні типу Word (кожна з них займає у пам'яті 2 байти): одне з них задає сегмент, а інше - зсув. Значення указника не може бути виведене на екран та на друк. Його треба попередньо розшифровувати.

Майте на увазі, що компілятор ТП завжди повинен знати, який об'єкт адресується, щоб коректно його обробляти. Згадайте, що змінна типу Integer займає у пам'яті 2 байти, змінна типу LongInt - 4 байтЬ, змінна типу Real - б байтів, змінна типу Byte займає у пам'яті 1 байтів і т.д (див додаток 7).

Ще одна з тонкощів роботи у ТП полягає в тому, що коли Ви пишете листа до близької людини, то відступаєте абзаци, грамотно формулюєте фрази, де потрібно ставите коми, тире, крапки і т.д. Так от, програма, яку Ви пишете до транслятора, теж повинна бути грамотно написана, щоб він зміг її зрозуміти...

8.27.4. Засоби роботи з адресами

Для початку розглянемо функції для роботи з адресами різних об'єктів ТП (табл.. 52).

Таблиця 52

_Функції для роботи з адресами різних об'єктів ТП_

Функція : Тип

Значення, яке повертається

Addr(X)   : Pointer

Посилання на початок об'єкту X у пам'яті

Seg(X)   : Word

Сегмент, у якому зберігається об'єкт X

Ofs(X)   : Word

Зсув у сегменті для об'єкту X

Ptr(S,   0  : Word) : Pointer

Посилання  на  місце  у  пам'яті  яке задане значеннями зсуву 0 і сегменту Б

SizeOf(X)   : Word        Розмір об'єкту X у байтах

Операція @X : Pointer

Повертає посилання на початок об'єкту X у пам'яті (аналог функції Асісіг)

Функції Addr (X), Seg(X) та Ofs(X), а також оператор @ повертають адресу об'єкту X або компоненти цієї адреси. Під змінною X можна розуміти будь-який об'єкт: змінні вбудованих типів ТП, користувацькі типи, об'єкти, процедури і функції (але не константи).

Функція Addr (X) та оператор @ повертають значення типу Pointer -адресу об'єкту X. Їх дія однакова:

Страницы:
1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20  21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40  41  42  43  44  45  46  47  48  49  50  51  52  53  54  55  56  57  58  59  60  61  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78  79  80  81  82  83 


Похожие статьи

Б С Бусигін - Прикладна інформатика