русс | укр

Мови програмуванняВідео уроки php mysqlПаскальСіАсемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование


Linux Unix Алгоритмічні мови Архітектура мікроконтролерів Введення в розробку розподілених інформаційних систем Дискретна математика Інформаційне обслуговування користувачів Інформація та моделювання в управлінні виробництвом Комп'ютерна графіка Лекції


Процедури


Дата додавання: 2014-11-28; переглядів: 785.


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

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.

 


<== попередня лекція | наступна лекція ==>
Підпрограми | Функції


Онлайн система числення Калькулятор онлайн звичайний Науковий калькулятор онлайн