Створення бібліотек підпрограм у Turbo Pascal h2>
Стандартний
мова Pascal не має коштів розробки та підтримки бібліотек
програміста (на відміну, скажімо, від мови Fortran та інших мов
програмування високого рівня), які компілюються окремо і в
надалі можуть бути використані як самим розробником, так і іншими. Якщо
програміст має досить великі напрацювання, і ті або інші підпрограми
можуть бути використані при написанні нових додатків, то доводиться ці
підпрограми цілком включати в новий текст. p>
В
Turbo Pascal це обмеження долається за рахунок, по-перше, введення
зовнішніх процедур, по-друге, розробки та використання модулів. У цій
публікації на прикладах розглянемо роботу з тими і іншими програмними
одиницями. p>
Почнемо
з зовнішніх підпрограм. p>
Такий
механізм передбачає, що вихідний текст кожної процедури або функції
зберігається в окремому файлі і при необхідності за допомогою спеціальної директиви
компілятора включається в текст створюваної програми. p>
Покажемо
це на прикладі задач цілочисельний арифметики, де аргументи, результати та
проміжні величини є цілими (Integer, Word, LongInt і т.д.). Ось
кілька таких завдань. p>
1.
Дано натуральне число n. Знайти суму перших та останньої цифри цього числа. P>
2.
Дано натуральне число n. Переставити місцями першу і останню цифри цього
числа. p>
3.
Дано натуральне число n. Дописати до нього цифру k в кінець і на початок (якщо це
можливо, тобто результат не вийде за діапазон допустимих значень), або
повідомити про неможливість виконання операції. p>
4.
Знайти найбільшу цифру в запису даного натурального числа. P>
5.
Дано натуральне число n. Переставити його цифри так, щоб утворилося
Максимальна кількість, записане тими ж цифрами. p>
При
вирішенні кожної з цих завдань може бути використана функція, що повертає
кількість цифр у запису натурального числа. p>
Ось
можливий варіант такої функції: p>
Function Digits (N: LongInt): Byte; p>
Var Kol: Byte; p>
Begin p>
Kol: = 0; p>
While N 0 Do Begin Kol: = Kol + 1; N: = N Div 10 End; p>
Digits: = Kol p>
End; p>
Збережемо
цей текст у файлі з розширенням. inc (це розширення зовнішніх підпрограм в
Turbo Pascal), наприклад, digits.inc. P>
Ще
необхідна функція зведення натурального числа в натуральну ступінь. p>
Function Power (A, N: LongInt):
LongInt; (файл
power.inc) p>
Var I, St: LongInt; p>
Begin p>
St: = 1; p>
For I: = 1 To N Do St: = St * A; p>
Power: = St p>
End; p>
Спробуємо
використовувати функції при вирішенні завдання номер один. p>
Program Example1; p>
Var N, S: LongInt; p>
($ I
digits.inc) (підключаємо зовнішню функцію digits.inc, повертає кількість
цифр у записі числа) p>
($ I
power.inc) (зовнішня функція, що виконує зведення числа A до степеня N) p>
Begin p>
Write ( 'Введіть натуральне число:'); p>
ReadLn (N); p>
(для
визначення останньої цифри числа N беремо залишок від ділення цього числа на 10,
а для визначення першого ділимо N на 10 в ступені на одиницю меншу, ніж
кількість цифр у записі числа
(розрядів нумерація починається з 0)) p>
S: = N Mod 10 + N Div Power (10, Digits (N) - 1); p>
WriteLn ( 'Бажаєма сума:', S) p>
End. p>
Зовнішні
процедури створюються і впроваджуються в використовують їх програми аналогічно
функцій, і ми не будемо детально на цьому зупинятися. p>
Далі
мова піде про модулях: їхній структурі, розробки, компіляції та використанні. p>
Модуль
- Це набір ресурсів (функцій, процедур, констант, змінних, типів і т.д.),
розробляються і зберігаються незалежно від використовують їх програм. На відміну від
зовнішніх підпрограм модуль може містити достатньо великий набір процедур і
функцій, а також інших ресурсів для розробки програм. Зазвичай кожен модуль
містить логічно пов'язані між собою програмні ресурси. p>
В
основі ідеї модульності лежать принципи структурного програмування. Існують
стандартні модулі Turbo Pascal, які зазвичай описуються в літературі по
даного мови. p>
Модуль
має наступну структуру: p>
Unit
; (Заголовок модуля) p>
Interface p>
(інтерфейсна частину) p>
Implementation p>
(розділ реалізації) p>
Begin p>
(розділ ініціалізації модуля) p>
End. p>
Після
службового слова Unit записується ім'я модуля, яке (для зручності подальших
дій) має збігатися з ім'ям файлу, що містить даний модуль. Тому
(як прийнято в MS DOS) ім'я не повинно бути більше ніж 8 символів. p>
В
розділі Interface оголошуються всі ресурси, які будуть надалі доступні
програмісту при підключенні модуля. Для підпрограм тут вказується лише
повний заголовок. p>
В
розділі Implementation реалізуються всі підпрограми, які були раніше оголошені.
Крім того, тут можуть міститися свої константи, змінні, типи,
підпрограми і т.д., які носять допоміжний характер і використовуються для
написання основних підпрограм. На відміну від ресурсів, оголошених у роздiлi
Interface, все, що додатково оголошується в Implementation, вже не буде
доступно при підключенні модуля. При написанні основних підпрограм достатньо
вказати їх ім'я (тобто не потрібно повністю переписувати весь заголовок), а потім
записати тіло підпрограми. p>
Нарешті,
розділ ініціалізації (який часто відсутня) містить оператори, які
повинні бути виконані відразу ж після запуску програми, що використовує модуль. p>
Наведемо
приклад розробки і використання модуля. Оскільки розглянута нижче завдання
досить елементарна, обмежимося лістингом програми з докладними
коментарями. p>
Завдання.
Реалізувати у вигляді модуля набір підпрограм для виконання наступних операцій
над звичайними дробами виду P/Q (P - ціле, Q - натуральне): 1) складання;
2) віднімання; 3) множення; 4) розподіл; 5) скорочення дробу; 6) зведення
дробу до степеня N (N - натуральне); 7) функції, що реалізують операції відносини
(так само, не дорівнює, більше або дорівнює, менше або дорівнює, більше, менше). p>
Дріб
представити таким типом: p>
Type Frac = Record p>
P: Integer; p>
Q: 1 .. High (LongInt) p>
End; p>
Використовуючи
цей модуль, вирішити завдання: p>
1.
Дано масив A - масив звичайних дробів. Знайти суму всіх дробів, відповідь
представити у вигляді несократімой дробу. Обчислити середнє арифметичне всіх дробів,
відповідь представити у вигляді несократімой дробу. p>
2.
Дано масив A - масив звичайних дробів. Відсортувати його в порядку
зростання. p>
Unit Droby; p>
Interface p>
Type p>
Natur = 1 .. High (LongInt); p>
Frac = Record p>
P: LongInt; (Чисельник дробу) p>
Q: Natur (Чисельник дробу) p>
End; p>
Procedure Sokr (Var A: Frac); p>
Procedure Summa (A, B: Frac; Var C:
Frac); p>
Procedure Raznost (A, B: Frac; Var C
: Frac); p>
Procedure Proizvedenie (A, B: Frac;
Var C: Frac); p>
Procedure Chastnoe (A, B: Frac; Var
C: Frac); p>
Procedure Stepen (A: Frac; N:
Natur; Var C: Frac); p>
Function Menshe (A, B: Frac):
Boolean; p>
Function Bolshe (A, B: Frac):
Boolean; p>
Function Ravno (A, B: Frac):
Boolean; p>
Function MensheRavno (A, B: Frac):
Boolean; p>
Function BolsheRavno (A, B: Frac):
Boolean; p>
Function NeRavno (A, B: Frac):
Boolean; p>
(Розділ
реалізації модуля) p>
Implementation p>
(Найбільший
спільний дільник двох чисел - допоміжна функція, що раніше не оголошена) p>
Function NodEvklid (A, B: Natur):
Natur; p>
Begin p>
While A B Do p>
If A> B Then p>
If A Mod B 0 Then A: = A Mod B
Else A: = B p>
Else p>
If B Mod A 0 Then B: = B Mod A
Else B: = A; p>
NodEvklid: = A p>
End; p>
Procedure Sokr; (Скорочення дробу) p>
Var M, N: Natur; p>
Begin p>
If A.P 0 Then p>
Begin p>
If A.P <0 Then M: = Abs (A.P) p>
Else M: = AP; (Поєднання типів, тому що A.P - LongInt) p>
N: = NodEvklid (M, AQ); AP: = AP Div N; AQ: = AQ Div N p>
End p>
End; p>
Procedure Summa; (Сума дробів) p>
Begin p>
(Чисельник дробу)
C.Q: = (A.Q * B.Q) Div NodEvklid (A.Q, B.Q); p>
(Чисельник дробу) CP: = AP * CQ Div AQ + BP * CQ Div
B.Q; p>
Sokr (C) p>
End; p>
Procedure Raznost; (Різниця дробів) p>
Begin p>
(Чисельник дробу) CQ: = (AQ * BQ) Div
NodEvklid (A.Q, B.Q); p>
(Чисельник дробу)
C.P: = A.P * C.Q Div A.Q - B.P * C.Q Div B.Q; p>
Sokr (C) p>
End; p>
Procedure Proizvedenie; p>
Begin p>
(Чисельник дробу) CQ: = AQ * BQ; p>
(Чисельник дробу) CP: = AP * BP; p>
Sokr (C) p>
End; p>
Procedure Chastnoe; p>
Begin p>
(Чисельник дробу)
C.Q: = A.Q * B.P; p>
(Чисельник дробу) CP: = AP * BQ; p>
Sokr (C) p>
End; p>
Procedure Stepen; (Ступінь) p>
Var I: Natur; p>
Begin p>
C.Q: = 1; C.P: = 1; Sokr (A); p>
For I: = 1 To N Do Proizvedenie (A, C, C) p>
End; p>
Function Menshe; p>
Begin Menshe: = A.P * B.Q
Function Bolshe; p>
Begin Bolshe: = AP * BQ> AQ * BP End; p>
Function Ravno; p>
Begin Ravno: = A.P * B.Q = A.Q * B.P
End; p>
Function BolsheRavno; p>
Begin BolsheRavno: = Bolshe (A, B) Or
Ravno (A, B) End; p>
Function MensheRavno; p>
Begin MensheRavno: = Menshe (A, B) Or
Ravno (A, B) End; p>
Function NeRavno; p>
Begin NeRavno: = Not Ravno (A, B) End; p>
(Розділ
ініціалізації модуля) p>
Begin p>
End. p>
Дамо
деякі рекомендації з розробки модулів: p>
1)
спроектувати модуль, тобто виділити основні та допоміжні підпрограми,
інші ресурси; p>
2)
кожну підпрограму доцільно налагодити окремо, після чого «вклеїти» в
текст модуля. p>
Збережемо
текст розробленої програми у файлі DROBY.PAS і откомпіліруем наш модуль. Для
цього можна скористатися зовнішнім компілятором, що поставляються разом з Turbo
Pascal. Команда буде виглядати так: TPC DROBY.PAS. Якщо в тексті немає
синтаксичних помилок, отримаємо файл DROBY.TPU, інакше буде відповідне
повідомлення із зазначенням рядка, що містить помилку. Інший спосіб компіляції
модуля - у середовищі програмування Turbo Pascal вибрати у пункті меню Run
підпункти Make або Build (при цьому повинна бути включена компіляція на диск). p>
Тепер
можна підключити модуль до програми, де планується його використання. p>
Для
приклад вирішимо завдання підсумовування масиву дробів. p>
Program Sum; p>
Uses Droby; p>
Var A: Array [1 .. 100] Of Frac; p>
I, N: Integer; p>
S: Frac; p>
Begin p>
Write ( 'Введіть кількість елементів
масиву:'); p>
ReadLn (N); p>
SP: = 0; SQ: = 1; (Спочатку сума
дорівнює нулю) p>
For I: = 1 To N Do (Вводимо та підсумовуємо дробу) p>
Begin p>
Write ( 'Введіть чисельник', I,
'-й дробу:'); ReadLn (A [I]. P); p>
Write ( 'Введіть знаменник',
I, '-й дробу:'); ReadLn (A [I]. Q); p>
Summa (A [I], S, S); p>
End; p>
WriteLn ( 'Відповідь:
', S.P,'/', S.Q) p>
End. p>
Другу
завдання пропонуємо вирішити читачеві самостійно. p>
Як
видно з прикладу, для підключення модуля використовується службове слово USES,
після чого вказується ім'я модуля і відбувається це відразу ж після заголовка
програми. Якщо необхідно підключити декілька модулів, вони перераховуються
через кому. p>
При
використанні ресурсів модуля зовсім не потрібно знати, як працюють його
підпрограми. Достатньо володіти інформацією, як виглядають їх заголовки і
яку дію ці підпрограми виконують. За таким принципом здійснюється
робота з усіма стандартними модулями. Тому, якщо програміст розробляє
модулі не тільки для особистого користування, йому необхідно зробити повне
опис всіх доступних при підключенні ресурсів. У такому випадку можлива
повноцінна робота з таким продуктом. p>
Ще
кілька слів про видимості об'єктів модуля. Якщо в програмі, що використовує
модуль, є ідентифікатори, що збігаються з точністю до символу з
ідентифікаторами модуля, то вони «перекривають» відповідні ресурси модуля.
Тим не менше, навіть у такій ситуації доступ до цих ресурсів модуля може бути
отриманий таким чином: .. p>
В
Насамкінець наведемо набір завдань, що дозволяють отримати певні навички в
розробці модулів. p>
I.
Реалізувати у вигляді модуля набір підпрограм для виконання наступних операцій
над комплексними числами: 1) складання; 2) віднімання; 3) множення; 4) розподіл;
5) обчислення модуля комплексного числа; 6) зведення комплексного числа в
ступінь n (n - натуральне). p>
Комплексне
число представити таким типом: p>
Type Complex = Record p>
R, M: Real;
(дійсна і уявна частина числа) p>
End; p>
Використовуючи
цей модуль, вирішити завдання: p>
1.
Дано масив A - масив комплексних чисел. Отримати масив C, елементами якого
будуть модулі сум поруч стоять комплексних чисел. p>
2.
Дано масив A [M] - масив комплексних чисел. Отримати матрицю B [N, M], кожна
рядок якої виходить зведенням до степеня, що дорівнює номеру цього рядка,
відповідних елементів даного масиву A. p>
II.
Реалізувати у вигляді модуля набір підпрограм для виконання наступних операцій з
квадратними матрицями: 1) складання двох матриць; 2) множення однієї матриці на
іншу; 3) знаходження транспонований матриці; 4) обчислення визначника матриці. p>
Матрицю
описати таким чином: p>
Const NMax = 10; p>
Type Matrica = Array [1 .. NMax, 1 .. Nmax] Of Real; p>
Використовуючи
цей модуль, вирішити наступні завдання: p>
1.
Вирішити систему лінійних рівнянь N-го порядку (2