Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_TP.doc
Скачиваний:
10
Добавлен:
22.12.2018
Размер:
1.4 Mб
Скачать

Вычисление значения функции. Завершение подпрограмм.

В теле функции должен присутствовать оператор присваивания , в левой части которого указано имя функции, в правой - выражение , вычисляющее возвращаемое значение . Таких операторов может быть несколько. Не забывать про совместимость типов, передаваемость возвращаемого значения.

Пример: определение максимума двух целых чисел.

FUNCTION MAX(A,B:BYTE):BYTE;

BEGIN

IF A>B THEN MAX:= A ELSE MAX:=B

END;

BEGIN

. . . . . . . . . . . . . . . . . . .

M:=MAX(A-B,A+B)+2*MAX(A*B, A MOD B);

. . . . . . . . . . . . . . . . . . .

В Турбо Паскале есть дополнительное средство прерывания выполнения подпрограмм в произвольной точке - процедура EXIT без параметров. Она медленно завершает работу подпрограммы и возвращает управление в точку ее вызова. В функциях перед EXIT обязятельно должен выполниться оператор присваивания с именем функции в левой части . Если вызов процедуры EXIT был произведен из блока , соответствующего программе в целом, будет немедленно завершено выполнение всей программы.

PROCEDURE D1(X,Y:REAL; VAR R:REAL);

BEGIN

IF X-Y < 0.001 THEN EXIT;

R:= (X*X+Y*Y);

END;

Предварительное описание подпрограмм.

Достаточно распространен случай, когда две подпрограммы ,описанные на одном уровне вложенности, содержат взаимные вызовы друг друга.

PROCEDURE JOHN(X,Y:REAL);

BEGIN

JACK(1,2);

END;

PROCEDURE JACK(A,B:BYTE);

BEGIN

JOHN( 0.5,0.8);

. . . . . . . . . . . . . . . . . . .

END;

Решением этой проблемы является механизм предварительных описаний подпрограмм.

Предварительное описание подпрограмм содержит заголовок процедуры и служебное слово FORWARD , которое указывает, что полное описание подпрограммы располагается далее. Для приведенного примера предварительное описание будет выглядеть следующим образом :

PROCEDURE JOHN(X,Y:REAL);FORWARD;

JACK(A,B:BYTE);FORWARD ;

Рекурсия и побочный эффект

В теле подпрограммы доступны все объекты , описанные в объемлющем блоке , в том числе и имя самой подпрограммы . Внутри ее тела возможен вызов самой себя. Это и есть рекурсия . Рекурсивные функции - функции и процедуры, использующие вызов самих себя. Рекурсия достаточно широко применяется в программировании математических алгоритмов. Наиболее популярен алгоритм определения факториала:

0!=1 1!=1 2!=1*2=2 n!=1*2*.....*(n-1)

FUNCTION FACT(N:WORD):LONGINT;

BEGIN

IF N=1 THEN

FACT:=1;

ELSE

FACT:= N*FACT(N-1)

END;

В Паскале нет ограничений на рекурсивные вызовы подпрограмм, но каждый очередной рекурсивный вывод приводит к образованию новой копии локальных объектов и все они существуют независимо друг от друга.

Рассмотрение вопросов, связанных с подпрограммами, дополним обсуждением одного неожиданного эффекта при выполнении функций, причиной которого является изменение значений нелокальных переменных в теле функции.

Если в некоторой функции имеются конструкции ( например, операторы присваивания), изменяющие значения переменных, описанных в объемлющих блоках , то может возникнуть ситуация, при которой значение выражения , использующего вызов такой функции , зависит от порядка следования операндов , что является потенциальным источником трудноуловимых программных ошибок и поэтому крайне нежелательно. Описанная ситуация называется побочным эффектом .

Пример побочного эффекта:

PROGRAM SIDEEFFECT;

VAR A,Z : INTEGER;

FUNCTION CHANGE (X:INTEGER):INTEGER;

BEGIN

Z:=Z-X; { изменяем значение нелокальной переменной}

CHANGE:=SQR(X);

END;

BEGIN

Z:=10;A:= CHANGE(Z);WRITELN(A,Z);

Z:=10; A:= CHANGE(10)*CHANGE(Z) ;WRITELN(A,Z);

Z:=10; A:= CHANGE(Z)*CHANGE(10);WRITELN(A,Z);

END.