Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

У наведеному прикладі k є формальним параметром-аргументом, с — формальним параметром-результатом.

Підпрограми

Підпрограми призначені для реалізації алгоритмів опрацювання окремих частин деякої складної задачі. Вони дають змогу реалі­зовувати концепцію структурного програму­вання, суть якого поля­гає в розкладанні складної задачі на послідовність простих підзадач і в складан­ні для алгоритмів розв’язування кожної підзадачі від­повідних підпрограм. Розріз­няють два види під­про­грам — під­про­грами-процедури та підпро­грами-функ­ції. Під­програми поді­ля­ються на стандартні та підпрограми користу­вача. Стандартні підпрограми створювати не потрібно — вони містяться у стандартних модулях System, Crt, Dos, Graph тощо. Під­програма користувача — це по­йме­нована група команд, яку створюють і опису­ють в основній програмі в розділах procedure або function і до якої звертаються з будь-якого місця програми потрібну кількість разів.

1. Процедури (procedure). Загальний опис процедури:

procedure <назва> (<список формальних параметрів>); <розділи описів і оголошень процедури>; begin <розділ команд процедури> end;

У списку формальних параметрів перераховують змінні разом із зазначенням їхніх типів. Розрізняють параметри-аргументи (ін­ший термін: параметри-значення) — вхідні дані для процедури, і параметри-результати (інший термін: параметри-змінні), через які можна по­вер­тати результати роботи процедури в основну про­граму. Перед списками параметрів-результатів кожного типу за­пи­сують слово var. Зауважимо, що масиви фіксованих розмірів у списках формальних параметрів не можна описувати за до­помогою слова array (див. зразки програм).

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

Приклад. Розглянемо процедуру з назвою Cina, яка визначає с —вартість k хвилин телефон­ної розмови з похвилинною оплатою 0.6 грн. + 20% ПДВ.

procedure Cina(k:integer; var c:real);

Begin

c:=k*0.6; c:=c+0.2*c;

end;

У наведеному прикладі k є формальним параметром-аргументом, с — формальним параметром-результатом.

До процедури звертаються з розділу команд основної програми або іншої підпрограми. Процедуру викликають за допомогою ко­манди виклику:

<назва процедури> (<список фактичних параметрів>);

Параметри, які записують у команді виклику процедури, нази­ва­ються фактичними. Фактичними параметрами-аргументами мо­жуть бути сталі, змінні, вирази, а параметрами-результатами — лише змін­ні. Типи даних тут не зазначають.

Між фактичними і формальними параметрами має бути відповід­ність за кількістю й типами. Зверніть увагу, відповідні фак­тичні та формаль­ні параметри можуть мати різні імена.

Команда виклику функціонує так: значення фактичних пара­метрів присвоюються відповідним формальним параметрам процеду­ри, виконується процедура, визначаються параметри-результати, зна­­чення яких надаються (повертаються) відповідним фактич­ним па­ра­метрам у команді виклику.

Змінні, описані в розділі описів основної програми, називаються глобальними. Вони діють у всіх підпрограмах, з яких складається про­грама. Змінні, описані в розділі описів конкретної процедури, називаються локальними. Вони діють тільки в межах даної про­це­дури.

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

Задача 1. Розв’язати задачу про кількість викликів на АТС з по­пе­ред­нього параграфа, використовуючи три процедури: 1) для ви­зна­чення кількості викликів за кожну секунду (надамо їй назву Kilvykl); 2) для об­числення суми викликів за перші 10 секунд (Sumavykl); 3) для ви­зна­чення найбільшої кількості викликів за деяку секунду (Maxkilvykl). Використати функцію random.

program ATS1;

uses Crt;

type vyklyk= array [1..10] of integer;

var y:vyklyk; max, s:integer;

procedure Kilvykl(var y:vyklyk); { Процедура Kilvykl визначає }

var i:integer; { кількість викликів кожної секунди }

Begin

for i:=1 to 10 do

Begin

y[i]:=random(i);

writeln('y(', i, ')=', y[i]:5);

end;

end;

procedure Sumavykl(y:vyklyk; var s:integer); { Процедура

обчислює cуму викликів за перші 10 секунд }

var i:integer;

Begin

s:=0; for i:=1 to 10 do s:=s+y[i];

writeln('Сума викликів S=', s:3);

end;

procedure Maxkilvykl(y:vyklyk; var max:integer);

var i:integer; { Процедура Maxkilvykl визначає }

begin { найбільшу кількість викликів}

max:=y[1]; { за деяку секунду}

for i:=2 to 10 do

if max<y[i] then max:=y[i];

write('Максимальна кількість викликів за одну ');

writeln('секунду дорівнює ', max:3)

end;

Begin

clrscr;

randomize;

Kilvykl(y); { Виклик процедури Kilvykl}

Sumavykl(y, s); { Виклик процедури Sumavykl}

Maxkilvykl(y, max); { Виклик процедури Maxkilvykl}

readln

End.

2. Функції (function). Функція, на відміну від процедури, може повертати в місце виклику лише один результат простого стандарт­ного типу.

Загальний опис функції:

function <назва>(<список формальних параметрів>): <тип функції>; <розділи описів і оголошень функції>; begin <розділ команд функції, де має бути така команда: назва:=вираз> end;

У розділі команд функції має бути команда присвоєння значення деякого виразу назві функції. Результат функції поверта­ється в основну програму через її назву (як і випадку вико­ристан­ня станда­рт­них функцій, таких як sin, cos). Виклик функ­ції здійс­ню­ється лише з виразів так:

<назва> (<список фактичних параметрів>).

Приклад. Створимо функцію для обчислення tg(x) та обчислимо значення виразу tg(x)+ctg(x)+tg2(x).

program Myfunc;

uses Crt;

var x,y:real;

function tg(x:real):real;

Begin

tg:=sin(x)/cos(x)

end;

begin clrscr;

writeln('Введіть х');

readln(x);

y:=tg(x)+1/tg(x)+sqr(tg(x));

writeln('y=', y:5:2); readln

End.

Задача 2. Розв’язати задачу про виробництво цукерок на фабри­ці з попереднього параграфа, використовуючи функції і про­цедури користувача.

program Fabryka1;

uses Crt;

const n=5;

type vytraty = array [1..n, 1..n] of real;

var imin:integer; a:vytraty;

function func(i,j:integer):real;

Begin

func:=2*abs(sin(i))+j;

end;

procedure Table(var a:vytraty);

var i,j:integer;

Begin

writeln(' Вид сировини');

writeln(' 1 2 3 4 5');

for i:=1 to n do {Утворимо таблицю затрат}

Begin

write(i, ' сорт');

for j:=1 to n do

Begin

a[i,j]:=func(i,j); {Використаємо створену функцію}

write(a[i,j]:7:2); {Роздрукуємо елементи і-го рядка}

end;

writeln {Перейдемо на новий рядок}

end;

end;

procedure MinSyrov(a:vytraty; var imin:integer);

var i,j:integer; min:real;

Begin

imin:=1; min:=a[1,3];

for i:=2 to n do

if a[i,3]<min then

Begin

min:=a[i,3]; imin:=i

end;

writeln('Найменше сировини третього виду ');

writeln('необхідно для цукерок ', imin, ' сорту')

end;

Begin

clrscr;

Table(a); {Виклик процедури Table }

MinSyrov(a, imin); {Виклик процедури MinSyrov }

readln

End.

3. Рекурсивні функції. Рекурсією називається алго­ритміч­на кон­ст­рукція, де підпрограма викликає сама себе. Рекурсія дає змо­гу записувати циклічний алгоритм, не використовуючи команду цик­­лу. Розглянемо спочатку поняття стеку.

Стек — це структура даних в оперативної пам’яті, де дані запа­м’я­товуються і зберігаються за принципом «перший при­йшов — останнім пішов». Ана­логом у військовій справі є ріжок для набоїв до автомата.

Приклад. Рекурсивна функція обчислення суми цілих чисел від a до b має вигляд

function Suma(a,b:integer):integer;

Begin

if a=b then Suma:= a { Це стоп-умова рекурсії }

else Suma:= b + Suma(a, b–1) { Це неявний цикл }

end;

Обчислимо функцію Suma(3, 5). Формально можна записати Su­ma(3, 5) = 5 + Suma(3, 4) = 5 + 4 + Suma(3, 3) = 5 + 4 + 3. Систе­ма ви­конує такі обчислення за два етапи: 1) спочатку формує стек, куди заносить числа 5, 4, 3. На другому етапі числа додає у зворот­ній послідовності (оскільки вони надходять зі стеку): 3+4+5 = 12.

Задача 3. Скласти рекурсивну функцiю Factorial для обчис­лення факторіала числа n! = 1·2·3·...· n, (0! = 1, 1! = 1), яка грунтується на багато­разовому (рекурсивному) застосуваннi формули n! = n ·(n – 1)!.

function Factorial(n: integer): integer;

Begin

if n = 0 then Factorial:= 1 { Це стоп-умова }

else Factorial:= n * Factorial(n–1)

end;

Обчислимо 4!: Factorial(4) = 4 · Factorial(3) = 4 · 3 · Factorial(2) = 4 · 3 · 2 · Factorial(1) = 4 · 3 · 2 · 1 · Factorial(0) = 4 · 3 · 2 · 1 · 1. У стек будуть занесені числа 4, 3, 2, 1, 1. Результат утвориться так: 1 · 1 · 2 · 3 · 4 = 24.

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

Завдання 3. Скласти програму розв’язування задачі 6, викори­стовуючи рекурсивні функції.

4. Відкриті масиви. У списках формальних параметрів підпрог­рами можна описувати так звані відкриті масиви (масиви зазда­легідь невідомого розміру) так:

<назва масиву>: array of<назва базового типу>;

У підпрограмі мінімальне значення індекса такого масиву є 0, а номер останнього елемента дає стандартна функція high (<назва масиву>). Нумерація елементів такого формального масиву у підпрог­рамі починається з нуля. Відкритий масив використовують для почер­гового опрацювання у процедурі масивів різних розмірів.

Задача 4. Використовуючи підпрограми, утворити масив y, еле­мен­ти якого задані фор­му­лою ут = fy (m)=10cos(m)+2, , та масив g з елементами gn=fg (n) =n 2/2, . Об­числити в цих масивах суми еле­мен­тів більших, ніж 2. Вивести на екран резуль­тати обчислень.

program MyProcedure;

{$F+}

uses Crt;

type myfunc= function (n:integer):real;

var y: array [1..7] of real;

g: array [1..9] of real;

function fy(m:integer):real;

Begin

y:=10*cos(m)+2

end;

function fg(n:integer):real;

Begin

g:=n*n/2

end;

procedure Utvoryty(f:myfunc; var z: array of real);

var i:integer;

Begin

for i:=0 to high (z) do

Begin

z[i]:=f(i+1); write(z[i]:5:2);

end;

writeln

end;

function suma(z: array of real):real;

var i:integer; s: real;

Begin

s:=0;

for i:=0 to high (z) do

if z[i]>2 then s:=s+z[i];

suma:=s

end;

Begin

clrscr;

Utvoryty(fy, y);

Utvoryty(fg, g);

write('Сума потрібних елементів y – ');

writeln('S=', suma(y):6:2);

write('Сума потрібних елементів g – ');

writeln('S=', suma(g):6:2);

readln

End.

Зауваження. Зверніть увагу на утворення та застосування нового типу – типу функції: type myfunc= function (n:integer):real. До цього типу віднесено конкретні функції fy (x) та fg (x). Завдяки типу myfunc можна за допомогою однієї процедури утворю­ва­ти різні масиви. У зв'язку з цим використано директиву {$F+}, яка під­тримує необхідну модель (far-модель) виклику функцій.

5. Стандартні модулі. Підпрограми, які мають універсальне при­зна­­чення та можуть згодитись багатьом користувачам, варто об’єд­нувати у бібліотеки та модулі.

Модуль — незалежна програмна одиниця. Він містить описи констант, ти­пів даних, змінних та підпрограм. Розрізняють стандартні модулі та мо­дулі, створені користувачем.

Є такі стандартні модулі:

Crt— для роботи з екраном і клавіатурою; System— містить найчастіше вживані процедури та функ­ції; String — містить функції для роботи з рядковими змінними; Printer— для роботи з пристроєм друкування; Graph — містить процедури та функції для графічних побудов; Overlay — модуль засобів для роботи з великими програ­мами; Dos, Windows— дають змогу виконувати команди опера­ційної системи під час виконання паскаль-прог­рам чи отримувати певні дані від операційної системи; Graph3, Turbo3— забезпечують сумісність з попередніми вер­сіями ТР тощо.

Під’єднання модулів у конкретній програмі здійснюють за до­по­могою команди

uses <список назв модулів>;

Процедури і функції модуля System можна застосовувати за замовчу­ванням. Саме з цього модуля компілятор бере процедури read, readln, write, writeln, стандартні функції sin, cos тощо.

Розглянемо по чотири корисні процедури з модулів System та Crt:

exit— для виходу з поточної підпрограми або при­пи­нен­ня роботи основної програми; halt — для зупинки виконання програми і передачі керу­ван­ня в операційну систему; break — для примусового виходу з циклів for, while, repeat; continue— для переходу до виконання наступної ітерації в циклах for, while, repeat; delay(n) — для затримки виконання наступної команди на заданий (n) користувачем час (у мікросекундах); clrscr —дляочищення екрану перед виконанням про­грами; textcolor(колір) —задання кольору (числом від 0 до 15) текста; textbackground(колір) —для задання кольору тла (фону).

З-поміж функцій модуля Crt часто застосовують символьну фун­кцію readkey, яка отримує значення натиснутого користувачем символу на основній символьно-цифровій частині клавіатури, а також логічну функцію keypressed, яка набуде значення true, якщо користувач натисне на будь-яку клавішу на основній клавіатурі.

У модулі Dos є процедури і функції для роботи з файловою сис­темою в режимі виконання паскаль-програми. Про­цедура

exec ('<повна назва exe-файлу>', '<параметри програми>' або '')

служить для запуску на виконання exe-файлу іншої програми з середини програми користувача (на початку програми користувача слід зазначити директиву {$M $2000,0,1000}, див. довідники). Корисними є також дві процедури, які дають змогу хронометрувати час вико­нання програми користувача чи її фрагментів і опрацьо­вувати дати:

GetTime (Hour, Minute, Second, SotiSec) надає зазначеним у спи­с­ку змінним числові значення поточного часу (год, хв, сек, соті сек);

GetDate (Year, Month, Day, Number) надає змінним зі списку типу word значення поточної дати(рік, місяць, день, день тижня).

Завдання 5. Розгляньте завдання № 3 з § 5 про обчислення зна­ко­змінної суми трьо­ма способами з точністю e =0,00001 (§ 5, п.2, задача-зразок № 4, власна задача-завдання № 7 з розділу "Задачі"). Зро­біть exe-файли для відповідних трьох програм. Складіть програму, яка буде складатися з директиви {$M...}, команди uses Crt, Dos; трьох команд типу exec('suma1.exe', ''); декількох команд get­time(...), розташованих так, щоб хронометрувати час виконання процесором кожної з під’єднаних програм. Визначіть час у мікро­се­кундах, затрачений процесором для розв’язування задачі кожним способом. Який спосіб найефективніший за часом обчислень?

6. Модулі користувача (unit). Свій модуль користувач будує за певними правилами. Струк­тура модуля така:

unit <назва>; interface {інтерфейсна частина} <розділ описів> implementation {реалізаційна частина} <тексти підпрограм користувача> begin <блок ініціалізації> end.

Назву модулю дає користувач. Вона має бути унікальною. У роз­ділі описів оголошують інші потрібні модулі, описують типи, сталі та заголовки підпрограм, доступні у даному модулі.

У реалізаційній частині наводять тексти підпрограм за порядком згадування їхніх заголовків у описах. Списки параметрів можна не писати, оскільки вони наведені в описах заголовків. Інтерфейс і реалізаційна частина можуть бути порожніми. Таку можливість використовують, коли необхідно описати, наприклад, спільні для багатьох програм сталі, змінні, типи даних.

У блоці ініціалізації у разі потреби задають початкові дані, від­кривають файли, чистять екран тощо. Цей блок виконується першим, тобто перед командами основного блоку головної програ­ми, до якої приєднаний даний модуль. Якщо стартовий блок не потрібний, то службове слово begin опускають.

Модулі використовуються, зокрема, у візуальному програмуванні (див. розділ 3).

Приклад. Створимо модуль для обчислення значень функцій tg(x), xy . Під час звертання до нього очистимо екран.

unit Mymodul;

Interface

uses Crt;

function tg(x:real):real;

function step(x,y:real):real;

Implementation

function tg(x:real):real;

Begin

tg:=sin(x)/cos(x)

end;

function step(x,y:real):real;

Begin

step:=exp(y*ln(x))

end;

begin clrscr

End.

Щоб оформити підпрограму як модуль в меню середовища Турбо Паскаль в пункті Compile/Destination встановлюємо значення Disk і транслюємо її (Ctrl+F9). На диску отримаємо файл з тим же іме­нем, але з розширенням tpu. Модуль створено.

Приклад. Обчислимо tg(x) і 1.35, використовуючи модуль Mymodul.

program UseModul;

uses Mymodul;

var x,y,a,b,c:real;

Begin

a:=1.3; b:=5;

writeln('Введіть x:');

readln(x);

y:=tg(x);

writeln('tg(', x:5:2,')=', y:6:2);

c:=step(a, b);

writeln('1.3^5=', c:5:2);

readln

End.

Окремі модулі користувач може об’єднати в особисту бібліотеку (на­приклад Mybibl.tpl) за допомогою програми TpuMover, вико­навши в середовищі MS-DOS команду

tpumover <повний шлях до файлу>\Mybibl.tpl /+ Mymodul

Зауваження. Файл Mybibl.tpl необхідно розташувати в каталозі, де немає файла з системною бібліотекою turbo.tpl.

 

Поделиться:





Читайте также:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...