logo
методичка_1_05_ВНУ

Процедури з параметрами. Параметри-значення

Описана процедура mах2а не дуже зручна в користуванні, оскільки для неї жорстко зафіксовані вхідні дані а та b так, що перед кожним звертанням до процедури цим змінним потрібно присвоїти значення, з яких треба вибрати більше. Щоб уник­нути цього обмеження, в мові Паскаль передбачено змогу не фіксувати вхідних даних, з якими повинна працювати проце­дура, а зробити їх параметрами процедури, які конкретизува­тимуться під час кожного звертання до процедури.

Стосовно процедури mах2а введемо формально два іденти­фікатори, наприклад г1 і г2, якими відобразимо значення, які порівнюють і з яких вибирають більше, і щодо них запишемо тіло процедури:

begin

if r1>r2

then s:=r1

else s:=r2

end

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

procedure max2b(r1, г2: real);

begin

if r1>r2

then s:=r1

else s:=r2

end;

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

Тепер наведену вище програму можна записати так:

program maxd(input, output);

var

x, у, u, v: real;

s: real;

procedure max2b(r1, r2: real);

begin

if r1>r2

then s:=r1

else s:=r2

end;

begin

read(x.y);

max2b(x+y,x*y);

u:=s;

max2b(0.5,u);

v:=s;

writeln('u=',u,' v=',v);

end.

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

Виконання оператора процедури max2b(x+y, x*y) відповідає виконанню такого еквівалентного йому блоку:

var

r1, r2: real;

begin

r1 :=x+y; r2:=x*y;

begin

if r1>r2

then s:=r1

else s:=r2

end

end.

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

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

Параметри-змінні

Для того, щоб результат обчислень у тілі процедури зручно було використати в програмі, треба не фіксувати змінну, якій присвоюється одержане значення, а зробити її також парамет­ром. Позначимо цю змінну, наприклад, res і введемо її в список формальних параметрів процедури. Однак параметр res суттєво відрізняється від формальних параметрів г1 і г2. Він у тілі про­цедури повинен бути не значенням, а деякою змінною, яка існує поза тілом процедури. І щоб процедура могла присвоїти зна­чення такій змінній, треба забезпечити безпосередній доступ до цієї змінної з процедури, а для цього потрібно, щоб відпо­відний параметр був параметром-змінною.

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

На відміну від формального параметра-значення, для якого фактичним параметром може бути будь-який вираз відповід­ного типу, для формального параметра-змінної фактичним па­раметром може бути тільки змінна відповідного типу.

Тепер програму можна записати так:

program maxe(input, output);

var

x, у, u, v: real;

procedure max2d(r1. r2: real; var res: real);

begin

if r1>r2

then res:=r1

else s:=r2

end;

begin

read(x, y);

max2d(x+y, x*y, u);

max2d(0.5, u, v);

writeln('u=', u,' v=', v) ;

end.

У цьому випадку виконання оператора-процедури max2d(x+y, x*y,u) рівносильне виконанню еквівалентного блоку:

var

r1, r2: real;

begin

r1 :=x+y; r2:=x*y;

if r1>r2

then u:=r1

else u:=r2

end .

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

ФУНКЦІЇ

У математиці за допомогою функцій задають залежності одних величин від інших, які називають аргументами. Такі за­лежності бувають у вигляді таблиць, графічні, аналітичні тощо. В алгоритмічних мовах розглядають лише функції, для яких можна задати алгоритм визначення їхніх значень. Мова Паскаль допускає тільки такі функції, значення яких належать до прос­тих типів. Для визначення функцій використовують опис функ­цій, який розміщують у розділі опису процедур і функцій. За­гальний вигляд опису функцій такий:

function <ім'я_функції>(<список_формальних_параметрів>):<тип_функції>;

<блок>

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

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

У блоці описуваної функції повинен бути хоча б один опе­ратор типу

<ім'я функції> := <вираз>

Це означає, що за значення функції прийнято значення при­своюваного виразу. Таких операторів присвоєння може бути декілька, проте хоча б один повинен виконуватись у процесі виконання процедури. Як остаточне значення функції прий­мають результат останнього за часом виконання оператора присвоєння. Наприклад, функцію f(n)=n! можна описати так:

function FACT(n: integer): integer;

var і, k: integer;

begin

k:=1;

for i:=1 to n do k:=k*i;

FACT:=k;

end;

Як відомо, у мові Паскаль є набір стандартних функцій, які описувати не потрібно. Можна вважати, що ці описи попе­редньо вставляє транслятор у розділ опису процедур і функцій трансльованої програми.

Звертатися до функції можна за допомогою виклику. Ви­клик - це ім'я функції, після якого в круглих дужках може бути список фактичних параметрів. Наприклад, sin(x+y), FACT(10).

Виклик функції використовують як операнд деякого виразу. Наприклад, для обчислення p=(k+1)! можна застосувати опи­сану функцію обчислення факторіала і записати в програмі

p:=FACT(k+1).

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

Рекурсивні функції і процедури

Деякі функції можна визначати рекурсивно. Наприклад, f(n)=n! можна визначити так:

Тобто це є визначенням функції через цю саму функцію. У мові Паскаль рекурсивний опис функції полягає в тому, що в тілі такої функції міститься звертання до цієї ж функції. На­ведемо рекурсивний опис функції n!:

function FACT2(n: integer): integer;

begin

if n=0

then FACT2:=1

else FACT2:=n*FACT2(n-1)

end;

Зазначимо, що в лівій частині оператора присвоєння FACT2 не означає рекурсивності. Рекурсія є в правій частині, де наявне звертання до функції FACT2 з параметром n-1.

Під час обчислення FACT2(3), наприклад, відбувається послідовне вираження FACT3(3) через FACT2(2), FACT2(2) через FACT2(1), FACT2(1) через FACT2(0)=1. Тоді FACT2(1)=1; FACT2(2)=2*1=2; FACT2(3)=3*2=6;

У цьому випадку неявно вводяться додаткові змінні. Ви­користання рекурсії робить програму компактнішою, однак по­требує додаткового машинного часу і пам'яті.

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

Рекурсивний опис полягає в тому, що у виконуваній частині процедури або функції міститься звертання до неї самої. При­кладом рекурсивного опису є розглянута функція обчислення факторіала. У випадку рекурсивного опису потрібна наявність базової частини опису, яка забезпечувала б завершення рекур­сивних викликів функції або процедури. В наведеному при­кладі такою базовою частиною, що забезпечує досягнення ситуації, коли FACT(n) не залежить від FACT(n-1), є визначення функції FACT(0)=1 при n=0.