Итак, сегодня мы с вами на learnpascal.ru продолжаем изучать функции и процедуры — важнейшую часть структурного программирования. В этом уроке мы рассмотрим только процедуры и функции. И даже не будем практиковаться, оставим это для последующих уроков.
Структура программы.
Программы на языке Паскаль состоят из заголовка программы, раздела описаний и тела программы. Раздел описаний может включать следующие подразделы: меток, констант, типов, переменных, процедур и функций. Последовательность подразделов в структуре программы произвольная, но естественно, что если вводится переменная нового типа, заданного в Туре, то подраздел Туре предшествует подразделу Var. Принцип нашего языка программирования «то, что используется, должно быть описано» сохраняется и для раздела описаний.
program <имя программы>; label <метки>; const <описание констант>; type <описание типов данны>; var <описание переменных>; <процедуры и функции>; begin <основное тело программы>; end.
Структура процедуры.
До этого момента времени мы использовали из раздела описаний только описание переменных и типов. На этом занятии мы начнем изучать процедуры. Структура процедуры повторяет структуру программы. Отличия выделены «полужирным» шрифтом.
procedure <имя процедуры> (<параметры>); label <метки>; const <описание констант>; type <описание типов данных>; var <описание переменных>; <процедуры и функции>; begin <основное тело процедуры>; end;
Напишу простую программу с процедурой, складывающей два числа.
var
a, b, c: integer;
procedure sum(x, y: integer; var z: integer);
begin
z := x + y;
end;
begin
write('Введите два числа: ');
readln(a, b);
sum(a, b, c); {процедура вызывается своим именем, которое вы написали после зарезервированного слова procedure в описании}
writeln(c);
end.
Итак, что вы видите? Точнее, что вам не понятно в данной программе? Я думаю, что вы не можете понять, почему перед z стоит var, а перед x, y — нет. Но всему свое время.
Обратимся к примеру, приведенному на рисунке выше. Слева приведен фрагмент текста основной программы, справа — процедура. Как только в теле программы объявляется имя процедуры с параметрами, выполнение «главного» тела прекращается, и управление вычислительными процессами передается процедуре. После выполнения процедуры осуществляется возврат на оператор основной программы, следующий за вызовом процедуры.
Немножко теории:
В любой программе все переменные делятся на два типа: локальные и глобальные. В нашей программы переменные а, b, с — глобальные, а х, у, z — локальные. Глобальные переменные — это переменные из раздела описаний основной части программы, а локальные — из раздела описаний процедур и функций. Локальные переменные существуют только в течение времени работы процедуры, определяются (создаются) при её вызове и исчезают после завершении работы процедуры.
В программе определены переменные a, b, c. В процедуре x, y, z — её параметры, и они являются переменными процедуры. Причем между х, у и z существует большая разница.
Поясню ее очередным рисунком.
Параметры.
При описании процедуры указывается список формальных параметров. Каждый параметр является локальным по отношению к описываемой процедуре, к нему можно обращаться только в пределах данной процедуры (в нашем примере х, у, z — формальные параметры). Фактические параметры — это параметры, которые передаются процедуре при обращении к ней (а, b, с — фактические параметры). Число и тип формальных и фактических параметров должны совпадать с точностью до их следования.
Параметры-значения.
Другими словами, передача параметров по значению. Копия фактического параметра становится значением соответствующего формального параметра. Внутри процедуры можно производить любые действия с данным формальным параметром (допустимые для его типа), но эти изменения никак не отражаются на значении фактического параметра, то есть каким он был до вызова процедуры, то таким же и останется после завершения ее работы (х, у — параметры-значения).
Параметры-переменные.
Другими словами, передача параметров по ссылке. Это те формальные параметры, перед которыми стоит идентификатор var. Передается адрес фактического параметра (обязательно переменной), после этого формальный
параметр становится его синонимом. Любые операции с формальным параметром выполняются непосредственно над фактическим параметром.
Структура функции
Функция выглядит почти так же, как и процедура. Почти единственное отличие в том, что заголовок функции начинается с ключевого слова Function и кончается типом возвращаемого данной функцией значения.
function <имя функции> (<список формальных операторов>): <тип возвращаемого значения>;
Кроме того, в теле функции обязательно должен быть хотя бы один оператор присваивания, где в левой части стоит имя функции или переменная result, а в правой — ее значение.
Пример:
var a, b, c: integer; function sum(x, y: integer): integer; begin sum := x + y; end; begin readln(a, b); writeln(sum(a, b)); end.
Или так:
var a, b, c: integer; function sum(x, y: integer): integer; begin result := x + y; end; begin readln(a, b); writeln(sum(a, b)); end.
Небольшое послесловие:
Каждая процедура должна иметь одну точку входа и одну точку выхода (то есть использование goto, break, exit нежелательно), использование глобальных переменных в процедуре следует свести к минимуму, взаимодействие с процедурой должно осуществляться (по возможности) только через параметры.
Постепенно вы должны отказаться от технологии неструктурированного программирования. Сегодня мы с вами осваиваем структурную технологию разработки программ, при этом на каждом этапе текущая задача разбивается на ряд подзадач, определяя тем самым некоторое количество отдельных подпрограмм. Концепция процедур и функций — один из механизмов второго витка развития технологий программирования, а именно, структурного проектирования.
Ïðîöåäóðû è ôóíêöèè
Ïðàêòè÷åñêè âî âñåõ àëãîðèòìè÷åñêèõ ÿçûêàõ èìååòñÿ âîçìîæíîñòü ïðîãðàììèðîâàíèÿ ôóíêöèé è ïðîöåäóð — áëîêîâ îïåðàòîðîâ, îôîðìëåííûõ â âèäå ïîäïðîãðàìì. Ðàçðàáîòêà ôóíêöèé è ïðîöåäóð íåîáõîäèìà ïðè ìíîãîêðàòíîì èñïîëüçîâàíèè â ðàçíûõ ìåñòàõ ïðîãðàììû èëè â íåñêîëüêèõ ïðîãðàììàõ áëîêà îïåðàòîðîâ, âûïîëíÿþùèõ îäíîòèïíûå äåéñòâèÿ, íàïðèìåð, ðàñ÷åò çíà÷åíèé ñëîæíîé ôóíêöèè ïðè ðàçëè÷íûõ çíà÷åíèÿõ àðãóìåíòà.  Òóðáî — Ïàñêàëå èìååòñÿ òàêæå âîçìîæíîñòü ñîçäàâàòü áèáëèîòåêè (ìîäóëè), ñîñòîÿùèå èç ñïåöèàëüíûõ ïðîöåäóð è ôóíêöèé, îòëè÷íûõ îò ïîñòàâëÿåìûõ â ïàêåòå ( ìîäóëè System, Crt, Graph).
Ïðîöåäóðû (ïîäïðîãðàììû) è ôóíêöèè, îïðåäåëÿåìûå ïðîãðàììèñòîì, ïðèâîäÿòñÿ â ðàçäåëå îïèñàíèÿ îñíîâíîé ïðîãðàììû. Ïðîöåäóðû è ôóíêöèè èìåþò çàãîëîâîê, ðàçäåë îïèñàíèÿ è ðàçäåë îïåðàòîðîâ.
Çàãîëîâîê ïðîöåäóðû ñîñòîèò èç ñëóæåáíîãî ñëîâà Procedure, èìåíè ïðîöåäóðû è ñïèñêà ïàðàìåòðîâ,
íàïðèìåð:
Procedure Name_P(p1, p2,...: "òèï"; Var p3, p4,...: "òèï";...);
Çàãîëîâîê ôóíêöèè ñîñòîèò èç ñëóæåáíîãî ñëîâà Function, èìåíè ôóíêöèè è ñïèñêà ïàðàìåòðîâ, êðîìå òîãî óêàçûâàåòñÿ òèï âîçâðàùàåìîãî ôóíêöèåé çíà÷åíèÿ,
íàïðèìåð:
Function Name_F("ñïèñîê ôîðìàëüíûõ ïàðàìåòðîâ"):"òèï ðåçóëüòà-òà"; Çäåñü:
Function è Procedure — ñëóæåáíûå ñëîâà,
Name_F, Name_P — èìåíà ôóíêöèè è ïðîöåäóðû ñîîòâåòñòâåííî,
p1, p2 — èìåíà ôîðìàëüíûõ ïàðàìåòðîâ-çíà÷åíèé,
p3, p4 — èìåíà ôîðìàëüíûõ ïàðàìåòðîâ-ïåðåìåííûõ,
. . . — ìíîãîòî÷èå îçíà÷àåò âîçìîæíîñòü ïåðå÷èñëåíèÿ áîëüøåãî ÷èñëà ïàðàìåòðîâ.
 äàëüíåéøåì, åñëè íå îãîâàðèâàåòñÿ îñîáî, âñå ñêàçàííîå ê ïðîöåäóðå îòíîñèòñÿ òàêæå è ê ôóíêöèè.
Òèï âîçâðàùàåìîãî ôóíêöèåé çíà÷åíèÿ ìîæåò áûòü ïðîñòûì, ñòðîêîâûì èëè òèïîì-óêàçàòåëåì. Òèï ôîðìàëüíûõ ïàðàìåòðîâ ìîæåò áûòü ëþáûì, íî äîëæåí óêàçûâàòüñÿ òîëüêî èäåíòèôèêàòîðîì (èìåíåì òèïà). Òàêèì îáðàçîì, èìÿ òèïà ôîðìàëüíîãî ïàðàìåòðà — ìàññèâà äîëæíî áûòü çàäàíî ïðåäâàðèòåëüíî â îïåðàòîðå Type, íàïðèìåð: Type M= array[1..100]of real; Çàòåì òèï ìàññèâà ìîæåò óêàçûâàòüñÿ â çàãîëîâêå ïðîöåäóðû, íàïðèìåð: Procedure Name_P(p: M); Òèï ôîðìàëüíûõ ïàðàìåòðîâ îïèñûâàåòñÿ òîëüêî â çàãîëîâêå ïðîöåäóðû. Ñïèñîê ôîðìàëüíûõ ïàðàìåòðîâ ìîæåò îòñóòñòâîâàòü, íàïðèìåð. ïðîöåäóðà Randomize; íå èìååò ïàðàìåòðîâ.
Åñëè â ðåçóëüòàòå âûïîëíåíèÿ íåñêîëüêèõ îïåðàòîðîâ ïîëó÷àåòñÿ îäíî çíà÷åíèå ïåðåìåííîé, òî ýòè îïåðàòîðû ìîæíî âêëþ÷èòü â îïèñàíèå ôóíêöèè. Íàïðèìåð, ôóíêöèÿ Sin(x); âîçâðàùàåò çíà÷åíèå, êîòîðîå ïðèñâàèâàåòñÿ ïåðåìåííîé Y:=sin(x); (ýòà, è äðóãèå ñòàíäàðòíûå ôóíêöèè îïèñàíû â ìîäóëå System, êîòîðûé ïîäêëþ÷àåòñÿ ê ïðîãðàììå àâòîìàòè÷åñêè).
Åñëè â ðåçóëüòàòå âûïîëíåíèÿ íåñêîëüêèõ îïåðàòîðîâ ïðîèçâîäèòñÿ íåêîòîðîå äåéñòâèå èëè ðàñ÷åò íåñêîëüêèõ ïåðåìåííûõ, òî ýòè îïåðàòîðû ëó÷øå âêëþ÷èòü â îïèñàíèå ïðîöåäóðû. Íàïðèìåð, ïðîöåäóðà ClrScr; èç ìîäóëÿ CRT î÷èùàåò ýêðàí.
Âûçîâ ïðîöåäóðû îñóùåñòâëÿåòñÿ â ðàçäåëå âûïîëíåíèÿ îñíîâíîé ïðîãðàììû èëè äðóãèõ ïðîöåäóð (âëîæåííûå ïðîöåäóðû). Ïðîãðàììà (ïðîöåäóðà) âíóòðè êîòîðîé âûçûâàåòñÿ äðóãàÿ ïðîöåäóðà íàçûâàåòñÿ âíåøíåé ïî îòíîøåíèþ ê âûçûâàåìîé ïðîöåäóðå.
Ïðè âûçîâå ïðîöåäóðû âìåñòî ôîðìàëüíûõ ïàðàìåòðîâ ïîäñòàâëÿþòñÿ ôàêòè÷åñêèå ïàðàìåòðû, çíà÷åíèÿ êîòîðûõ èñïîëüçóþòñÿ â ïðîöåäóðå.
Íàïðèìåð:
Name_P(p11, p22,..., p33, p44,...); - âûçîâ ïðîöåäóðû Name_P,
Y:= Name_F("ñïèñîê ôàêòè÷åñêèõ ïàðàìåòðîâ"): - âûçîâ ôóíêöèè Name_F,
Çäåñü:
p11, p22, . . . — èìåíà èëè çíà÷åíèÿ ïåðåìåííûõ,
p33, p44, . . . — èìåíà ïåðåìåííûõ, çíà÷åíèÿ êîòîðûõ âîçâðàùàþòñÿ â ïðîãðàììó.
Y — ïåðåìåííàÿ, êîòîðîé ïðèñâàèâàåòñÿ çíà÷åíèå âîçâðàùàåìîå ôóíêöèåé.
Òèïû ñîîòâåòñòâóþùèõ ôîðìàëüíûõ è ôàêòè÷åñêèõ ïàðàìåòðîâ äîëæíû ñîâïàäàòü, à èìåíà ìîãóò ñîâïàäàòü èëè áûòü ðàçëè÷íûìè. Âìåñòî ïàðàìåòðîâ-çíà÷åíèé ìîæíî ïîäñòàâëÿòü èìåíà ïåðåìåííûõ, çíà÷åíèÿ ïåðåìåííûõ èëè âûðàæåíèÿ, âìåñòî ïàðàìåòðîâ-ïåðåìåííûõ ïîäñòàâëÿþòñÿ èìåíà ïåðåìåííûõ. Ôóíêöèÿ è ïàðàìåòðû-ïåðåìåííûå âîçâðàùàþò âî âíåøíþþ ïðîãðàììó çíà÷åíèÿ, ïîëó÷åííûå ïîñëå îêîí÷àíèÿ ðàáîòû ôóíêöèè èëè ïðîöåäóðû. Èçìåíåíèÿ ïàðàìåòðîâ-çíà÷åíèé â ïðîöåäóðå íîñèò ëîêàëüíûé õàðàêòåð, âî âíåøíåé ïðîãðàììå ñîîòâåòñòâóþùèå ôàêòè÷åñêèå ïàðàìåòðû íå èçìåíÿþòñÿ. Åñëè íå òðåáóåòñÿ ïåðåäàâàòü âî âíåøíþþ ïðîãðàììó íîâûå çíà÷åíèÿ, òî ñëåäóåò èñïîëüçîâàòü ïàðàìåòðû-çíà÷åíèÿ, à íå ïàðàìåòðû-ïåðåìåííûå.
 ïðîöåäóðå ìîæíî èñïîëüçîâàòü ëîêàëüíûå ìåòêè, êîíñòàíòû è ïåðåìåííûå, îïèñàâ èõ â ðàçäåëå îïèñàíèÿ ïðîöåäóðû. Ëîêàëüíûå èìåíà íå äîëæíû ñîâïàäàòü ñ èìåíàìè ôîðìàëüíûõ ïàðàìåòðîâ, à èõ çíà÷åíèÿ íå ïåðåäàþòñÿ âî âíåøíþþ ïðîãðàììó. Ìåòêè, êîíñòàíòû è ïåðåìåííûå, îïèñàííûå âî âíåøíåé ïðîãðàììå ðàíüøå, ÷åì ñàìà ïðîöåäóðà, íàçûâàþòñÿ ãëîáàëüíûìè ïî îòíîøåíèþ ê âûçûâàåìîé ïðîöåäóðå. Åñëè ëîêàëüíûå è ãëîáàëüíûå èìåíà ñîâïàäàþò, òî â ïðîöåäóðå èñïîëüçóþòñÿ ëîêàëüíûå çíà÷åíèÿ, à âî âíåøíåé ïðîãðàììå — ãëîáàëüíûå çíà÷åíèÿ, ò. å. ëîêàëüíûå è ãëîáàëüíûå èäåíòèôèêàòîðû íåçàâèñèìû. Åñëè èìÿ ãëîáàëüíîé ïåðåìåííîé óíèêàëüíî (â ïðîöåäóðå íå îïèñûâàåòñÿ ïåðåìåííàÿ ñ òàêèì æå èìåíåì) è åå çíà÷åíèå â ïðîöåäóðå èçìåíÿåòñÿ, òî îíî èçìåíÿåòñÿ è âî âíåøíåé ïðîãðàììå. Âûçûâàÿ â ïðîãðàììå ïðîöåäóðó ïðîãðàììèñò èñïîëüçóåò åå èìÿ è ïàðàìåòðû íå àíàëèçèðóÿ, à ÷àñòî è íå çíàÿ ñîäåðæèìîãî ïðîöåäóðû. Ïîýòîìó â öåëÿõ óíèâåðñàëüíîñòè ïðîöåäóð ñëåäóåò âñå çíà÷åíèÿ â ïðîöåäóðó ïåðåäàâàòü ÷åðåç ñïèñîê ïàðàìåòðîâ, à ïåðåìåííûå âíóòðè ïðîöåäóðû îïèñûâàòü, ò. å. äåëàòü èõ ëîêàëüíûìè.
Ïðèâåäåì ïðèìåð ïðîöåäóðû âûâîäà íà ýêðàí âèçèòíîé êàðòî÷êè ïðîãðàììèñòà.
Program NP_1;
Var
Dat, Fam: string; { Fam: ãëîáàëüíàÿ ïåðåìåííàÿ }
Procedure VIZ(D_R :string); { D_R - ôîðìàëüíûé ïàðàìåòð }
Var
S_t: string;{ S_t: ëîêàëüíàÿ ïåðåìåííàÿ }
Begin
Writeln('| --------------------------------------------- |');
Writeln('| Ðàçðàáîò÷èê ïðîãðàììû:', Fam:14,' |');
Writeln('| |');
Writeln('| ã. Àíæåðî-Ñóäæåíñê ', D_R:14,' |');
Writeln('| Òåëåôîí: 2-99-76 |');
Writeln('| ----------------------------------------------|');
Write(' Êîììåíòàðèé: ');
Readln(S_t)
end;
Begin
Fam:='È.È.Èâàíîâ';
Dat:='06.12.95'; {Dat - ôàêòè÷åñêèé ïàðàìåòð}
VIZ(Dat); { âûçîâ ïðîöåäóðû }
Readln;
END.
Åñëè ïðîöåäóðà îïèñàíà â äðóãîì ôàéëå ñ èìåíåì, íàïðèìåð, F_PR. pas, òî åå ìîæíî ïîäêëþ÷èòü ê ïðîãðàììå, óêàçàâ â ðàçäåëå îïèñàíèÿ äèðåêòèâó: {$I F_PR. pas}
Ïðèâåäåì ïðèìåð èñïîëüçîâàíèÿ ñòàíäàðòíûõ ïðîöåäóð ìîäóëÿ DOS äëÿ âûâîäà òåêóùåé äàòû è âðåìåíè:
uses DOS; { ïîäêëþ÷åíèå ìîäóëÿ DOS }
Procedure Date_Time;
var y, m, d, d_w:word; h, min, sec, hund: word;{ëîêàëüíûå ïàðàìåòðû }
begin
GetDate(y,m,d,d_w); {âûçîâ ïðîöåäóðû DOS, âîçâðàùàþùåé ïàðàìåòðû äàòû }
GetTime(h,min,sec,hund); { ïðîöåäóðà, âîçâðàùàþùàÿ ïàðàìåòðû âðåìåíè }
writeln('ñåãîäíÿ: ' );
writeln('_':10, d, ' ÷èñëî');
writeln('_':10, m, ' ìåñÿö');
writeln('_':10, y, ' ãîä' );
writeln('äåíü íåäåëè: ', d_w ); { d_w= 0 - âîñêðåñåíüå, è ò. ä. }
writeln('Âðåìÿ: ' );
writeln('_':6, h, ' ÷àñîâ' );
writeln('_':6, min, ' ìèíóò' );
writeln('_':6, sec, ' ñåêóíä' ); readln
end;
Begin
Date_Time
end.
 ïðàêòè÷åñêèõ çàäà÷àõ ÷àñòî ïèøóòñÿ ïðîöåäóðû, âîçâðàùàþùèå çíà÷åíèÿ ýëåìåíòîâ ìàññèâîâ. Ïðèâåäåì ïðèìåð ïðîöåäóðû ðàñ÷åòà «N» çíà÷åíèé ôóíêöèè, íàïðèìåð, Y= 4*Sin(x)+7*Cos(x); â çàäàííîì äèàïàçîíå x1
type r_1000= array[1. . 1000] of real; { çàäàåòñÿ òèï r_1000 }
var Z: r_1000; x1, x2: real; n: word;
Procedure Mas_Y(var Y:r_1000; x1,x2:real; n:word); {Y — ïàðàìåòð-ïåðåìåí-íàÿ}
var i: word; x, dx: real; { ëîêàëüíûå ïàðàìåòðû }
begin
If (n>1000) or (n1 è íå äîëæíà ïðåâûøàòü 1000′);
Readln;
Halt
end;
i:=0;
x:=x1;
dx:=(x2-x1)/(n-1); { dx — øàã èçìåíåíèÿ àðãóìåíòà }
If dxx1)’);
Readln(x1, x2);
Writeln(‘Ââåäèòå çíà÷åíèå 1
Çäåñü òèï ôîðìàëüíîãî ïàðàìåòðà «Y» çàäàåòñÿ â ðàçäåëå îïèñàíèÿ òèïîâ âíåøíåé ïðîãðàììû è ñîâïàäàåò ñ òèïîì ôàêòè÷åñêîãî ïàðàìåòðà «Z», çíà÷åíèÿ ýëåìåíòîâ êîòîðîãî âîçâðàùàþòñÿ âî âíåøíþþ ïðîãðàììó.
Îïåðàòîð Halt ïðåðûâàåò âûïîëíåíèå âñåé ïðîãðàììû, äàæå åñëè îí èñïîëüçóåòñÿ âíóòðè ïðîöåäóðû. Ïðèìåíåíèå îïåðàòîðà Exit âíóòðè ïðîöåäóðû âûçûâàåò ïðåðûâàíèå ïðîöåäóðû, íî íå âíåøíåé ïðîãðàììû.
Ïðèâåäåì ïðèìåð ïðîöåäóðû âûâîäà ìàññèâà ÷èñåë â ôàéë:
Type M_30õ30_r= array[1..30, 1..30] of real; { çàäàåòñÿ òèï M_30õ30_r }
var x: M_30õ30_r;
i, j, n, m: byte;
{------------------------------------------------------------------------}
Procedure Wr_M(a: M_30õ30_r; name_f: string; n, m: byte);
Var
i, j: byte; { a - ìàññèâ NxM, n
Äëÿ ïðàâèëüíîãî ñ÷èòûâàíèÿ äàííûõ, çàïèñàííûõ â ôàéë áåñôîðìàòíûì âûâîäîì íåîáõîäèìà çàïèñü ïðîáåëà äëÿ ðàçäåëåíèÿ ÷èñåë.
Ïðèâåäåì ïðèìåð ôóíêöèè äëÿ ðàñ÷åòà âûñîòû òðåóãîëüíèêà ïî çàäàííûì çíà÷åíèÿì åãî ñòîðîí.
Program TR;
Var a, b, c, ha, hb, hc: real;
{----------------------------------------------------------------------------}
Function H_TR(a, b, c: real): real; { a, b, c - Ñòîðîíû òðåóãîëüíèêà }
Var p, s: real;
Begin
If (a0 ?');
readln;
Halt
end;
If (a>(b+c)) or (b>(a+c)) or (c>(a+b)) Then
begin
Writeln('a
 ïðîãðàììå òðèæäû âûçûâàåòñÿ ôóíêöèÿ ðàñ÷åòà âûñîòû òðåóãîëüíèêà äëÿ ðàçëè÷íûõ êîìáèíàöèé ôàêòè÷åñêèõ ïàðàìåòðîâ, ÷òî ïîçâîëÿåò âû÷èñëèòü âñå âûñîòû òðåóãîëüíèêà.
Ïðèâåäåì ïðèìåð èñïîëüçîâàíèÿ ôóíêöèè äëÿ ðàñ÷åòà ñóììû ÷ëåíîâ ñòåïåííîãî ðÿäà, ïðåäñòàâëÿþùåãî òðèãîíîìåòðè÷åñêóþ ôóíêöèþ Y= Sin(x).
PROGRAM fun_sin;
var y, y1, x1: real;
{-------------------------------------------------------------------------}
Function Sin_r( x: real): real;
Var a, k, y: real; i: longint;
begin
if abs(x) > 2*Pi Then x:= 2*pi*Frac(x/(2*Pi)); {ó÷åò ïåðèîäè÷íîñòè }
if abs(x) > 2*Pi Then x:= x - 2*pi*Int(x/(2*Pi)); { ôóíêöèè }
if abs(x) > Pi Then x:= Pi - ABS(x); { ó÷åò àñèììåòðèè ôóíêöèè }
i:= 0; a:= x; y:= a;
while abs(a)>0.0000001 do
begin
i:=i+1;
k:=-x*x/(2*i*(2*i+1));
a:= a*k;
y:= y + a
end;
Sin_r:= y; { ïðèñâîåíèå ôóíêöèè åå çíà÷åíèÿ }
end;
{-------------------------------------------------------------------------}
Begin
write('Ââåäèòå çíà÷åíèå àðãóìåíòà: x1= ');
Readln(x1);
Y:= Sin_r(x1); { âûçîâ ôóíêöèè, ðàçðàáîòàííîé ïðîãðàììèñòîì }
Y1:= Sin(x1); { âûçîâ ñòàíäàðòíîé ôóíêöèè }
writeln('çíà÷åíèå àðãóìåíòà: x1= ', x1);
writeln('ðàñ÷åòíîå çíà÷åíèå ôóíêöèè: Sin_r(x1)= ', y :-11:8);
writeln('êîíòðîëüíûé ðåçóëüòàò: Sin(x1) = ', y1:-11:8);
writeln('Íàæìèòå Enter');
readln;
end.

 îïèñàíèè ôóíêöèè îáÿçàòåëåí îïåðàòîð ïðèñâîåíèÿ ôóíêöèè åå çíà÷åíèÿ. Èçìåíåíèå âåëè÷èíû ïàðàìåòðà-çíà÷åíèÿ "x" â òåëå ôóíêöèè íå îòðàæàåòñÿ íà åãî çíà÷åíèè âî âíåøíåé ïðîãðàììå. Ôóíêöèÿ âîçâðàùàåò çíà÷åíèå, êîòîðîå âî âíåøíåé ïðîãðàììå ïðèñâàèâàåòñÿ ïåðåìåííîé "y". Ñîäåðæàíèå
Ó÷åáíèê ïî ÿçûêó Pascal
Ëàáîðàòîðíûå ðàáîòû ïî ïðîãðàììèðîâàíèþ
Ñïðàâî÷íèê
Процедуры и функции в Паскале. Рекурсия
Часто в задаче требуется повторить определенную последовательность операторов в разных частях программы. Для того, чтобы описывать эту последовательность один раз, а применять многократно, в языках программирования применяются подпрограммы. Подпрограмма — автономная часть программы, выполняющая определенный алгоритм и допускающая обращение к ней из различных частей общей программы. Использование подпрограмм позволяет реализовать один из самых современных методов программирования — структурное программирование.
В языке Паскаль существует два вида подпрограмм: процедура (PROCEDURE ) и функция ( FUNCTION ). Процедуры и функции в Паскале объявляются в разделе описания за разделом переменных. В данном уроке приведены примеры и задачи использования процедуры и функций, а также использование рекурсии в языке Паскаль. Параметры, записываемые в обращении к подпрограммам, называются фактическими; параметры, указанные в описании подпрограмм — формальными. Фактические параметры должны соответствовать формальным по количеству, порядку следования и типу. Параметры, объявленные в основной (главной) программе, действуют в любой подпрограмме и называются глобальными. Параметры, объявленные в подпрограмме, действуют только в этой подпрограмме и называются локальными.
Процедуры
Процедуры используются в случаях, когда в подпрограмме необходимо получить несколько результатов. В языке Паскаль существует два вида процедур: процедуры с параметрами и без параметров. Обращение к процедуре осуществляется по имени процедуры, за которым могут быть указаны фактические параметры. Все формальные параметры являются локальными для данной процедуры и глобальными для каждой процедуры в ней. При вызове процедуры устанавливаетcя взаимно однозначное соответствие между фактическими и формальными параметрами, затем управление передается процедуре. После выполнения процедуры управление передается следующему, после вызова процедуры, оператору вызывающей программы.
Пример 1. Процедура без параметров, которая печатает строку из 60 звездочек.
procedure pr;
var i : integer ;
begin
for i :=1 to 60 do write (‘ * ‘); writeln;
end.
Пример 2. Процедура c параметрами. Даны 3 различных массива целых чисел (размер каждого не превышает 15). В каждом массиве найти сумму элементов и среднеарифметическое значение.
program proc;
var i , n , sum: integer;
sr : real;
procedure work (r:integer; var s:integer; var s1:real); {процедура work}
var mas : array [1..15] of integer ; { объявление массива мas}
j : integer;
begin
s:=0;
for j:=1 to r do begin {ввод элементов массива mas}
write(‘ Vvedite element — ‘, j,’: ‘) ;
read (mas[j]);
s:=s+mas [j];
end;
s1:=s/r;
end;
begin { главная программа}
for i:=1 to 3 do begin
write (‘Vvedite razmer ‘,i, ‘ masiva: ‘);
readln(n);
work (n, sum, sr); {вызов процедуры work}
writeln (‘Summa elementov = ‘,sum);
writeln (‘Srednearifmeticheskoe = ‘,sr:4:1);
end;
readln;
end.
Результат работы программы: В программе трижды вызывается процедура work, в которой формальные переменные r, s, s1 заменяются фактическими n, sum, sr. Процедура выполняет ввод элементов массива, вычисляет сумму и среднее значение. Переменные s и s1 возвращаются в главную программу, поэтому перед их описанием ставится служебное слово var. Локальные параметры mas, j действуют только в процедуре. Глобальные — i, n, sum, sr доступны во всей программе.
Функции в Паскале
Набор встроенных функций в языке Паскаль достаточно широк (ABS, SQR, TRUNC и т.д.). Если в программу включается новая, нестандартная функция, то ее необходимо описать в тексте программы, после чего можно обращаться к ней из программы. Обращение к функции осуществляется в правой части оператора присваивания, с указанием имени функции и фактических параметров. Функция может иметь собственные локальные константы, типы, переменные, процедуры и функции. Описание функций в Паскале аналогично описанию процедур. Отличительные особенности функций: — результат выполнения — одно значение, которое присваивается имени функции и передается в основную программу;
— имя функции может входить в выражение как операнд.
Пример 3. Написать подпрограмму-функцию степени аx, где a, х – любые числа. Воспользуемся формулой: аx = ex ln a
program p2;
var f, b, s, t, c, d : real; { глобальные параметры}
function stp (a, x : real) : real;
var y : real; { локальные параметры}
begin
y := exp (x * ln ( a)) ;
stp:= y;{присвоение имени функции результата вычислений подпр-мы}
end; { описание функции закончено }
begin {начало основной программы }
d:= stp (2.4, 5); {вычисление степеней разных чисел и переменных }
writeln (d, stp (5,3.5));
read (f, b, s, t); c := stp (f, s)+stp (b, t);
writeln (c);
end.
Рекурсия
Процедуры и функции в Паскале могут вызывать сами себя, т.е. обладать свойством рекурсивности. Рекурсивная функция обязательно должна содержать в себе условие окончания рекурсивности, чтобы не вызвать зацикливания программы. При каждом рекурсивном вызове создается новое множество локальных переменных. То есть переменные, расположенные вне вызываемой функции, не изменяются.
Пример 4. Составить рекурсивную функцию, вычисляющую факториал числа n следующим образом: n! = 1 , если n= 1 и n!= ( n -1 )! · n , если n > 1
function f ( n : integer): integer;
begin
if n = 1 then f := 1 else f := n * f ( n -1 ); { функция f вызывает саму себя}
end;
Источник: http://life-prog.ru/
Цель урока
образовательная
- сформировать у учащихся единую систему понятий,
связанных с понятиями процедуры и функции; - научить применять подпрограммы в решении задач
на Паскале, а также научить понимать кокой вид
подпрограммы необходим при решении определенной
задачи; - показать основные приемы использования
подпрограмм;
воспитательная
- воспитать аккуратность, внимание,
организованность; - культура вычислительных навыков;
развивающая
- развить логическое мышление,
алгоритмической культуры учащихся; - развить знания и умения составлять и отлаживать
подпрограммы на языке Паскаль.
Учащиеся должны:
- знать правила записи процедур без параметров и
с параметрами; - знать правила записи функций;
- уметь применять процедуры и функции при решении
простых задач.
Ход урока
I. Орг. момент
II. Вступление. Актуальность
Выдать задание на листочках (Приложение 1).
Найти повторы.
Иногда в разных местах программы
приходится выполнять практически одни и те же
последовательности действий с разными исходными
данными. Такие последовательности действий
можно оформить в виде так называемых подпрограмм
(от англ, subroutine) – сгруппировать операторы
в блок, к которому можно обратиться по имени,
причем неоднократно.
Подпрограммы сокращают текст
программы, существенно уменьшают время их
исполнения, облегчают жизнь программистам,
которые могут создавать программы модульно, т. е.
собирая сложную программу из законченных
кусочков более простых составляющих. Это
позволяет группе программистов создавать
большие программы, а группе школьников
разрабатывать и реализовывать какие-либо
глобальные проекты
Подпрограммы делятся на процедуры и функции.
Встроенные (стандартные) процедуры и
функции являются частью языка и могут
вызываться по имени без предварительного
описания. Например, abs, sqrt, ln, sin…- функции
(возвращают результат), readln, write… – процедуры (не
возвращают результат). Их наличие существенно
облегчает разработку прикладных программ.
Однако в большинстве случаев некоторые специфичные
для данной программы действия не находят
прямых аналогов в библиотеках Turbo Pascal, и тогда
программисту приходится разрабатывать свои нестандартные
процедуры и функции.
III. Объяснение нового материала
Процедуры пользователя пишутся самим
программистом в соответствии с синтаксисом
языка в разделе описания подпрограмм.
Структура процедуры повторяет
структуру программы, это «программа в
миниатюре» — она также представлена
заголовком и телом.
Заголовок состоит из
зарезервированного слова procedure, идентификатора (имени)
процедуры.
VAR … // раздел описания переменных главной
программы
procedure ИмяПроцедуры;
var …
begin
…
end;
begin
//тело главной программы
end.
Вызов процедуры для последующего
выполнения записывается в теле главной
программы.
Пример 1. Программа вычисления площади и
периметра.
Открыть в Паскале файл (Приложение
2). Оформим повторяющуюся часть программы
в виде процедуры (программа внутри главной
программы).
{***Вычисление****}
procedure tx;
begin
writeln;
writeln(‘Вычисление: ‘);
write(‘Введите стороны a, b: ‘);
end;
{*******************}
Вызов в нужном месте:
tx;
При вызове процедуры работа главной
программы приостанавливается и начинает
выполняться вызванная процедура. Когда
процедура выполнит свою задачу, программа продолжится
с оператора, следующего за оператором вызова
процедуры.
Т.е. мы “научили” ПК новой команде tx.
Ею можно пользоваться только в этой программе и,
причем, много раз. (Приложение
3)
Достоинства подпрограмм:
- Программы, написанные с участием подпрограмм, легче
тестировать и отлаживать, у них более четкая логическая
структура. - Самостоятельный характер подпрограмм
позволяет поручать их составление различным
программистам. Так осуществляется разделение
работы по программированию и, тем самым,
ускоряется ее завершение; - Использование подпрограмм позволяет экономить
память. Память для хранения переменных,
использующихся в подпрограмме, выделяется
только на время ее работы и высвобождается, как
только ее выполнение заканчивается.
Пример 2. Пользователь вводит две
стороны трех прямоугольников. Вывести их
площади.
Можно решить задачу так:
for i:=1 to 3 do
begin
writeln(‘Введите a и b:’);
readln(a,b);
writeln(‘Площадь=’,a*b);
end;
Хорошим стилем программирования
считается использование процедур. Необходима
процедура, которая будет вычислять площадь
прямоугольника. Вот как схематично будет
выглядеть главная программа:
текст
readln (a,b);
вычисление
текст
readln (a,b);
вычисление
текст
readln (a,b);
вычисление
Процедура текста уже есть (см пример1).
Создадим вторую процедуру, которая вычисляет
площадь. Но для того чтобы вычислить S, надо знать
2 стороны, поэтому процедуре надо показать какие
стороны она должна перемножать.
procedure pl (c,d: integer);
var S:integer;
begin
S:=c*d;
writeln(‘площадь прямоугольника со
сторонами ’,c, ‘ ‘ ,d, ‘=‘,S);
end;
Параметр – это переменная, которой
присваивается некоторое значение. Существуют формальные
параметры, определенные в заголовке
подпрограммы, и фактические параметры –
выражения, задающие конкретные значения при
обращении к подпрограмме.
Процедура выполнится, если вызвать ее
по имени и указать фактические параметры, отделенные
друг от друга запятыми и заключенных в круглые
скобки:
pl(4,5);
pl(a,b);
Фактические параметры должны
совпадать по типу и количеству с формальными.
Итак, главная программа:
for i:=1 to 3 do
begin
tx;
readln(a,b);
pl(a,b);
end;
Замечание. При решении
этой задачи необходимо проверять введенные
пользователем числа (они не должны быть
отрицательными, иначе работа программы
прервется).
Составим процедуру проверки:
procedure error (f,g:integer);
begin
if (f<0) or (g<0) then begin
writeln(‘стороны прямоугольника не могут
быть отрицательными’);
halt; //прерывание программы
end;
end;
Итоговая программа – Приложение 4
Итак формат процедуры:
Procedure <имя> (формальные параметры);
Const …;
Type …;
Var …;
Begin
<операторы>;
end;
Пример 3. Составить программу
обмена местами двух чисел с=5 и d=7.
program obmenDan;
uses wincrt;
var c,d:integer;
{обмен}
procedure obmen ( a,b:integer);
var m:integer;
begin
m:=a; a:=b; b:=m;
writeln(a,b);
end;
begin
writeln (‘Введите 2 числа: ‘);
readln(c,d);
obmen(c,d);
writeln(c,’ ‘,d);
end.
После запуска программы видно, что
поменялись местами формальные параметры (в
процедуре), а фактические (которые используются в
лавной программе) – не поменялись. Рассмотрим
рисунок, на котором приведена часть оперативной
памяти:
1) при вызове процедуры obmen с двумя
параметрами 5 и 7, в переменные a и b помещаются
тоже числа 5 и 7 соответственно:
2) далее в процедуре осуществляется
перестановка значений ячеек памяти a и b:
3) но в переменных c и d данные не
поменялись, т.к. они находятся в других ячейках
памяти.
Для того чтобы переменные c и d, a и b ссылались
на одни и те же ячейки памяти (если изменятся
значения a и b, то изменятся значения и c, d)
необходимо при описании формальных параметров,
перед нужными переменными добавить слово VAR:
procedure obmen (var a,b:integer);
Измените программу obmenDan:
obmen (1,4);
ошибка из-за
var. Числа – константы, которые нельзя изменять в
процедуре.
Пример 4. Найти площадь круга с
использованием процедуры, которая производит
только вычисление, но не отображает результат на
экране.
procedure circle (r:real);
var S:real;
begin
S:=pi*r*r;
end;
Процедура должна возвращать
результат:
procedure circle (r:real; var S:real);
begin
S:=pi*r*r;
end;
begin
readln(a, e);
writeln(e);
end.
Замечание: Переменная в
процедуре S используется для возвращения
результатов работы процедуры в основную
программу. При ее изменении, изменяется и
фактический параметр в вызывающей программе, т.е.
переменная e.
Чаще для этого в Паскале вместо
процедур используют функции (подпрограммы,
которые что-то возвращают).
Функция аналогична процедуре, но имеются
два отличия.
- Функция передает в программу результат своей
работы – единственное значение, носителем
которого является имя своей функции. - Имя функции может входить в выражение как
операнд. Функция возвращает результат в точку
своего вызова.
Например, sqr(x) – возведет в квадрат значение х и
возвратит в точку вызова вычисленное значение
квадрата числа х: y:=sqr(x);
Функция, определенная пользователем,
состоит из заголовка и тела функции. Тело функции
по структуре аналогично программе. Описание
меток, констант, типов и т.д. действительны только
в пределах данной процедуры.
Формат:
Function <имя> (формальные параметры) : <тип
результата>;
Const …;
Type …;
Var …;
Begin
<операторы>;
end;
В разделе операторов должен
находиться хотя бы один оператор, присваивающий
имени функции значение. В точку вызова
возвращается результат последнего присваивания.
Пример 5. Переделаем задачу о
площади круга.
function circle (r:real): real;
begin
circle:=pi*r*r;
end;
вызов:
a:=circle(5); (ОБЯЗАТЕЛЬНО присваиваем)
или
e:=circle(a);
writeln(e);
Пример 6. Найти 1!+2!+…+n!
Используем функцию нахождения
факториала, т.к подаем на вход и получаем
результат.
function fact (a:integer): integer;
var i: integer;
begin
fact:=1;
for i:=1 to a do
fact:=fact*I;
end;
В строке fact:=fact*I;
компилятор найдет ошибку, т.к fact должна
вызываться с параметрами. Поэтому обячно вводят
дополнительную переменную, в которую помещают
результат. А потом в переменную fact присваивают
этот результат:
program factorial;
uses wincrt;
var sum,n,j: integer;
function fact (a: integer): integer;
var i,d: integer;
begin
d:=1;
for i:=1 to a do
d:=d*i;
fact:=d;
end;
begin
sum:=0;
readln(n);
for j:=1 to n do
sum:=sum+fact(j);
writeln(sum);
end.
IV. Итог урока
В данное время процесс
программирования превращается в промышленное
изготовление программ на основе технологий
программирования. Большинство специалистов
придерживаются точки зрения, что метод
нисходящего проектирования программ наиболее
удобен для решения сложных проблем. Cначала
задача определяется в общих чертах, затем
происходит постепенное уточнение ее структуры.
На очередном шаге каждая подзадача, в свою
очередь, разбивается на ряд других. Решение
отдельного фрагмента сложной задачи
представляет собой самостоятельный программный
блок – подпрограмму.
V. Домашнее задание
Решить задачи (письменно):
- Составить процедуру, которая во введенной
строке заменяет все буквы a на *. - Даны два предложения. Найти общее количество
букв “н” в них. (Определить функцию для расчета
количества букв “н” в предложении.)










