Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Основи програмування Паскаль.docx
Скачиваний:
51
Добавлен:
12.05.2015
Размер:
511.7 Кб
Скачать

18.1 Процедури

Загальний вид підпрограми-процедури наступний:

Procedure Ім'я (Список формальних параметрів);

{вище - заголовок підпрограми}

Var опису локальних змінних;

Begin

{Тіло процедури}

End;

Інші підрозділи розділу описів, такі як label,constі досліджуваний нижче операторtype, також можуть бути присутнім між заголовком і тілом процедури й дія їх також буделокально– тобто, визначене лише в рамках даної процедури. Єдиний правильний зв'язок процедури з "зовнішнім миром", тобто, іншими підпрограмами й головною програмою – зазначений після іменісписок формальних параметрів. У цьому списку через кому вказуються вхідні й вихідні параметри процедури із вказівкою їх типів даних. Вхідні параметри служатьвихідними данимидля процедури, а вихідні визначаютьрезультати її обчислень, передані в головну програму або іншу підпрограму. Передвихіднимипараметрами, змінені значення яких повинні зберігатися після завершення процедури, слідуказувати ключове слово var. Причини саме такої вказівки ми обговоримо нижче.

Саме по собі написання процедури ще не викликає виконання ніяких дій. Щоб процедура спрацювала, її потрібно викликати, записавши в потрібній крапці програми ім'я процедури зісписком фактичних параметрів, які будуть підставлені на місце формальних. Усе це робиться не так складно, як звучить. Представимо, що ми розв'язали написати процедуру розв'язку будь-якого квадратного рівняння з іменемEquation. Вхідними даними цієї процедури будуть значення коефіцієнтів рівнянняa,bіc, вихідними – знайдене корінняx1іx2(якщо вони існують). Крім того, нам знадобиться "тимчасова" (а точней, локальна) зміннаd, що дозволяє процедурі зберігати обчислене значення дискримінанта:

Procedure Equation (a,b,c:real; var x1,x2:real);

Var d:real;

Begin

d:=sqr(b)-4*a*c;

if d>=0 then begin

x1:=(-b+sqrt(d))/(2*a);

x2:=(-b-sqrt(d))/(2*a);

end;

End;

Оскільки всі параметри цієї процедури – дійсні, у її заголовку нам вистачило двох списків – один для вхідних параметрів a,bіc, іншої – для вихіднихx1іx2( зверніть увагу на словоvarперед цим списком!). У випадку негативного значення дискримінанта, значенняx1іx2 залишаються невизначеними (що, загалом кажучи, не зовсім коректно!), а якщо ні, то вони обчислюються й повинні бути передані в головну програму. Викликати цю процедуру ми могли б, наприклад, так:

Var a,b,c,d,x1,x2,x3,x4:real;

. . .

Write ('Уведіть значення a,b,c:');

Read (a,b,c);

Equation (a,b,c,x1,x2);

{ спробували розв'язати рівняння ax2+bx+c=0,

значення a,b,c, увів користувач,

відповіді, якщо вони обчислювалися, будуть поміщені в x1 і x2}

Equation (1,4,-3.5,x3,x4);

{ розв'язали рівняння x2+4x-3.5=0, відповіді помістили в x3 і x4}

Equation (4,1,-3.5,x3,x4);

{ спробували розв'язати рівняння 4x2+x-3.5=0,

а відповіді помістити в x1 і x2}

Equation (1,b,0,x1,x3);

{ спробували розв'язати рівняння x2+bx=0,

а відповіді помістити в x1 і x3}

. . .

І так далі. Суть у тому, що при кожному виклику підпрограми значення фактичних параметрів підставляються на місце формальних і з ними проводяться обчислення, передбачені операторами підпрограми. Зазначені вимоги називаютьузгодженням параметріві описують у такий спосіб:формальні й фактичні параметри повинні бути погоджені між собою по кількості, типі й порядку проходження. Це означає, що кількість формальних і фактичних параметрів повинне бути однаковим, при цьому, при виклику процедури кожний фактичний параметр повинен мати той же тип і займати в списку те ж місце, що й відповідний йому формальний параметр. Зі сказаного випливає, що нашу процедуруEquationможна викликати тільки з п'ятьома параметрами (а не трьома, родину або нулем), причому всі ці параметри повинні бути речовинними. Якщо формальний параметр є вихідним (перед ним у заголовку процедури зазначене ключове словоvar), то відповідний фактичний параметр не може бути константою (адже значення константи не можна змінити). Для більше наочності опишемо дану відповідність у вигляді таблиці:

Формальний параметр у заголовку процедури

Відповідний фактичний параметр при виклику процедури

Змінна деякого типу даних без var

Змінна, константа, елемент масиву або значення вирази того ж типу даних

Змінна деякого типу даних з var

Змінна або елемент масиву того ж типу даних

Масив

Масив

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

procedure p1 (x:integer); { для x створиться локальна копія!}

begin

x:=x+1; {значення копії збільшилося на 1}

writeln ('X=',x); {і було виведено на екран}

end;

var x:integer;

begin

x:=3;

p1(x);

writeln ('X=',x);

{після виклику з передачею параметра за значенням,

x як і раніше рівно 3}

end.

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

procedure p1 (var x:integer);

{одержуємо адресу змінної, переданої в якості x}

begin

x:=x+1; {значення x збільшилося на 1}

writeln ('X=',x); {і було виведено на екран}

end;

var x:integer;

begin

x:=3;

p1(x);

writeln ('X=',x);

{після виклику з передачею параметра по посиланню,

x стало рівно 4 - воно було змінено процедурою p1}

end.

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

Перейдемо до прикладів.

Пр.Для крапки на площині із заданими координатами (x,y) знайти відстаньlвід крапки до початку координат, а також довжину окружності й площа кругу радіусомlіз центром на початку координат.

Позначимо довжину окружності як c, а площа кругу –s. Неважко помітити, що крім виділення в окрему процедуру розрахунків величинl,cіs, доцільно написати також процедуруGetдля введення речовинного значення з попереднім виводом запрошення до введення ( нам доведеться вводити, щонайменше, 2 значення –xіy), а також процедуруPutдля друку речовинного значення із зазначеною шириною, точністю й рядком коментаря (виводитися будуть шукані величиниl,cіs).

procedure Circle2 (x,y:real; var l,c,s:real);

const pi=3.1415926;

{Просто для ілюстрації; насправді є функція pi}

begin

l:=sqrt(sqr(x)+sqr(y));

c:=2*pi*l;

s:=pi*sqr(l);

end;

procedure Get (S:string; var x:real);

{S - запрошення,

x - параметр-змінна величина, що вводиться із клавіатури, }

begin

write (S,': ');

readln (x);

end;

procedure Put (S:string; x:real);

{S - коментар до виведення, x - виведена величина}

begin

writeln (S,'= ',x:8:3);

end;

var x,y,c,s,l:real;

begin

writeln;

Get ('Уведіть координату x',x);

Get ('Уведіть координату y',y);

Circle2 (x,y,l,c,s);

Put ('Видалення від початку координат',l);

Put ('Довжина окружності',c);

Put (' Площа кругу',s);

end.

Незважаючи на те, що процедура Circle2викликана в цій програмі однократно, вона може придатися при повторнім використанні коду. Вихідними даними ( параметрами-значеннями) для цієї процедури є координати крапкиxіy, вихідними даними ( параметри-змінні) – знайдені значенняl,cіs.

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

Пр.Написати процедуру, що друкує перші N членів ряду Фибоначчи.

Члени ряду Фибоначчи обчислюються по формулі:

F0= 0, F1= 1, FN = FN-1 + FN-2, N=2,3,...

Помітимо, що крім простий і гарної формули, ряд Фибоначчи чудовий ще тим, що відношення двох його сусідні членів дає в межі константу "золотого перетину", широко використовувану у всіляких розрахунках. Для обчислення й виведення на екран Nперших членів ряду Фибоначчи напишемо процедуруFiboз формальним параметромall, що визначають, скільки членів ряду потрібно знайти. У головній програмі організуємо цикл уведення значення фактичного параметраN.

procedure Fibo (all:integer);

var n,n1,n2:longint;

{n – поточний елемент ряду,

n1 – попередній, n2 – обчислений 2 кроку назад

}

i:integer;

begin

n1:=1; n2:=0;

writeln;

write (n2,' ',n1,' ');

for i:=2 to all do begin

n:=n1+n2;

write (n,' ');

n2:=n1; n1:=n; {перепривласнили для наступного кроку}

end;

end;

var n:integer;

begin

repeat

writeln ('Уведіть число членів ряду або 0 для виходу:');

read (n);

if n=0 then halt(1)

else Fibo(n);

until false;

end.