- •5.160 5. Программирование с использованием подпрограмм
- •5. Программирование с использованием подпрограмм
- •Процедуры
- •Объявление процедуры
- •Заголовок процедуры
- •Обращение к процедуре
- •Список формальных параметров
- •Пример 5.1 выполнения задания
- •Задания 5.1 для самостоятельной проработки
- •Функции Объявление функции
- •Заголовок функции
- •Обращение к функции
- •Пример 5.2 выполнения задания
- •Задания 5.2 для самостоятельной проработки
- •Рекурсивные подпрограммы
- •Пример выполнения задания на составление рекурсивной подпрограммы
- •Задания 5.3 для самостоятельной проработки
- •Параметры - открытые массивы
- •Динамические массивы
- •Перегружаемые подпрограммы
- •Параметры со значениями по умолчанию
- •Примеры программ с подпрограммами
Обращение к процедуре
Обращение к процедуре является отдельным оператором программы. Список фактических параметровпредставляет реально существующие данные – константы, переменные, выражения, записываемые в круглых скобках через запятую. Соответствие фактических параметров формальным параметрам устанавливается порядком их следования в списках. При вызове подпрограммы фактические параметры как бы (уточнение будет дано позже) занимают в алгоритме места соответствующих формальных параметров, после чего алгоритм выполняется.
Пример объявления и вызова процедуры, выводящей на экран первое из двух значений, представленных параметрами, кратное 5, или сообщение, что кратных нет.
//Объявление процедуры
procedure PutMod5(I,J:Integer); // I и J – формальные параметры
begin
if I mod 5 = 0 then
WriteLn(I)
else if J mod 5 = 0 then
WriteLn(J)
else
WriteLn('Нет параметров, кратных 5');
end;
. . . . .
begin// РАЗДЕЛ ОПЕРАТОРОВ ПРОГРАММЫ
. . . . .
//Вызов процедуры
PutMod5(A+3, B); // A+3 и B – фактические параметры
. . . . .
end.
Рассмотрим на конкретных значениях переменных AиB, что будет выведено подпрограммой при таком вызове:
при A=2 иB=10 будет выведено значение 5,
при A=3 иB=10 будет выведено значение 10,
при A=3 иB=11 будет выведен текст «Нет параметров, кратных 5».
Список формальных параметров
Тип в объявлении формального параметра пока будем считать обязательным и задавать только именем ранее объявленного или стандартного типа (другие возможности будут рассмотрены позже).
Прежде чем перейти к пояснению правил объявления формальных параметров, введем в рассмотрение два термина: входной параметривыходной параметр. Параметр считается входным, если он представляет исходные данные для счёта по алгоритму подпрограммы (в рассмотренном примере оба параметра являются входными). Параметр считается выходным, если он представляет результаты счёта по подпрограмме. Допускается, что один и тот же параметр может одновременно представлять и исходные данные и результат, то есть быть одновременно и входным, и выходным.
В языке Object Pascal рассмотренное функциональное деление параметров (на входные, выходные, входные-выходные) дополнено механизмами реализации их функций, отраженными в правилах объявления формальных параметров. Сначала рассмотрим два вида объявлений параметров: параметры-значения и параметры-переменные.
Параметры-значениявсегда являются только входными параметрами. Соответствующими фактическими параметрами могут быть выражения (в частности, константы и переменные). При вызове подпрограммы выражения вычисляются, и полученные значения заносятся (а значения констант и переменных просто копируются) в ячейки памяти, представленные соответствующими формальными параметрами, значения которых внутри подпрограммы можно изменять. Механизм параметров-значений таков, что эти изменения никак не отразится на значениях фактических параметров, то есть после выхода из подпрограммы они останутся неизменными. Таким образом, формальный параметр-значение можно рассматривать как переменную, известную внутри подпрограммы, а механизм таких параметров – как защиту фактических параметров, если они являются переменными, от непреднамеренного изменения.
Объявление параметров-значений даётся просто их именем (списком имен через запятую) и типом (без предшествующих слов var,const,out). В рассмотренной процедуре PutMod5 оба параметра являются параметрами-значениями.
Параметры-переменныеявляются одновременно и входными, и выходными параметрами. Соответствующими фактическими параметрами могут быть только переменные. Механизм параметров-переменных таков, что изменения, выполняемые в алгоритме подпрограммы над соответствующими формальными параметрами, приводят к изменению значений фактических параметров, и эти изменения сохранятся после выхода из подпрограммы. Достигается это за счет того, что в подпрограмму передаётся не сама переменная, а ссылка на неё, то есть обеспечивается непосредственный доступ из подпрограммы к данным фактического параметра.
Объявление параметров-переменных даётся с предшествующим их имени (списку имен) словом varи типом.
Пример процедуры, умножающей данные в первых nячейках массиваMasна дробную часть числаR. Все участвующие в обработке данные должны передаваться через параметры.
type tMas=array[1..8] of Real;
. . . . .
//Объявление процедуры
procedure MasMulR(R:Real; N:Integer; var Mas:tMas);
var
i:Integer;
begin
R:=Frac(R);//Получить дробную часть R
for i:=1 to N do
Mas[i]:=Mas[i]*R;
end;//MasMulR – конец текста процедуры
. . . . .
var
X:tMas=(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0);
Z:Real=3.4;
. . . . .
begin// РАЗДЕЛ ОПЕРАТОРОВ ПРОГРАММЫ
. . . . .
MasMulR(Z,5,X);//Вызов процедуры
. . . . .
end.
В этом примере параметр Mas является и входным, и выходным, поэтому он объявлен как параметр-переменная (с предшествующим словом var). Параметр R является только входным. Так как он объявлен как параметр-значение, то его значение можно, после того, как оно будет использовано как входное данное, менять внутри подпрограммы, то есть использовать как дополнительную переменную, не опасаясь, что изменим значение соответствующего фактического параметра. При указанных в примере начальных значениях переменных после выполнения процедуры переменная Z сохранит своё значение3.4, а в массиве будут следующие данные:(0.4, 0.8, 1.2, 1.6, 2.0, 6.0, 7.0, 8.0).
Параметры-значения обладают одним недостатком, который может быть очень существенным, если параметром является структурная переменная, например, массив, занимающая большой объём памяти. В этом случае подпрограмма, получив управление, должна выделить такой же объём памяти, какой занимает фактический параметр, и скопировать в неё данные из фактического параметра. То есть недостаток состоит в том, что нерационально используется память и происходит потеря времени на копирование данных перед началом их обработки по алгоритму подпрограммы. Указанных недостатков лишен другой вид входного параметра, получивший название «параметр-константа».
Параметр-константа, как и параметр-значение, служит для представления только входных данных. При его использовании в подпрограмму передаётся ссылка на фактический параметр (как и для параметра-переменной), но, чтобы исключить его непреднамеренное изменение во время работы программы, уже на этапе компиляции выполняются соответствующие проверки и исполняемая программа не создаётся, если подпрограмма содержит операторы, которые могут изменить данные фактического параметра.
Объявление параметров-констант даётся с предшествующим их имени (списку имен) словом constи типом.
Последний вид параметра следует использовать для параметров, представляющих только результаты работы подпрограммы. По аналогии с параметрами других видов ему подошло бы название параметр-результат, или по предшествующему его имени словуout в объявлении –параметр-выходная переменная. Этот параметр передаётся по ссылке, но компилятор не запрещает его использования в качестве источника исходных данных. За этим должен следить программист, а словоoutперед его именем в списке формальных параметров призвано облегчить понимание алгоритма подпрограммы, напоминая, что этот параметр не представляет входных данных.
Пример процедуры, в объявлении которой желательно использовать параметр-константу и параметр-результат. Подпрограмма должна вычислять сумму положительных элементов массива X(100,100) и их количество.
type
tMas=array[1..100,1..100] of Extended;
. . . . .
//Объявление процедуры
procedure SumCol(const X:tMas, out S: Extended; out K:Integer);
var
i,j: Integer;
begin
S:=0;
K:=0;
for i:=1 to 100 do
for j:=1 to 100 do
if X[i,j]>0 then
begin
S:=S+X[i,j];
K:=K+1;
end;
end;
. . . . .
var
Y:tMas; Sum: Extended; Col: Integer;
. . . . .
begin// РАЗДЕЛ ОПЕРАТОРОВ ПРОГРАММЫ
. . . . .
SumCol(Y,Sum,Col);
. . . . .
end.
Взглянув на заголовок подпрограммы, сразу можно сказать, что первый параметр является только входным, а два последних – только выходными. Первый параметр объявлен параметром-константой, а не параметром-значением, чтобы избежать выделения памяти в 100000 байт и копирования в неё данных из фактического параметра - массива Y.