
Процедуры и функции (96
..pdf
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
ния. Эти параметры предназначаются только для передачи данных в подпрограмму, но не для получения от нее результата.
Например:
Procedure E1 (par1: type1; par2: type2; par3, par4 : type3);
Для установки в операционной системе даты используется процедура, имеющая заголовок:
Procedure SetData (Year, Month, Day: word);
Все три параметра: Year, Month, Day — параметры-значения. Параметры-переменные — это формальные параметры. При описании заголовков процедур/функций перед идентификаторами параметров-переменных ставится ключевое слово var, что позволяет информации передаваться из подпрограммы в основную про-
грамму.
В ячейки памяти формального параметра передается адрес фактического параметра, по имеющемуся адресу изменяется содержимое ячеек памяти фактического параметра, т. е. выполняется возврат результата (рис. 3).
Рис. 3
В качестве фактического параметра-переменной могут использоваться переменные любых типов, включая и файловые типы, но использование констант не допускается. Через параметрыпеременные в программу передаются полученные результаты. Параметры-переменные называются выходными параметрами. Параметры-константы — это формальные параметры, которые защищены, и в подпрограмме им нельзя присвоить какое-либо значение. Параметры-константы гарантируют пользователям, что параметры, которые они передают, не будут изменены ни в коем случае. Перед параметрами-константами ставится ключевое слово const.
11

Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
Рис. 4
Вячейки памяти формального параметра передается адрес фактического параметра: по имеющемуся адресу разрешено только брать значения фактического параметра, а изменять его значения запрещено, т. е. обратного влияния нет (рис. 4).
Вкачестве фактического параметра-константы могут исполь-
зоваться как переменные, так и константы различных типов. Не допускаются файловые типы.
Например:
Procedure MGTU1 (var par1, par2: type1; par3, par4: type2);
где par1, par2 — параметры-переменные; par3, par4 — параметрызначения.
Procedure MGTU2 (const par1, par2: type1; var par3, par4: type2; par5, par6: type3);
здесь par1, par2 — параметры-константы; par3, par4 — параметрыпеременные; par5, par6 — параметры-значения.
Для получения от операционной системы даты используется процедура, имеющая заголовок:
Procedure GetData (Var Year, Month, Day: word);
Все три параметра Year, Month, Day — параметры-переменные типа Word.
Если в заголовке процедуры тип параметра не указывается, то такой параметр называется бестиповым.
Procedure NOTYPE (Var Par1, Par2; const Par3, Par4).
Бестиповые параметры могут передаваться только по адресу, т. е. как параметры-переменные и параметры-константы. Бестиповыми могут быть только параметры-переменные. Параметры Par1, Par2 могут иметь любой тип, через них можно передавать подпрограмме строки, массивы, записи, целые и вещественные типы и
12
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
другие данные. Но внутри подпрограммы должен быть явно описан тип, к которому направляются бестиповые переменные.
Передача параметров в процедурах и функциях через открытые массивы
Открытый массив — это массив без определения его границ, т. е. без указания его размерности. Для объявления такого массива применяется обычное объявление массива, но без указания размерности:
Type
T_OpenArray=array of char; Var
Vodmas: T_OpenArray of byte;
Procedure Test( OpenArray: T_OpenArray); Function Test1(OpenArray:array of byte) : real;
В подпрограмме нижняя граница массива определяется как нулевая через функцию Low(OpenArray), верхняя граница определяется через функцию High(OpenArray), размер массива определяется функцией SizeOf(OpenArray).
Параметры-процедуры. При передаче имени функции или процедуры в качестве параметра необходимо выполнить следующие действия.
1. В разделе описания Type описать пользовательский тип как функцию (или процедуру) с соответствующими параметрами без указания имени функции (или процедуры), например:
Type
TfuncPar = Function (X:Real): Real; TprocPar = Procedure (Y:byte;ch:char);
2.В разделе описания переменных определить переменную через объявленный тип. Эти переменные называются процедурными переменными. Они могут быть использованы в качестве формальных параметров.
3.Процедуры, передаваемые в качестве параметров, необходимо обязательно заключать между директивами компилятора {$F+}
и{$F-}, т. е. оттранслировать с опцией {$F+} или описать с директивой Far — дальней модели вызова.
13
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
Процедуры не должны быть:
•стандартными процедурами или функциями;
•вложенными процедурами или функциями;
•inline-процедурами или функциями;
•interrupt-процедурами или функциями.
4.Связать переменные типа функции/процедуры с пользовательской процедурой или функцией.
5.Передать в процедуру значение этой переменной или непосредственно передавать имя процедуры или функции.
При вызове подпрограммы вместо формальных процедурных параметров осуществляется подстановка имен соответствующих фактических процедур и функций. Если процедуры или функции, использующиеся в качестве фактического параметра, в свою очередь имеют параметры, то они могут быть только параметрамизначениями.
Использование процедур и функций
Использование процедуры означает ее вызов во время выполнения программы, т. е. обращение к ее имени в любом месте внутри блока исполняемых операторов, заключенных в теле основной программы между ключевыми словами BEGIN. . . END.
Функция вызывается всегда, когда ее имя используется в качестве составной части выражения или оператора присваивания в основном блоке программы. Необходимо использовать функцию как подпрограмму тогда, когда следует получить единственное значение. Не рекомендуется использовать функцию для возврата многих значений через параметры-переменные.
При передаче параметров подпрограмм вместо формальных параметров-значений можно использовать целые выражения, но
тип выражения должен соответствовать типу формального параметра.
Можно использовать результат функции либо подстановку имени функции вместо фактического параметра-значения.
Если необходимо возвратить несколько значений, следует всегда использовать процедуру.
14

Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
Область действия (сфера видимости) идентификаторов при использовании процедур и функций
Областью действия (сферой видимости) идентификатора
(переменной) называется часть программы, где он может быть использован. Область действия идентификаторов (переменных)
определяется местом их объявления. Если идентификаторы допускается использовать только в рамках одной процедуры или функции, то такие идентификаторы называются локальными.
Локальные переменные могут быть описаны как в заголовке подпрограммы, так и в описательной ее части. Если действие идентификаторов распространяется на несколько вложенных процедур и/или функций, то такие идентификаторы называются глобальными.
Рассмотрим сказанное на примере (рис. 5).
Рис. 5
Рассмотренный пример показывает, что переменные A0, B0, C0, описанные в основной программе, являются глобальными переменными для всех процедур и функций, т. е. их можно использовать в самих процедурах. Переменные A1, B1, C1 являются
15
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
глобальными для всех процедур и функций, вложенных в процедуру Parlok, но в самой процедуре они локальные. Переменные А2, В2, С2, объявленные в описательной части самой внутренней процедуры Parlok1, и формальная переменная Р1, описанная в заголовке процедуры, являются локальными. Из процедуры Parlok1 можно обращаться к переменным A2, B2, C2 как описанным в теле процедуры, а также к переменным A1, B1, C1 и A0, B0, C0 как видимым из процедуры в качестве глобальных параметров.
Из программы DEMO нельзя обратиться к переменным A1, B1, C1 и A2, B2, C2, так как они локальны и не видны программе.
При завершении работы подпрограммы память, выделенная под переменные, освобождается, поэтому все результаты, полученные при работе подпрограмм, разрушаются и не сохраняются до следующего обращения к подпрограмме.
Действия переменных подчиняются следующим правилам.
1.Локальные переменные действуют локально там, где они определены и могут выступать в качестве глобальных, если они окружают контекст процедур или функций.
2.Локальные переменные процедур/функций никогда не работают во внешнем окружении.
3.В случае совпадения имен глобальной и локальной переменной действовать будет только локальная переменная. Локальная переменная перекрывает значение глобальной переменной в основной программе, если локальная переменная передается основной программе и ее имя совпадает с именем глобальной переменной.
Отсюда следует важный вывод: если подпрограмма что-то передает в вызывающую программу, то подпрограмма ничего не должна изменять в основной программе!
Локальные данные создаются только при вызове процедуры или функции и существуют только во время ее выполнения. Выделение памяти для них происходит только на период функционирования процедуры или функции, и освобождение памяти происходит по окончании работы процедуры или функции. Поэтому локальные данные выводятся на печать в самой процедуре (рис. 6).
16

Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
Рис. 6
Перекрытие глобальных переменных и констант
Рассмотрим пример с использованием параметров-переменных и параметров-значений в процедуре, если в качестве фактических параметров выступают глобальные переменные:
Program Proba; {перекрытие глобальных переменных} Const
A : integer=5; B : integer=7; Var C : integer;
Procedure Uvel (var c : integer; b: integer) {удвоение элементов}
begin
c := c+c; b := b+b;
17
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
writeln (‘Удвоение C и B процедурой в процессе решения :’ , c:5,
b:5)
end; {uvel} Begin {Proba}
writeln (‘Исходные A и B до решения равны: ’, a:5, b:5) Uvel (a, b)
Uvel (c, b)
Writeln (‘Результат после работы процедуры:’,a:5, b:5, c:5) End. {Proba}
Решение на экране будет представлено следующим образом.
Исходные А и В до решения равны: 5 7 Удвоенные С и В процедурой в процессе решения: 10 14 Результат после работы процедуры: 10 7
Результат работы показывает следующее: параметр А описан в процедуре как параметр-переменная, а параметр В — как параметрзначение.
После окончания работы процедуры параметр А изменил начальное значение А = 5 на А = 10 только потому, что полученное значение было возвращено формальному параметру через переменную А.
Параметр-значение никак не влияет на формальные параметры. Вывод: параметры-переменные используются как средство связи процедуры с программой. С помощью этих параметров подпрограммы могут передавать результаты своей работы вызы-
вающей программе:
Function Log10 ( Х: Real): Real;
{функция возвращает значение десятичного логарифма числа Х} BEGIN
log10: = Ln(Х)/Ln(10) END;
Function Pwr (a,x: Real): Real;
{функция возвращает значение АХ (А в степени х (А>0)} Begin
Pwr:= Exp(x*Ln(a)); end;
Рассмотрим примеры по написанию подпрограмм.
18
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
Удобно показать необходимость реализации подпрограмм на примере вычисления числа сочетаний. Поиск числа сочетаний является задачей комбинаторики — области математики, которая изучает вопросы о том, сколько различных комбинаций можно составить из заданных объектов.
Число сочетаний из n элементов по m вычисляют по формуле
Cmn =n!/m!(n-m)!
где n, m — целые положительные числа и n > m. Алгоритм решения.
1.Вычислим n! — это числитель формулы.
2.Вычислим m!
3.Вычислим (n – m)!
4.Перемножим m! на (n – m)!, получим знаменатель формулы.
5.Разделив числитель на знаменатель, получим результат.
Из алгоритма ясно, что трижды производятся действия по вычислению факториала. Программа будет иметь несколько операторов, которые будут выполнять одни и те же действия, что ведет к росту числа операторов и понижает уровень смыслового понимания работы программы, ее удобочитаемость. Чтобы исключить повторные действия и уменьшить число операторов в программе, следует использовать процедуру или функцию для вычисления факториала.
Рассмотрим два метода определения факториала заданного числа.
1. Факториал — это произведение целых чисел от 1 до n: n!=1 ∙ 2 ∙ 3 ∙ . . . ∙ n;
0! = 1; 1! = 1;
2! = 1 ∙ 2 = 2; 3! = 1 ∙ 2 ∙ 3 = 6;
4! = 1 ∙ 2 ∙ 3 ∙ 4 = 24.
Вычислить факториал можно с использованием итерационного вычисления в цикле For, начиная перемножение чисел с 1 до n включительно:
Function factI (n: byte): longint; Var
f, i: byte; Begin
19
Copyright ОАО «ЦКБ «БИБКОМ» & ООО «Aгентство Kнига-Cервис»
f:=1;
For i=1 to n do f:=f*i; factI:=f;
end;
2. Формулу для вычисления факториала можно записать в виде: n! = (n – 1)! ∙ n
Мы получили рекуррентную формулу для вычисления факториала, которая справедлива для всех значений n > 0.
Рекуррентная формула — это формула, которая применяется для определения членов в последовательности чисел, каждый член в которой получают умножением предыдущего на некоторое постоянное для данной последовательности выражение:
an= f(n, an−1,an−2, ... an−p).
Вычисление по рекуррентным формулам называется рекурсивным методом вычисления. Любой объект, который частично определяется через самого себя, называется рекурсивным.
Программа вычисления факториала с использованием рекурсивного метода будет иметь вид:
Function fact_R (n: byte): longint; Begin
If n=1 then fact_R := 1 Else fact_R :=n*fact_R(n-1)
end;
Программа нахождения числа сочетаний будет иметь следующий вид:
Program Sochetanie_n_m;
{Вычисляет сочетания из n элементов по m} uses crt;
Var n,k,l,r:byte;
Chislitel, sochetanie_fI, sochetanie_p, sochetanie_fR, znamenatel:longint; c,d,e,s:longint;
{————}
function factorial_I(K:byte):longint; {вычисляет k! итерационным методом} var i:byte;
p:longint; begin
20