Занятие 11. Процедуры и функции
Часто одна и та же последовательность операторов может выполняться в программе несколько раз в разных местах. В этом случае эту последовательность операторов можно оформить как подпрограмму и вызывать с разными параметрами в нужных местах программы. Подпрограммы в Паскале реализованы в виде процедур и функций. Процедура(функция) это подпрограмма, которая описывается один раз, а вызываться может несколько раз из разных мест программы, возможно с разными параметрами. Отличие процедур от функций заключается в том, что функция возвращает значение, а процедура - нет.
Использование процедур(функций) позволяет:
1. избежать дублирования программного кода: описав процедуру(функцию) один раз, можно вызывать ее несколько раз из разных мест программы;
2. упаковка программного кода в процедуры(функции) позволяет структурировать программу: с использованием процедур(функций) программа приобретает четкую и понятную структуру;
3. однажды написанная процедура(функция) может многократно использоваться в других программах, таким образом, создаются библиотеки процедур(функций).
Примером применения процедуры(функции) может служить подпрограмма, которая вычисляет минимальное значение двух переменных, находит подстроку из строки, обработчики событий и методы объектов оформлены в виде процедур.
Процедуры и функции перед использованием должны быть обязательно описаны.
Описание процедуры(функции) состоит из трех частей: заголовка, раздела описаний и тела:
<Заголовок подпрограммы>
<Раздел описаний>
<Тело>
Описание и вызов процедуры
Синтаксис описания процедуры имеет вид:
Procedure <имя процедуры> [(список формальных параметров)];
[(раздел описаний)]
begin
<операторы>
end;
Ключевое слово procedure задает описание заголовка. В заголовке задается:
- имя процедуры, по которому она в дальнейшем может быть вызвана;
- список формальных параметров, который не является обязательным.
Формальными параметрами называются параметры, которые задаются при описании процедуры, в отличие от фактических параметров, которые задаются при вызове процедуры. Каждый параметр в списке описывается со своим типом. Разделителем списка формальных параметров является - ';' (точка с запятой). Если несколько параметров имеют одинаковый тип, то их можно перечислить через запятую. Например:
Procedure Compute(x,y : integer; str : String);
В разделе описаний описываются переменные, константы и другие подпрограммы, которые используются только внутри этой процедуры.
Тело процедуры заключается в операторные скобки begin..end.
Например: процедура считает сумму двух чисел, которые поступают на вход и выдает их сумму в свойстве caption объекта Label1.
Procedure sum(a,b:integer);
Begin
Label1.Caption:=IntToStr(a + b);
End;
Синтаксис вызова процедуры имеет следующий вид:
<имя процедуры>[(список фактических параметров)];
Фактические параметры это параметры, которые задаются при вызове процедуры(функции). Разделителем списка фактических параметров является - ',' (запятая). Порядок следования и типы фактических параметров должны четко соответствовать порядку следования и типам соответствующих формальных параметров.
Пример 1.Вызов процедуры sum:
sum(4,7);
Пример 2. Дан двумерный массив размером 10 на 10, описывающий поле для игры «Сапер». Если значение в ячейке поля равно 0, то там нет мины, если значение ячейки равно 1 – там лежит мина. Написать процедуру, которая инициализирует этот массив, т.е. пустым ячейкам поля присваивает значения 0 и раскладывает 20 мин в случайных ячейках поля.
Решение. Опишем массив на верхнем уровне секции реализации или в секции Interface:
var Pole:array[1..10,1..10] of byte;
Назовем процедуру InitPole. Входных параметров она не имеет. Поэтому вызывается она следующим образом: InitPole;
В секции implemention опишем тело процедуры:
Procedure InitPole;
Var i, j, k : Integer;
Begin
{ всем ячейкам поля присвоить значение 0 }
for i:=1 to 10 do
for j:=1 to 10 do Pole[i,j]:=0;
{ разложить мины в случайные места поля }
i:=1;
randomize;
while i<=20 do
begin
j:=random(10)+1;
k:=random(10)+1;
if Pole[j,k]=1 then continue;
Pole[j,k]:=1;
i:=i+1;
end;
End;
Пример 3. В игре, описанной в пункте «Как совместить разные виды движения», все летающие тарелки движутся по одному и тому же закону. Требуется написать процедуру, назовем ее FlyNLO, которая будет управлять движением тарелки. На вход процедуре поступает указатель на летающую тарелку. Для того чтобы можно было получать доступ к объектам формы внутри процедуры, следует делать процедуру методом класса формы. Для этого нужно ее заголовок описать в классе формы, как показано:
type
TForm1 = class(TForm) { описание класса формы }
Pushka: TImage;
Fly1: TImage;
Fly2: TImage;
Snar: TImage;
Timer1: TTimer;
Timer2: TTimer;
procedure FlyNLO(Sender:TObject); { заголовок процедуры }
…
Как видно из заголовка процедуры ей передается параметр Sender типа TObject – это указатель на конкретную летающую тарелку. Тело процедуры описывается в разделе implementation модуля и имеет следующий вид:
procedure TForm1.FlyNLO(Sender:TObject);
begin
if not (Sender as TImage).Visible then
with (Sender as TImage) do
begin
top:=random(200)+1;
left:=0;
visible:=true;
tag:=random(10)+5;
end
else
{ полет }
if (Sender as TImage).left+(Sender as TImage).Width<Form1.Width then
(Sender as TImage).left:= (Sender as TImage).left+(Sender as TImage).tag
else
(Sender as TImage).visible:=false;
end;
Как вы видите этот программный код мало, чем отличается от того, что мы писали в пункте «Как совместить разные виды движения». Для правильной работы процедуры-метода необходимо указать тип объекта Sender. Для этого используется оператор As, который позволяет рассматривать Sender как объект класса TImage.
Вызывается эта процедура в обработчике события OnTimer, столько раз, сколько у нас летающих тарелок с соответствующими параметрами:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
FlyNLO(Fly1); {полет 1 летающей тарелки}
FlyNLO(Fly2); {полет 2 летающей тарелки}
End;
Описание и вызов функции
Синтаксис описания функции очень похож на описание процедуры и имеет следующий вид:
Function <имя функции>[(список формальных параметров)]:<тип результата>;
[<раздел описаний>]
begin
<операторы>
end;
Ключевое слово function – задает описание заголовка функции. Заголовок содержит:
- имя функции, которое используется при ее вызове;
- список формальных параметров, при этом каждый параметр описывается со своим типом, также как при описании процедуры;
- тип возвращаемого функцией значения.
Раздел описаний функции содержит описания переменных, констант и других подпрограмм, которые используются только внутри этой функции.
Тело функции заключается в операторные скобки begin..end.
Внутри каждой функции есть зарезервированная локальная переменная с таким же именем, что и сама функция, имеющая тот же тип, что и возвращаемое функцией значение. Она доступна для чтения и может быть использована в промежуточных вычислениях. Она обязательно должна получить значение на выходе из функции.
Пример описания функции:
function maxim(a,b:integer):integer;
begin
if a>b then
maxim:=a
else
maxim:=b;
end;
Синтаксис вызова функции имеет следующий вид:
<Переменная>:=<Имя функции>[(Список формальных параметров)]
Так как функция возвращает результат, она может использоваться в выражениях, при этом вместо функции подставляется возвращаемое ей значение.
Например, вызов функции maxim:
k:=maxim(100,56)