функції користувача

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

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

Загальна форма запису заголовка функції

FUNCTION ім'я (список параметрів: тип): тип;

FUNCTION ім'я. тип;

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

Мал. 33. Синтаксична діаграма заголовка функції

Отже, заголовок функції відрізняється від заголовка процедури не тільки зміною слова PROCEDURE на FUNCTION, але і видаленням зі списку параметрів параметра-результату з присвоєнням його типу імені функції:

PROCEDURE <имя процедуры> (Аргументи;
VAR параметр-результат: тип);

FUNCTION <имя функции> (Аргументи): тип;

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

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

Відомо, що Паскаль має набір стандартних функцій. Однак цей набір обмежений. Користувач може за бажанням розширити список функцій, створивши свої функції - функції користувача. Так, наприклад, в Паскалі є SQR (X) = X 2. а ось функції F (X) = X n. де n належить множині цілих чисел Z, немає. Використовуючи певний раніше поняття функції, можна створити для цього універсальну функцію, яка давала б ступеня довільного дійсного числа з будь-яким цілим показником.

Визначимо речову функцію POWER, яка повинна мати два параметра-аргументу - для показника і для заснування ступеня:

function POWER (FACTOR: real; EXP: integer): real;

var COUNT: integer; TFACTOR: real;

if EXP = 0 then POWER: = 1

for COUNT: = 2 to ABS (EXP) do

if EXP <0 then POWER := 1/TFACTOR

if N <0 then writeln ('Нет факториала')

else writeln ( 'Факторіал', N, 'дорівнює', FACTORIAL (N))

Ми бачимо, що характерною особливістю побудованої функції є наявність в її тілі оператора присвоювання:

FACTORIAL: = VALUE * FACTORIAL (VALUE - 1),

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

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

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

Розглянемо рекурсивний процес на прикладі обчислення факторіала для N = 3. Отримаємо наступні кроки:

1. N = 3, де N <> 0. Тоді FACTORIAL: = 3 * FACTORIAL (2);

2. N = 2, де N <> 0. Тоді FACTORIAL: = 2 * FACTORIAL (1);

3. N = 1, де N <> 0. Тоді FACTORIAL: = 1 * FACTORIAL (0);

4. N = 0, отже, FACTORIAL: = 1,

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

У вираз 1 * FACTORIAL (0) замість FACTORIAL (0) підставляється його значення 1, обчислюється твір 1 * 1, яке стає значенням FACTORIAL (1). У вираз 2 * FACTORIAL (1) замість FACTORIAL (1) підставляється значення 1, обчислюється 2 * 1 і стає значенням FACTORIAL (2). У вираз 3 * FACTORIAL (2) замість FACTORIAL (2) підставляється значення 2, обчислюється 3 * 2 і стає значенням змінної FACTORIAL, яка повертає в основну програму значення 3 !.

Весь цей двоетапний рекурсивний процес реалізується в пам'яті ЕОМ за допомогою організації в ній стека рекурсії. Справа в тому, що для зберігання значень змінної N (а значить і змінної VALUE) відводиться не один осередок, а стек з ім'ям N. У цей стек послідовно заносяться значення 3, 2, 1, 0, причому значення 0 є ознакою кінця заповнення стека . Потім починає працювати цикл з тілом FACTORIAL: = FACTORIAL * N, де значення N вибираються послідовно з стека в порядку 1, 2, 3. Вихідним же значенням змінної FACTORIAL є одиниця, яка є значенням 0 !.

Робота стека представлена ​​в таблиці:

Заповнення стека (поглиблення)

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

Ця функція явно носить рекурсивний характер, виходячи з її визначення:

X n = 1, якщо n = 0;

X n = X n-1 * X, якщо n> 1.

Нижче слід рекурсивна функція обчислення значення ступеня:

function POWER (FACTOR: real; EXPONENT: integer): REAL;

if EXPONENT <0

then POWER: = 1 / POWER (FACTOR, abs (EXPONENT))

if EXPONENT> 0

then POWER: = FACTOR * POWER (FACTOR, EXPONENT - 1)

Зауваження. Крім рекурсивних функцій, в мові Паскаль за тим же принципом можна визначати і рекурсивні процедури. Детально про них буде сказано в наступних розділах, а поки покажемо, як рекурсивна функція може бути перероблена в рекурсивную процедуру на прикладі обчислення факторіала:

procedure FACTORIAL (VALUE: integer; var F: integer);

iF VALUE = 0 then F: = 1

else begin FACTORIAL (VALUE - 1, F);

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

1. Які види підпрограм використовуються в мові Паскаль?

2. На які два типи прийнято поділяти процедури?

4. В якому розділі програми поміщаються процедури користувача?

5. Яка роль параметрів процедури?

6. Чим відрізняються параметри-змінні від параметрів-значень?

7. Чим відрізняються фактичні параметри від формальних параметрів?

8. Де оголошуються локальні і глобальні змінні?

9. Яким чином в програмі викликається процедура?

10. У чому відмінність заголовка процедури від заголовка функції?

11. Який змінної обов'язково присвоюється значення в тілі функції?

12. Як в програмі викликається функція?

13. Що є відмінною рисою рекурсивної функції?

14. Яким чином в рекурсивної функції здійснюється вихід з рекурсії?

15. Завдання якого типу краще реалізовувати за допомогою рекурсивних функцій?