Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Модульність, розподіл пам'яті, підпрограми.doc
Скачиваний:
2
Добавлен:
25.11.2018
Размер:
764.42 Кб
Скачать

Різновиди підпрограм

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

Всі стандартні засоби знаходяться у стандартних бібліотеках, які, зазвичай, повинні бути підключені в тексті програми. Наприклад, у програмах на мові Рascal відповідні бібліотеки слід підключити у розділі Uses; у мові С для цього служать директиви препроцесора include.

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

Реалізація підпрограм може різнитися в залежності від мови програмування і залежить, в основному, від можливостей повернення ними значень. Хоча синтаксис деяких мов програмування не залежить від того, повертаються значення підпрограмами чи не повертаються. Наприклад, Maple не звертає на це увагу; у мові С вважається, що значення повертається підпрограмою зав­жди, тільки інколи воно може мати так званий пустий тип (void); в Pascal розрізняють підпрограми-функції, що по­вертають значення, та підпрограми-процедури, що можуть не повертати значень.

Досить часто результатом роботи під­програми має бути не одне, а декілька різних значень. В такому випадку ви­користовуються різноманітні спеціалізовані методи повернення комплексу значень. Найпростіший із них - використання параметрів-змінних, найефе­ктивніший - утворення блоку результатів і повернення адреси цього блоку, як результату роботи програми. В Maple використовується саме останній метод, тоді як Pascal і C — використовують і перший, і другий методи.

Розглянемо більш детально реалізацію підпрограм у мовах програмування.

Реалізація підпрограм у Pascal. Як зазначалося вище, у мові Pascal підпрограми можуть представлятися у формі процедур і функцій, які відрізняються між собою структурою та способом виклику.

Процедури – це підпрограми, які можуть повертати будь-яку кількість результатів, у тому числі і жодного. Зазвичай, використовуються для опису логічно завершених етапів вирішення задач (сортування масивів, розв’язання систем рівнянь, тощо).

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

procedure ім'я [( опис формальних параметрів)];

тіло процедури.

Опис формальних параметрів у заголовку процедури являє собою їх перелік з вказанням для кожного такого параметра імені типу того значення, яке представляється цим формальним параметром. РБНФ відповідного поняття:

опис формальних параметрів ::= ім'я {, ім'я}:тип {; ім'я {, ім'я}:тип}

Наприклад,

Procedure Proc (a,b:word; result:real);

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

Слід зазначити, що типи формальних параметрів не завжди можуть конструюватися (задаватися) в описах параметрів. У деяких версіях Pascal вони обов'язково повинні позначатися ідентифікатором. Наприклад, наступний заголовок процедури може бути неприпустимим:

Procedure Prim (а:1..3).

Виклик або активація процедури здійснюється окремим оператором, який представляє собою завершену одиницю дій мови програмування.

Для прикладу, відозмінемо процедуру MaxP, представивши її вхідні дані а і b у вигляді параметрів. Для цього введемо формальні параметри (ідентифікатори, які не використовуються в тілі процедури для інших цілей), наприклад r1 та r2, і запишемо тіло процедури з їх використанням:

procedure Max_Рroc(r1,r2:real);

begin

if r1>r2 then s:=r1

else s:=r2

end;

Після цього програму Max_3 можно записати так:

program Max_P;

var x,y,u,v:real;

s:real;

procedure Max_Рroc(r1,r2:real);

begin

if r1>r2 then s:=r1

else s:=r2

end;

begin

ReadLn(x,y);

Max_Proc(x+y,x*y);

u:=s;

Max_Proc(0.5,u);

v:=s;

WrіteLn(' u=',u,' v=',v)

ReadLn

end.

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

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

Формат оголошення функцій:

FUNCTION ім'я [( опис формальних параметрів)] : тип результату;

тіло функції.

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

Function Step(x:real; n:word) : real;

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

Як і у випадку з процедурами, типи формальних параметрів, а також типи значень, що повертаються функцією, не можуть конструюватися в описах параметрів, а обов'язково повинні позначатися ідентифікатором.

Виклик функції завжди є операндом виразу.

Для прикладу, враховуючи, що розглянута вище підпрограма Maxroc як результат повертає одне значення (значення більшої із двох її вхідних величин), оформимо її як функцію:

function Max_Func(r1,r2:real):real;

begin

if r1>r2 then Max_Func:=r1

else Max_Func:=r2

end;

Тоді програму Max_P можно записати інакше:

program Max_F;

var x,y,u,v:real;

function Max_Func(r1,r2:real):real;

begin

if r1>r2 then Max_Func:=r1

else Max_Func:=r2

end;

begin

ReadLn(x,y);

u:=Max_Func(x+y,x*y);

v:=Max_Func(0.5,u);

WrіteLn(' u=',u,' v=',v)

ReadLn

end.

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

Узагальнимо відмінності між процедурами і функціями Pascal:

  1. У заголовках функцій, окрім іншого ключового слова, явно вказується тип результату, що повертається.

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

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

  4. У тілі функції повинен бути оператор, в якому імені функції присвоюється значення. Саме це значення і повертається даною функцією.

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

Між процедурами і функціями у Pascal багато спільного (як з синтаксичної, так і з семантичної точки зору). Тому у випадках, коли з підпрограми повинен повертатися один результат, їх можна використовувати з однаковим успіхом. В інших випадках використання процедур або функцій визначається потребами задачі.

Приклади використання процедур і функцій:

program Demo_1;

uses Crt;

var x, y : byte;

procedure FonColor (Fon, Color : byte);

begin

TextBackGround (Fon);

TextColor (Color);

end;

begin

ClrScr;

FonColor (1,2);

Writeln (Зелений рядок на синьому фоні');

FonColor (2,14);

Writeln ('Жовтий рядок на зеленому фоні');

end.

program Demo_2;

var k, y : real;

function Step (x:real; n : word) : real;

var m:real;

i : word;

begin

m:=1;

for i:=1 to n do m:=m*x;

Step:=m;

end;

begin

k := 4.53;

y := Step (k, 5) / 7 + Step (k + 2, 4)

;

end.

Реалізація підпрограм у C. На відміну від інших мов програмування високого рівня в мові С немає поділу підпрограм на процедури і функції. Вся програма на С будується тільки із функцій. Функції забезпечують зручний спосіб окремого оформлення деяких обчислень з можливістю їх подальшого використання по імені (без турботи про те, як виконана реалізація).

Функції у мові С можна:

  • визначати (описувати дії, що виконуються функцією),

  • оголошувати (задавати форми звертання до функції),

  • викликати.

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

[тип результату] ім'я функції([список формальних параметрів])

{

тіло функції

}

Типи формальних параметрів можуть описуватися в заголовку функції або після нього, але до тіла функції:

float fun (float p1, float p2)

{ return p1>=p2 ? p1 : p2;

}

float fun (p1, p2)

float p1; float p2;

{ return p1>=p2 ? p1 : p2;

}

Допускається використання функцій, які не мають параметрів, але дужки у цьому випадку все рівно ставляться.

Функція у С++ може мати змінне число формальних параметрів. Тоді їх список у заголовку функції закінчується комою із трикрапкою (, ...). Наприклад,

float prim (int a, b, float s, … );

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

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

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

fact (int n) //обчислення факторіала числа

{ if (n>0) return n*fact(n-1);

else return 1;

}

Функція може не повертати жодного значення. Дія таких функцій може полягати, наприклад, у зміні значень деяких змінних, виведенні на друк деяких текстів тощо. Тоді тип результату функції задається ключовим словом void, що вказує на відсутність значення, яке повертається функцією. Наприклад,

void print( )

{ cout<< “Печать строки” << endl;

}

У цьому випадку керування із функції повертається:

  1. по досягненні кінця тіла функції ( символа «}» );

  2. при виконанні пустого оператора return.

Функція повинна бути визначена (описані дії) або оголошена (заданий прототип) до першого її використання;

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

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

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

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

Виклик функції може здійснюватися окремим оператором виклику або бути операндом виразу.

Приклад. Знаходження факторіалу введеного числа.

Варіант 1

Варіант 2

#include <stdio.h>

#include <conio.h>

int fact(int n)

{ if (n>0) return n*fact(n-1);

else return 1;

}

main( )

{ int x;

printf("x:");

scanf(“%d”, x);

printf("\n%d! =%d",x,fact(x));

getch( );

}

#include <stdio.h>

#include <conio.h>

int fact(int);

main( )

{ int x;

printf("x:");

scanf(“%d”, x);

printf("\n%d! =%d",x,fact(x));

getch ( );

}

int fact(int n)

{ if (n>0) return n*fact(n-1);

else return 1;

}