Смекни!
smekni.com

Паскаль типи дійсних оператори розгалуження функції та їх виклики процедури під задачі (стр. 3 из 4)

d2:=dd(x1, y1, 1, 2);

d3:=dd(x2, y2, 1, 2);

if d1<d2 then m:=d1 else m:=d2;

if d3<m then m:=d3;

writeln('найменша відстань: ', m)

end.

При виконанні цієї програми після читання значень змінних виконується виклик функції dd: значення змінних x1, y1, x2, y2 присвоюються відповідним параметрам a1, b1, a2, b2 як звичайним змінним і потім обчислюється значення dd. Воно і є значенням виразу dd(x1, y1, x2, y2), що присвоюється змінній d1.

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

Отже, ми бачимо, що мова Паскаль дозволяє не тільки користуватися викликами "стандартних" функцій, наприклад, odd або sin, але й створювати свої власні.

Функція має такий загальний вигляд:

functionім'я(означення параметрів) : ім'я типу;

означення

begin

послідовністьоператорів

end;

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

Параметрів у функції може не бути, тоді й дужки відсутні, а виклик такої функції є просто її ім'ям.

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

1) функція записується серед означень програми;

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

Виклик функції є виразом того типу, який указано в її заголовку. І він, як усякий вираз, може бути частиною складнішого виразу. Наприклад, за необхідності ми могли б написати d1:=sqr(dd(x1, y1, 1, 2)+1).

Повернемося до прикладу. Нескладно написати функцію обчислення меншого з двох значень:

function min(x1, x2 : real):real;

begin

if x1<x2 then min:=x1

else min:=x2

end;

і помістити її слідом за функцією dd у програмі minimdis. З її використанням обчислення мінімального зі значень змінних d1, d2, d3 можна в тілі програми задати так:

m:=min(d1, d2); m:=min(m, d3)

або навіть так:

m:=min(min(d1, d2), d3)

При обчисленні останнього виразу спочатку виконується "внутрішній" виклик min(d1, d2). Значення, обчислене при його виконанні, стає аргументом у "зовнішньому" виклику.

Задачі

3.13.* Написати функцію even, тобто "парне", що задає обчислення ознаки парності цілого.

3.14. Написати функцію обчислення за дійсним параметром x:

а) його знака (sign(x)=-1, 0 або 1 відповідно при x<0, x=0, x>0);

б)* ceil(x) – найменшого цілого, що не менше, ніж значення параметра (для від'ємних значень параметра можливі два варіанти означення).

3.15. Написати програму обчислення периметра й площі трикутника за координатами його вершин.

3.16. Написати тригонометричні функції з дійсним параметром, значення якого вимірюються в градусах.

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

4. Процедури, підпрограми та параметри

Розглянемо задачу: довільні значення трьох змінних a, b, c переставити за необхідності так, щоб вони були упорядковані за неспаданням, тобто щоб мали місце нерівності a£ b£ c. Алгоритм розв'язання цієї задачі простий:

якщо a>b, то обміняти значення змінних a і b;

{гарантовано, що a£ b}

якщо b>c, то обміняти значення змінних b і c;

{гарантовано, що b£ c і a£ c; але нерівність a£ b не гарантована, тому:}

якщо a>b, то обміняти значення змінних a і b.

Обмін значень двох змінних, наприклад, a і b, задається трьома операторами з допоміжною змінною: t:=a; a:=b; b:=t. Мовою Паскаль алгоритм записується так:

program sort3(input, output);

var a, b, c, t : integer;

begin

writeln('задайте три цілих'); readln(a, b, c);

if a>b thenbegin t:=a; a:=b; b:=t end;

if b>c thenbegin t:=b; b:=c; c:=t end;

if a>b thenbegin t:=a; a:=b; b:=t end;

writeln('упорядкування: ', a, ' ', b, ' ', c)

end.

Проте три майже однакові складені оператори, що задають ті самі дії, тільки з різними змінними – це нудно. Аналогічно функціям,

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

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

Процедура має загальний вигляд

procedure ім'я(означенняпараметрів);

означення імен

begin

послідовністьоператорів

end;

Процедура, як і функція, є означенням імені і записується серед означень програми.

На відміну від функції, в її заголовку немає імені типу для значень, породжуваних у результаті виклику, тому що ніякі значення не породжуються. За цією ж причиною в тілі процедури не може бути операторів присвоювання з її ім'ям у лівій частині. Виклик процедури складається з імені й аргументів у дужках і записується як окремий оператор, наприклад, readln(x, y).

Отже, напишемо інший варіант програми упорядкування трьох значень:

program sort31(input, output);

var a, b, c : integer;

procedure swap(xx, yy : integer);

var t : integer;

begin t:=xx; xx:=yy; yy:=t end;

begin

writeln('задайте три цілих:'); readln(a, b, c);

if a>b then swap(a, b);

if b>c then swap(b, c);

if a>b then swap(a, b);

writeln('упорядкування: ', a, ' ', b, ' ', c)

end.

КРАСИВО, АЛЕ НЕПРАВИЛЬНО!

Справа в тім, що при виконанні виклику, наприклад, swap(a, b), змінні xx і yy одержать значення змінних a і b, потім ці значення поміняються місцями, виконання виклику закінчиться, а в змінних a і b залишаться ті ж самі значення, що були перед викликом. Наприклад, якщо змінним a, b, c присвоїти "з зовнішнього світу" значення відповідно 3, 1, 2, то буде надруковано упорядкування: 3 1 2. Слушність цього напису дуже сумнівна.

Отже, при виконанні виклику процедури (чи функції) спочатку параметри одержують значення аргументів, а потім їх зміни ніяк не відбиваються на аргументах (рис.3.3). Тому параметри, що дотепер розглядалися, називаються параметрами-значеннями.

Мова Паскаль допускає в заголовках процедур і функцій означати параметри іншого виду. Вони називаються параметрами-змінними і означаються зі словом var попереду. Так, процедура swap набуває вигляду:

procedure swap(var xx, yy : integer);

var t : integer;

begin

t:=xx;

xx:=yy;

yy:=t

end;

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

Момент виконання програми a b c
перед першим викликом 3 2 1
після першого виклику 2 3 1
після другого виклику 2 1 3
після третього виклику 1 2 3

Якщо в програмі sort31 означити параметри процедури як параметри-змінні, то за виконання виклику swap(a, b) імені xx зіставляється та ж сама ділянка пам'яті, що й змінній a, а імені yy – та ж, що b. У результаті обмін місцями значень xx і yy є обміном a і b. Що й було потрібно. Таким чином, якщо в змінні a, b, c програми було прочитано значення 3, 2, 1 відповідно, то результати виконання викликів процедури swap можна подати станами пам'яті програми, як на рис.3.5.

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

Секція параметрів-значень – це список імен, за яким після двокрапки записано ім'я типу, наприклад, a1, a2 : real. Секція параметрів-змінних починається словом var, за яким записано список імен параметрів таім'я типу, наприклад,

var xx, yy : integer.

Секції розділяються ";". За необхідності ми могли б написати, наприклад,

procedure qq(x, y : integer; var z, t : integer).

Як ми вже говорили, у викликах підпрограм вказуються аргументи – вирази, однотипні з параметрами. Але є суттєва відмінність між аргументами, що можуть відповідати параметрам-значенням і параметрам-змінним.

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

Аргументом для параметра-змінної може бути тільки ім'я змінної того ж типу, що й параметр.

У літературі часто параметри підпрограм називаються формальнимипараметрами, а аргументи у викликах – фактичними.

Задачі

3.18.* Як Ви гадаєте, процедури readln і writeln мають параметри-значення або параметри-змінні?

3.19.* Як відомо, будь-які дві різні точки площини задають єдину пряму, що проходить через них. Рівняння прямої ax+by+c=0 називається нормалізованим, якщо (b=1) або (b=0 і a=1). Пряма може бути задана не єдиним рівнянням, але її нормалізоване рівняння єдине.