
14.Мова програмування Паскаль. Концепція підпрограми. Процедури і функції у мові Паскаль. Поняття рекурсії. Правила локалізації. Бібліотеки підпрограм, призначення, включення до основної програми, використання. Поняття структурованого програмування.
Pascal — алгоритмічна мова програмування універсального призначення. Існують діалекти мови з підтримкою об'єктно-орієнтованого програмування. В 1990 році було затверджено стандарт ISO 7185:1990, «Pascal»[1], та ISO 10206:1990 «Extended Pascal».
підпрограма — це іменована частина програми, котра описує деякі обчислення і може бути викликана з будь якого місця програми, де синтаксисом мови це не заборонено.
Для багаторазового виконання деякого програмного коду достатньо записати його один раз у підпрограмі, і надалі, в разі потреби, вказувати лише її ім'я. Концепція програмування, що ґрунтується на використанні підпрограм як стандартних блоків для створення нових програм, отримала назву повторне використання коду. Мови, в яких реалізовано механізми використання підпрограм, називаються процедурно-орієнтовтими. Мова Pascal належить до таких мов. Конструювання програм з невеликих «будівельних блоків» сприяє їх більшій ясності та гнучкості, що приводить до підвищення їх ефективності, якості та надійності. Одна з найпомітніших переваг такого підходу полягає у простоті механізму внесення змін і виправлень у процедурно-орієнтовані програми. В мові Pascal існує два різновиди підпрограм: процедури та функції. ^ Процедури користувача Із прикладами процедур і функцій ми вже зустрічалися - це стандартні процедури введення-виведення read, write, математичні функції, наприклад sin(x),trunc(x) тощо. Вони називаються стандартними тому, що є невід'ємною частиною системи Pascal. Наявність великої бібліотеки таких програмних засобів суттєво полегшує розроблення програм. Але у більшості випадків специфічні для певної програми дії не мають прямих відповідників у бібліотеках Pascal І для їх виконання програміст має створити власні процедури або функції, тобто процедури або функції користувача. І процедури, і функції можна поділити на класи підпрограм із параметрами та підпрограм без параметрів. Параметрами називаються змінні, за допомогою яких відбувається передача даних до підпрограми, що викликається, із програмного блоку, що здійснює виклик. Отже, підпрограми без параметрів можуть бути незалежними від зовнішніх даних, а підпрограми з параметрами обов'язково їх використовують. ^ Процедури без параметрів Оголошення процедури або функції записується в розділі оголошень програми і має таку саму структуру, як і вся програма, за винятком крапки наприкінці, замість якої використовується крапка з комою. Синтаксис оголошення процедури є таким: procedure <ім'я>(<оголошення параметрів>); <оголошення імен> begin <операторна частина процедури>; end; Тут procedure, begin, end — зарезервовані слова; < ім'я > — унікальний в межах програми ідентифікатор процедури, за яким вона викликається; <оголошення параметрів> — оголошення змінних, яким надаються значення під час виклику процедури; <оголошення імен> — розділ оголошень ідентифікаторів, що будуть використовуватись лише в межах процедури; <операторна частина процедури> - оператори, які виконуються під час виклику процедури, їх називають такожтілом процедури. Рядок програми, що містить ключове слово procedure, ім'я процедури та її параметри, називається заголовком процедури. Процедури можуть не мати параметрів, тоді вони називаються процедурами без параметрів, а синтаксис їх оголошення є таким: procedure <ім'я>; <оголошення імен>; begin <операторна частина процедури>; end; Виклик процедури здійснюється за її іменем, яке використовується в основній програмі або в інших процедурах як окремий оператор. Отже, формат операторавиклику процедури без параметрів такий: <ім'я процедури>; ^ Процедури з параметрами В ідеальній ситуації загальновідомим є лише заголовок підпрограми, а її внутрішня будова залишається прихованою від розробників інших підпрограм, програм або модулів. Для модифікації значення змінних, що використовуються всередині підпрограм застосовують спеціальні змінні, параметри процедури, що оголошуються в її заголовку. Синтаксис заголовка процедури з параметрами: procedure <ім'я> (<ім'я:тип>;... <var ім'я:тип>;...); Парою <ім'я:тип> позначається ідентифікатор параметра та ідентифікатор його типу. Зазначимо, що параметри одного типу можна об'єднувати в один список: <ім'я 1, ім'я2:тип>. ^ Локалізація імен Кожний ідентифікатор у програмі характеризується областю дії імені або областю видимості. Область видимості ідентифікатора - це область програми, в якій можна посилатися на даний ідентифікатор. У мові Pascal припускається довільна послідовність і кількість розділів, в яких іменуються ті чи інші об'єкти. Такі розділи можуть належати до різних програмних блоків: процедур, функцій або самих програм. Область дії іменування поширюється від точки, де ідентифікатор було оголошено, до кінця блоку, в якому це оголошення відбулося. Усі ідентифікатори, оголошені всередині процедури або функції, є локалізованими в ній, тобто вони є невидимими зовні підпрограми. Такі ідентифікатори називаються локальними. Мета локалізації змінних полягає в тому, щоб надати доступ лише до тих даних, які потрібні для формулювання задач, що їх розв'язують процедури або функції, і зробити в такий спосіб постановки обчислювальних задач незалежними від методів їх розв'язань. Крім власних локальних імен всередині підпрограми видимими є й деякі ідентифікатори верхнього рівня, тобто ідентифікатори, що їх було оголошено у «зовнішніх» програмних блоках. Ці ідентифікатори називаються глобальними. Зазначимо, що з глобальних імен видимими є лише ті, оголошення яких розташовані до оголошення даної підпрограми. Ім'я, локалізоване у підпрограмі, може збігатися з будь-яким глобальним іменем, оскільки цим іменам зіставляються різні ділянки оперативної пам'яті. У такому випадку локальне ім'я перекриває глобальне та робить його недоступним у підпрограмі. Імена локальних змінних можуть також збігатися з іменами локальних змінних інших підпрограм, такі змінні є абсолютно незалежними, хоч і мають однакові імена. ^ Різновиди параметрів Область оперативної пам'яті, що її використовує програма, поділяється на сегмент коду, сегмент даних та сегмент стеку. В сегменті коду (64 Кбайт) зберігаються команди програми, в сегменті даних (64 Кбайт) — значення глобальних змінних, а в сегменті стеку — значення локальних змінних і параметрів підпрограм. Параметри, що їх імена вказані в заголовку підпрограми, називаються формальними, оскільки під час компіляції їх оголошення вони не прив'язуються до жодного реального об'єкта. Натомість значення, що замінюють формальні параметри під час виклику підпрограм, називаються фактичними параметрами абоаргументами. Під час виклику підпрограми між її фактичними та формальними параметрами встановлюється однозначна відповідність щодо кількості параметрів, їх типів та порядку згадування. Формальні параметри поділяються на параметри-значення, параметри-змінні, параметри-константи та нетипізовані параметри-змінні. Якщо параметр оголошено як параметр - значения, то під час виклику підпрограми обчислюється значення відповідного аргументу і копія отриманого результату передається підпрограмі. Зміна параметрів-значень усередині підпрограми не впливає на значення змінних, що могли бути вказані як аргументи підпрограми, оскільки змінюються їх копії. Якщо параметр оголошено як параметр-змінну, то до підпрограми передається покажчик на параметр, тобто адреса певної змінної в сегменті даних оперативної пам'яті. Тому підпрограма виконує дії над значеннями параметрів-змінних, а не над їх копіями, і модифікація параметра-змінної приведе до модифікації змінної, що була вказана як аргумент в операторі виклику підпрограми. Для параметра-константи копія значення відповідного аргументу під час звернення до підпрограми не створюється. Значення такого параметра не можна змінювати у тілі підпрограми. Параметра-константи дозволяють зекономити оперативну пам'ять та підвищити швидкість виконання програми. У заголовку підпрограми перед іменем параметра-константи треба записати зарезервоване слово const. Якщо формальний параметр є нетипізованим параметром-змінною, то відповідний йому фактичний параметр може бути покажчиком на змінну довільного тилу, тобто адресою сегмента даних оперативної пам'яті, де зберігаються значення, тип яких не відомий. У заголовку підпрограми перед іменем параметра-змінної слід записати слово var, але не треба вказувати тип параметра. ^ Процес виклику підпрограми. Програмний стек Під час виклику підпрограми їй передається керування. По завершенні роботи вона повертає керування програмі, що її викликала, у ту точку, із якої виклик було здійснено. Перша команда підпрограми називається точкою входу, а адреса такої команди - адресою точки входу. Оператор, що продовжує виконання програми по завершенні роботи підпрограми, називається точкою повернення із підпрограми. Коли здійснюється виклик підпрограми, точка повернення з неї запам'ятовується і зберігається до завершення роботи цієї підпрограми. Для збереження точки повернення використовується ділянка оперативної пам'яті. Крім того, під час виклику підпрограми певні ділянки пам'яті зіставляються з її параметрами та локальними змінними. Сукупність усіх цих ділянок пам'яті називається локальною пам'яттю підпрограми. Якщо підпрограма є функцією, то до її локальної пам'яті додається ділянка для збереження значення, яке функція повертає. Ця ділянка ставиться у відповідність до імені функції.
Процедури та функції
У мові Паскаль, як і в більшості мов програмування, передбачені засоби, що дозволяють оформлювати допоміжний алгоритм як підпрограму. Це буває необхідно тоді, коли який-небудь підалгоритм неодноразово повторюється в програмі або ж є можливість використовувати деякі фрагменти вже розроблених раніше алгоритмів. Крім того, підпрограми застосовуються для розбиття великих програм на окремі смислові частини відповідно до модульного принципу в програмуванні.
Для використання підалгоритму в якості підпрограми йому необхідно привласнити ім'я і описати алгоритм за правилами мови Паскаль. Надалі, при необхідності викликати його в програмі, роблять виклик підпрограми вказуючи в потрібному місці імені відповідного підалгоритму зі списком вхідних і вихідних даних. Такий запис призведе до виконання вхідних в підпрограму операторів, що будуть працювати із зазначеними даними. Після виконання підпрограми програма продовжує роботу з тієї команди, яка безпосередньо слідує за викликом підпрограми.
У мові Паскаль є два види підпрограм - процедури та функції.
Процедури і функції розміщують в розділі описів програми. Для обміну інформацією між процедурами і функціями і іншими блоками програми існує механізм вхідних і вихідних параметрів. Вхідними параметрами називають величини, які передаються із блоку викликів до підпрограми (вихідні дані для підпрограми), а вихідними – ті, що передаються з підпрограми до блоку викликів (результат роботи підпрограми).
Одна і та ж підпрограма може викликатися неодноразово, виконуючи одні і ті ж дії з різними наборами вхідних даних. Параметри, що використовуються під час запису тексту підпрограми в розділ описів, називають формальними, а ті, що використовуються під час її виклику -фактичними.
Опис і виклик процедур і функцій
Структура опису процедур і функцій деякою мірою схожа на структуру Паскаль-програми: у них також є заголовок, розділ описів і виконувана частина. Розділ описів містить ті ж підрозділи, що і розділ описів програми: описи констант, типів, міток, процедур, функцій, змінних. Виконувана частина містить, власне, оператори процедур.
Формат опису процедури має вигляд:
procedure ім'я процедури (формальні параметри);
розділ опису процедур
begin
виконувана частина процедури
end;
Формат опису функції:
function ім'я функції (формальні параметри): тип результату;
розділ опису функції
begin
виконувана частина функції
end;
Формальні параметри в заголовках процедур і функцій записують у вигляді:
var ім'я параметру: ім'я типу
і відокремлюються один від одного крапкою з комою. Ключове слово var може бути відсутнім (про це далі). Якщо параметри однотипні, то їх імена можна перераховувати через кому, вказуючи загальне для них ім'я типу. Під час опису параметрів можна використовувати лише стандартні імена типів, або імена типів, визначені за допомогою команди type. Список формальних параметрів може бути відсутнім.
Виклик процедури здійснюється оператором, що має наступний формат:
ім'я процедури (список фактичних параметрів);
Список фактичних параметрів - це їх перерахування через кому. Під час виклику фактичні параметри ніби підставляються замість формальних, що стоять на тих же місцях у заголовку. Таким чином відбувається передача вхідних параметрів, потім виконуються оператори виконуваної частини процедури, після чого відбувається повернення в блок викликів. Передача вихідних параметрів відбувається безпосередньо під час роботи виконуваної частини.
Виклик функції в Турбо Паскаль може відбуватися в аналогічний спосіб, окрім того є можливість здійснити виклик всередині якогось виразу. Зокрема ім'я функції може стояти в правій частині оператора присвоєння, в розділі умов оператора if і т.д.
До повернення в блок викликів необхідно додати наступну команду в виконувану частину функції, для того, щоб передати в блок викликів вихідне значення функції
ім'я функції: = результат;
Під час виклику процедур і функцій необхідно дотримуватися наступних правил.
кількість фактичних параметрів має збігатися з кількістю формальних;
відповідні фактичні та формальні параметри повинні збігатися по порядку
проходження і по типу.
Зауважимо, що імена формальних і фактичних параметрів можуть збігатися. Це не призводить до проблем, так як відповідні їм змінні все одно будуть різні із-за того, що зберігаються в різних областях пам'яті. Крім того, всі формальні параметри є тимчасовими змінними - вони створюються в момент виклику підпрограми і знищуються в момент виходу з неї.
Розглянемо використання процедури на прикладі програми пошуку максимуму з двох цілих чисел.
var x,y,m,n: integer;
procedure MaxNumber(a,b: integer; var max: integer);
begin
if a>b then max:=a else max:=b;
end;
begin
write('Введіть x,y ');
readln(x,y);
MaxNumber(x,y,m);
MaxNumber(2,x+y,n);
writeln('m=',m,'n=',n);
end.
Аналогічну задачу, але уже з використанням функцій, можна вирішити так:
var x,y,m,n: integer;
function MaxNumber(a,b: integer): integer;
var max: integer;
begin
if a>b then max:=a else max:=b;
MaxNumber := max;
end;
begin
write('Введіть x,y ');
readln(x,y);
m := MaxNumber(x,y);
n := MaxNumber(2,x+y);
writeln('m=',m,'n=',n);
end.