7.3. Процедуры
Заголовок процедуры имеет вид:
PROCEDURE Procname(FORM) ,
где Procname - имя процедуры, FORM - список формальных параметров. Формальными параметрами могут быть:
- переменные;
- имена подпрограмм.
Формальные параметры, через которые возвращается результат рабо-ты процедуры, снабжаются спецификацией VAR.
Выполнение процедуры активируется с помощью оператора про-цедуры.
Оператор процедуры - это имя процедуры, за которым в скобках следует список фактических параметров.
Если формальный параметр имеет спецификацию VAR, то соответ-свующий фактический параметр может быть только переменной.
Примеры заголовков процедур: PROCEDURE Zub(a:real; VAR x,y:real);
PROCEDURE Mol(r:char; VAR z:Boolean);
и обращений к ним: Zub(x*Sqr(Ln(x))+1.2, p,s); Mol('c', b) .
Пример 7.3.1. Имеется массив чисел вещественного типа. Построить два новых массива, состоящих из целых и дробных частей элементов исход-ного массива. PROGRAM Intr;
CONST n=10;
TYPE remas = ARRAY[1..n] OF real;
intmas = ARRAY[1..n] OF integer;
VAR k : integer;
a,br : remas;
bi : intmas;
PROCEDURE Rol(n:integer; a:remas;VAR cr:remas;VAR ci:intmas);
VAR k : integer;
BEGIN
FOR k:=1 TO n DO
BEGIN
ci[k]:=Trunc(a[k]);
cr[k]:=a[k]-ci[k]
END;
END; { PROCEDURE Rol }
BEGIN
Write('Массив a : ');
FOR k:=1 TO n DO Read(a[k]);
Rol(n,a,br,bi); { Обращение к процедуре }
FOR k:=1 TO n DO
WriteLn(k:2, a[k]:30, bi[k]:10, br[k]:30)
END.
Пример 7.3.2. Разработать процедуру, выполняющую зеркальное ото-бражение элементов одномерного массива относительно его середины. CONST n=10;
TYPE arr = ARRAY[1..n] OF integer;
VAR k : integer;
a : arr;
PROCEDURE Mirror(n:integer; VAR a:arr);
VAR k,buf : integer;
BEGIN
FOR k:=1 TO n DIV 2 DO
BEGIN
buf:=a[k];
a[k]:=a[n-k+1];
a[n-k+1]:=buf
END
END;
BEGIN
Write('?');
FOR k:=1 TO n DO Read(a[k]);
Mirror(n,a);
FOR k:=1 TO n DO WriteLn(a[k])
END.
Задачи
7.3.1. Ввести два массива чисел. В каждом массиве найти наиболь-ший элемент и его индекс.
7.3.2. Имеется несколько массивов чисел. В каждом массиве подсчи-тать количество положительных и отрицательных элементов.
7.3.3. Имеется несколько массивов чисел. Упорядочить каждый массив в порядке возрастания элементов.
7.3.4. Имеется несколько одномерных массивов чисел. Для каждого из них построить другой массив, включив только положительные элементы исходного.
7.3.5. Имеется несколько строк символов. Для каждой строки опре-делить два чаще всего встречающихся символа.
7.4. Локальные и глобальные объекты в подпрограммах
Под объектами здесь будем понимать константы, переменные, типы, подпрограммы.
Объекты описываются в блоках. Напомним, что блок состоит из опи-саний и составного оператора. Таким образом, программа - это блок, подпро-грамма - тоже блок.
Любой объект, встречающийся в блоке, может быть локальным или глобальным по отношению к этому блоку.
Объект, описанный в блоке, является локальным по отношению к этому блоку. Иначе: область действия описания объекта - блок, внутри которого он описан. Вне блока описание объекта не действует.
Объект, который не описан в блоке, но описан в охватывающем его блоке, является глобальным. Это значит, что описание объекта действует внутри всех блоков, вложенных в блок с описанием этого объекта. Сказанное поясним с помощью рис.7.2.
блок
A
блок
B
блок
C
блок
D
блок
E
Рис 7.2. Вложенные блоки
Пусть некоторая переменная описана в блоке А. Тогда область ее дей-ствия - все блоки: A,B,C,D,E. У переменной, описанной в блоке В, область действия - блоки В,С, а у переменной, описанной в блоке Е, область дей-ствия только блок Е.
Если одно и тоже имя объекта встречается в описаниях в нескольких блоках, то действует внутреннее описание. Пусть, например, переменная а описана в блоках А,В.Е. Тогда в блоках В,С действует описание блока В, в блоке Е действует описание блока Е, а в блоке D - описание блока А.
Глобальные объекты для подпрограммы - это дополнительный (к списку параметров) канал взаимодействия с охватывающим ее блоком, при-чем, как правило, скрытый. Это часто приводит к трудно обнаруживаемым ошибкам. Наиболее яркий пример: так называемый побочный эффект функций. Пусть функция f(x) в процессе своей работы изменяет значение некоторой глобальной переменной a. Тогда a+f(x) скорее всего не будет равно f(x)+a . Не занимаясь дальнейшим анализом возможных ситуаций, дадим рекомендацию: не использовать в подпрограммах глобальные объекты. Исходные данные подпрограмма должна получать только через параметры, результат работы подпрограммы тоже должен выдаваться через параметры (у процедуры) или через имя функции. Все объекты сугубо "внутреннего" пот-ребления должны быть описаны в подпрограммах как локальные.