Слайд 2Процедуры и функции
Разновидностью программ являются подпрограммы.
Подпрограмма – как любая программа
может иметь все полагающиеся программе атрибуты: имя, разделы описания меток
(label), констант (const), типов (type), переменных (var) и может содержать вложенные функции и процедуры.
В языке Pascal имеется два вида подпрограмм:
процедуры и функции.
Упоминание в тексте программы имени процедуры (или функции) является ее вызовом.
Слайд 3Объявление и описание подпрограммы.
Подпрограммы объявляются и описываются в начале программы,
до ключевого слова begin, означающего начало тела программы.
Объявление функции
function
<имя_функции> [(<список_параметров>)]:<тип_результата>;
Обьявление процедуры
Procedure <имя процедуры> [(< список_параметров >)]
В отличие от констант и переменных, объявление подпрограммы может быть оторвано от ее описания. В этом случае после объявления нужно указать ключевое слово forward:
function <имя_функции> [(<параметры>)]:<тип_результата>; forward;
Слайд 4Описание подпрограммы
Если описание подпрограммы имеется, оно идет после ее объявления
по следующей схеме (единой для процедур и функций):
[ uses ;][
label <список_меток>;][ const <имя_константы> = <значение_константы>;][ type <имя_типа> = <определение_типа>;][ var <имя_переменной> : <тип_переменной>;] [ procedure <имя_процедуры> <описание_процедуры>][ function <имя_функции> <описание_функции>;] begin {начало тела подпрограммы} <операторы>end; (* конец тела подпрограммы *)
Слайд 5Если объявление подпрограммы было оторвано от ее описания, то описание
начинается дополнительной строкой с указанием только имени подпрограммы:
function ; или
procedure
<имя_подпрограммы>;
Описания двух различных подпрограмм не могут пересекаться. Но внутри любой подпрограммы могут быть описаны другие процедуры или функции - вложенные.
Слайд 6Пример подпрограммы-процедуры:
Program pr1;
procedure err(c:byte; s:string);
var zz: byte;
begin
if
c = 0 then
writeln(s)
else
writeln('Ошибка!');
end;
var
n:byte;
begin
readln(n);
err(n,’krona’);
end.
Слайд 7Пример подпрограммы-функции
Function Power(a,b:real):real;
Begin
If a>0 then
Power:=exp(b*ln(a))
Else if a
then
Power:=1
Else
Power:=0
End;
Слайд 8Список параметров
В заголовке подпрограммы (в ее объявлении) указывается список формальных
параметров - переменных, которые принимают значения, передаваемые в подпрограмму извне
во время ее вызова.
Procedure <имя> [(<список_формальных_параметров>)];
Function <имя> [(<список_формальных_параметров>)]:<тип>;
Список параметров может и вовсе отсутствовать:
procedure proc1;
function func1: boolean;
В этом случае подпрограмма не получает никаких переменных "извне".
Слайд 9Отсутствие параметров и, как следствие, передаваемых извне значений не означает,
что при каждом вызове подпрограмма будет выполнять абсолютно одинаковые действия.
Поскольку глобальные переменные видны изнутри любой подпрограммы, их значения могут неявно изменять внутреннее состояние подпрограмм.
Если же параметры имеются, то каждый из них описывается по следующему шаблону:
[<способ_подстановки>]<имя_параметра>:<тип>;
Если способ подстановки и тип нескольких параметров совпадают, описание этих параметров можно объединить:
[<способ_подстановки>]<имя1>,...,<имяN>: <тип>;
Имена локальных переменных, описываемые в разделе var внутреннем для подпрограммы, не могут совпадать с именами параметров этой же подпрограммы.
Слайд 10Пример:
function func2(a,b:byte; var x,y,z:real; const c:char);
В заголовке подпрограммы можно
указывать только простые (не составные) типы данных. Нельзя записать:
procedure proc2(a:
array[1..100]of char);
Чтобы обойти это ограничение, составной тип данных нужно описать в разделе type, а при объявлении подпрограммы воспользоваться именем этого типа:
type arr = array[1..100] of char;
procedure proc2(a: arr);
function func2(var x: string): arr;
Слайд 11Возвращаемые значения
Основное различие между функциями и процедурами состоит в
количестве возвращаемых ими значений.
Любая функция, завершив свою работу, должна вернуть
основной программе (или другой вызвавшей ее подпрограмме) ровно одно значение, причем его тип нужно явным образом указать уже при объявлении функции.
Для возвращения результата применяется специальная "переменная", имеющая имя, совпадающее с именем самой функции. Оператор присваивания значения этой "переменной" обязательно должен встречаться в теле функции хотя бы один раз.
Слайд 12Например:
function min(a,b: integer): integer;
begin
if a>b then
min:=
b
else
min:= a
end;
В отличие от функций, процедуры явно не
возвращают никаких значений.
Слайд 13Вызов подпрограмм
Любая подпрограмма может быть вызвана не только из основного
тела программы, но и из любой другой подпрограммы, объявленной позже
нее.
При вызове в подпрограмму передаются фактические параметры или аргументы (в круглых скобках после имени подпрограммы, разделенные запятыми):
<имя_подпрограммы>(<список_аргументов>) Аргументами могут быть переменные, константы и выражения, включающие в себя вызовы функций.
Слайд 14
Количество и типы передаваемых в подпрограмму аргументов должны соответствовать количеству
и типам ее параметров.
Тип каждого аргумента должен учитывать способ
подстановки, указанный для соответствующего параметра. Если у подпрограммы вообще нет объявленных параметров, то при вызове список передаваемых аргументов будет отсутствовать вместе с обрамляющими его скобками.
Слайд 15Вызов функции не может быть самостоятельным оператором, потому что возвращаемое
значение нужно куда-то записывать. Но может быть частью выражения. Например:
c:=
min(a,a*2);if min(z, min(x,y))= 0 then...;
Вызов процедуры является отдельным оператором в программе, так как процедура не возвращает значения. Например:
err(res,'Привет!');
После того как вызванная подпрограмма завершит свою работу, управление передается оператору, следующему за оператором, вызвавшим эту подпрограмму.
Слайд 16Области действия имен. Разграничение контекстов
Глобальные объекты - это типы данных,
константы и переменные, объявленные в начале программы до объявления любых
подпрограмм. Эти объекты будут видны во всей программе, в том числе и во всех ее подпрограммах. Глобальные объекты существуют на протяжении всего времени работы программы.
Локальные объекты объявляются внутри какой-нибудь подпрограммы и "видны" только этой подпрограмме и тем подпрограммам, которые были объявлены как внутренние для нее. Локальные объекты не существуют, пока не вызвана подпрограмма, в которой они объявлены, а также после завершения ее работы.
Слайд 17ЛОКАЛЬНЫЕ И ГЛОБАЛЬНЫЕ ВЕЛИЧИНЫ
Телом процедуры является блок, в котором могут
описываться
имена. Следовательно, возможно вложение блоков , а значит, сразу
же возникает
вопрос об области действия (или области видимости
- scope) имен.
1 . Все описанные в некотором блоке имена имеют силу только
для этого блока и вложенных в него блоков. Для такого блока имена
являются локальными. Локальных имен вне блока не существует.
2 . Все используемые в некотором блоке имена, описанные в
блоке более высокого уровня иерархии, являются для блока более
низкого уровня глобальными.
3 . Если в некотором блоке локальная и глобальная величины
имеют одно и то же имя, внутри блока с этим именем всегда связывается локальная величина. Значение имеющей то же имя глобальной величины на время обработки блока «замораживается».
Слайд 18program prog;
var a:byte;
procedure pr1 (p:byte);
var b:byte; {первый уровень
вложенности}
function f (pp:byte);
var c:byte; {второй уровень вложенности}
begin
{здесь "видны" переменные a, b, c, p, pp}
end;
begin {здесь "видны" переменные a, b, p}
end;
var g:byte;
procedure pr2;
var d:byte; {первый уровень вложенности}
begin {здесь видны переменные a, d, g}
end;
begin {тело программы; здесь "видны" переменные a, g}
end;
Слайд 19Побочный эффект
Поскольку глобальные переменные видны в контекстах всех блоков, то
их значение может быть изменено изнутри любой подпрограммы. Этот эффект
называется побочным, а его использование очень нежелательно, потому что может стать источником непонятных ошибок в программе.
Чтобы избежать побочного эффекта, необходимо строго следить за тем, чтобы подпрограммы изменяли только свои локальные переменные (в том числе и параметры-переменные).
Слайд 20Совпадение имен
Cовпадение глобальных и локальных имен не вызывает коллизий, поскольку
к каждому локальному имени неявно приписано имя той подпрограммы, в
которой оно объявлено. Тем не менее, рекомендуется этого избегать.
Если имеются глобальная и локальная переменные с одинаковым именем, то изнутри подпрограммы к глобальной переменной можно обратиться, приписав к ней спереди имя программы:
<имя_программы>.<имя_глобальной переменной> Например
a:= prog.a; (локальной переменной здесь присваивается значение глобальной):
Слайд 21Процедурный тип данных
Имена подпрограмм могут выступать в роли аргументов для
других подпрограмм.
Описание
В разделе type процедурный тип данных задается одним из
следующих способов:
<имя_типа> = function[(<список_параметров>)]:<тип_результата>; или
<имя_типа> = procedure[(<список_параметров>)];
Например:
type func = function(a,b:integer):integer;
Слайд 22Аргументы
Аргументами, которые можно передать в параметр процедурного типа, могут быть
только подпрограммы первого уровня вложенности, чье объявление полностью соответствует этому
типу. Кроме того, объявления подпрограмм, которые могут стать аргументами, необходимо снабдить ключевым словом far, означающим, что программа будет использовать не только основной сегмент данных.
Например, для параметра, имеющего описанный выше тип func, аргументами могут послужить такие функции:
function min(a,b: integer): integer; far;
Begin
if a>b then
min:= b
else
min:= a
end;
Слайд 23function max(a,b: integer): integer; far;
begin
if a
max:= b
else
max:= a
end;
Слайд 24Вызов
Пример подпрограммы, имеющей параметр процедурного типа:
procedure count(i,j:integer; f:func);
var c: integer;
Begin
...
c:= f(i,j);
...
end;
Если будет осуществлен вызов count(x,y,min), то в локальную
переменную с запишется минимум из x и y. Если же вызвана будет count(x,y,max), то в локальную переменную с запишется максимум из x и y.
Слайд 25Рекурсия
Рекурсией называется ситуация, когда процедура или функция сама себя вызывает.
В
Паскале можно пользоваться именами лишь тогда, когда в
тексте программы этому
предшествует их описание.
Рекурсия является единственным исключением из этого правила.
Рекурсия не должна восприниматься как некий программистский трюк. Это скорее некий принцип, метод.
Если в программе нужно выполнить что-то повторно, можно действовать двумя способами:
- с помощью последовательного присоединения (или итерации в форме цикла) ;
с помощью вложения одной операции в другую (а именно , рекурсии).
Слайд 26В следующем примере один раз счет от 1 до n
ведется с
помощью цикла, а второй - с помощью рекурсии.
Пример
показывает принципиальное различие между итерацией и рекурсией: итерации необходим цикл и локальная переменная k как переменная цикла.
Рекурсии ничего этого не требуется !
Слайд 27Один из наиболее ярких примером применения рекурсии дают числа Фибоначчи.
Они определяются следующим образом:
x[1]=х[2]=1,
x[n]=x[n-1]+x[n-2] при n > 2
Каждый элемент ряда
Фибоначчи является суммой двух предшествующих
элементов, т.е.
1 1 2 3 5 8 13 21 34 55 ...
program fibonacci(input,output) ;
uses crt;
var n,result:integer;
function fibit(n:integer) :integer;
var a,b,c,i:integer;
begin
а:= 1 ; b:= 1 ;
if (n=1) or (n=2) then fibit := 1
else begin
for i := 3 to n do
begin с:= а+b; а:= b; b:= с; end;
fibit :=с ;
end;
end;
function fibrek(n:integer) :integer;
begin
if (n=1) or (n=2)
then fibrek := 1
else fibrek := fibrek (n- 1 )+fibrek (n-2);
end;
Begin
write ('n = '); readln (n) ;
writeln('Итepaтивнo:' ,fibit(n));
writeln('Peкypcивнo:',fibrek (n)) ;
end.