Программа на Delphi

AllocMemCount – количество блоков выделенной памяти.

AllocMemSize – размер блоков выделенной памяти.

15. Подпрограммы

Подпрограмма – это законченная алгоритмическая единица, которая предназначена для выполнения некоторого ограниченного по отношению к использующей ее программе круга операций.

В языке Object Pascal есть два вида подпрограмм – процедуры и функции. Структура всякой подпрограммы во многом напоминает структуру исходного модуля. Каждая такая подпрограмма перед ее использованием должна быть описана. Описанием подпрограммы называется ее исходный код, а обращением к подпрограмме является оператор или его часть, которые содержат код вызова такой подпрограммы. Таким образом, описание – это технология, а обращение – это действия по предписанной технологии.

Всякая подпрограмма может иметь локальные и глобальные по отношению к ней параметры. Локальным является параметр, действие которого ограничено только подпрограммой, в которой он описан. Всякий другой параметр будет глобальным. Все глобальные параметры всегда описаны за пределами подпрограммы, в которой они используются.

15.1. Процедуры

Всякая процедура имеет заголовок и тело. Тело процедуры состоит из операторов, предназначенных для описания имен и действий над данными. Синтаксис процедуры имеет вид

ProcedureprocedureName(parameterList); directives;

localDeclarations;

begin

statements;

end;

Здесь

Name – имя процедуры,

parameterList – список формальных параметров,

directives – директивы,

localDeclarations – внутренние описания,

statements – операторы тела процедуры.

procedureName – имя процедуры. Именем процедуры может быть любое имя, не совпадающее ни с каким другим описанным в том же, что и процедура, блоке, именем.

parameterList – список формальных параметров может быть либо пуст (в этом случае скобки можно не использовать), либо должен содержать последовательность входных и/или выходных величин. Отдельная величина в описании заголовка может быть:

объявленной с помощью слова var переменной с типом или без типа;

константой;

выходной величиной (т. н. out-параметром).

Пример описания процедуры.

procedure ByRef(var X: Integer; L, K: Integer);

begin

X := X * 2 * L; {правильно}

K := 2 + L; {ошибка}

end;

Процедура c именем ByRef содержит три параметра – переменную X и две константы L и K. Тело процедуры состоит из операторов, заключенных в операторных скобках begin – end. Переменные L, K являются только входными и не могут быть изменены в теле процедуры. По этой причине оператор K:= 2 + L не даст результата и значение К останется таким же, каким оно было до обращения к процедуре. Напротив, переменная X, объявленная с помощью слова var, будет вычислена и на выходе будет иметь то значение, которое будет вычислено внутри процедуры ByRef.

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

procedure GetInfo(out Info: SomeRecordType);

var MyRecord: SomeRecordType;

.

Proc1(MyRecord);

переменная MyRecord не может передавать данные в процедуру Proc1. Напротив, только Proc1 может сформировать данные и передать их в MyRecord.

Тип параметра может быть любым. Однако нельзя объявлять новый тип прямо в заголовке подпрограммы. Такой тип должен быть объявлен раньше и только после этого может быть использован в заголовке подпрограммы.

localDeclarations – внутренние описания могут содержать описание локальных имен типов или переменных. В предыдущем примере переменная MyRecord типа SomeRecordType, объявленная внутри процедуры GetInfo, является образцом такого описания.

directives – директивы используются для того, чтобы дать компилятору некоторые дополнительные указания об описываемой процедуре. Директивы описаны в параграфе 15.3.

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

Program {начало программы}

Const n = 10; {размер матриц}

Type tMatr = array[1 n, 1 n] of Real; {тип матриц}

Var Q1, Q2, Q3: tMatr; {описание матриц}

Procedure MatrMult(M1, M2: tMatr; Var M3: tMatr); {заголовок}

Var i, j, k: Integer;

Begin

For i:= 1 to n do

For j:= 1 to n do

Begin {блок определения одного элемента матрицы M3}

M3[i, j]:=0;

For k:=1 to n do

M3[i, j]:= M3[i, j] + M1[i, k] * M2[k, j];

End;

End; {конец описания процедуры MatrMult}

Procedure Prim; {заголовок процедуры Prim}

Var i, j: Integer;

Begin

For i:= 1 to n do {блок задания элементов матриц Q1, Q2}

For j:= 1 to n do

Begin

Q1[i, j]:=i + j;

Q2[i, j]:=i - j;

End;

MatrMult(Q1, Q2, Q3); {оператор обращения к процедуре MatrMult}

End; {конец описания процедуры Prim}

… {текст головной программы}

Prim; {обращение к процедуре Prim}

Q3[2, 3]:= 1;

Приведенный в данном примере текст программы можно разделить на четыре части:

описание глобальных констант и переменных;

текст процедуры MatrMult;

текст процедуры Prim;

текст головной программы.

В верхней части описана глобальная константа n = 10, которая используется во всех следующих за этим структурах. Так, в секции Type объявлен тип вещественного квадратного массива tMatr. Далее в секции Var объявлены три переменные – матрицы Q1, Q2, Q3 типа tMatr.

Далее дан текст процедуры MatrMult, которая представляет алгоритм перемножения матриц M1 и M2 с записью результата в переменную M3. Матрицы M1, M2 в процедуре не меняются, поэтому их необязательно объявлять переменными (с позиций процедуры MatrMult переменные M1, M2 выступают в качестве констант). Напротив, матрица M3 получается как результат, определяемый внутри процедуры MatrMult, поэтому она объявлена в заголовке словом Var. Необъявление M3 как переменной привело бы к ошибке: измененные внутри процедуры значения этой матрицы не были бы зафиксированы. Переменные i, j, k, объявленные внутри процедуры, являются локальными и действуют только в пределах этой процедуры.

Описание процедур заканчивается процедурой Prim. В теле этой процедуры объявлено две локальные переменные i, j, выполняющих вспомогательную роль счетчиков циклов. Далее расположено два вложенных друг в друга цикла, с помощью которых определяются элементы матриц Q1 и Q2. По отношению к процедуре Prim эти матрицы являются глобальными переменными и, следовательно, они доступны не только во внешнем блоке, но и внутри процедуры Prim. И наконец, в нижней части расположен оператор обращения к процедуре MatrMult, который предназначен для вызова алгоритма перемножения матриц.


Страница: