Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ещё одна методичка по ЛО.doc
Скачиваний:
18
Добавлен:
23.03.2016
Размер:
433.15 Кб
Скачать

1.3.4. Блоки и подпрограммы

Используя перечисленные выше средства, уже можно составлять реальные программы. Однако программы решения практических задач обычно довольно велики, и рассмотренные простые языковые средства неадекватно их отражают. В'о-первых, в программе с простой структурой никак не отмечаются отдельные логические единицы, введенные в процессе ее разработки. Поэтому для программ, которые были разработаны с модульной структурой, первоначальная структура теряется в конечном монолитном программном тексте, что делает ее трудной для понимания и сопровождения. Во-вторых, постоянное хранение всех переменных, используемых в программе, неоправданно увеличивает потребности в памяти. Как правило, не все обьекты данных должны быть активными в каждый момент времени работы программы: одни используются в одной части программы, другие -- в другой; поэтому некоторые переменные могли бы быть размещены в одном и том же месте памяти. В-третьих, так как все объекты данных имеют одну и ту же область действия, т.е. они известны во всей программе, им всем должны быть даны различные имена. Поэтому программист вынужден выбирать неестественные имена, затемняя этим смысл программы. В-четвертых, описания объектов данных могут быть текстуально удалены от операторов, которые их обрабатывают, что затрудняет чтение программного текста. И наконец, в тех программах, где сложное действие нужно выполнять в нескольких различных точках, реализующая это действие последовательность операторов должна выписываться заново в каждой точке. При этом напрасно тратятся как место в памяти, так и усилия программиста, это также не способствует повышению ясности программы.

Эти проблемы решаются введением в язык понятий подпрограммы и блочной структуры. Рассмотрим понятие блочной структуры на примере блоков.

Блок -- это программная единица, состоящая из двух частей:

описания всех локальных или внутренних объектов данных (т.е. требуемых только внутри этого блока) и глобальных или внешних объектов данных (т.е. обрабатываемых в этом блоке, но описанных в объемлющих этот блок программных единицах);

описания действий, которые должен выполнить блок.

──────────────────────

П р и м е р 1.6. Описание блока, переставляющего

значения глобальных переменных I и J, с помощью локаль-

ной переменной ТЕМР:

block

TEMP: integer;

use I,J: in out integer;

begin

TEMP:=I;

I:=J;

J:=TEMP;

end block;

────────────────────────

Блок из примера 1. 6 должен быть расположен в том месте программы, содержащей описания переменных 1 и где необходимо произвести перестановку их значений. Для этого вводится временная переменная TEMP, которая используется при перестановке и уничтожается при завершении выполнения этом блока. В конструкции use указано, что в этом блоке будут использоваться (in) и изменяться (out) значения глобальных переменных I и J, т.е. они необходимы как для получения значений из внешней среды, так и для возвращения результатов -- модифицируемые глобальные переменные. Слова in и out можно указывать и по отдельности при спецификации глобальных объектов:

если указано in -- входной глобальный объект (исполызуется только для получения значения из внешней среды), если out -- выходной (инициализируется в этом блоке).

Блок может находится в любом месте программы, где может быть размещен оператор, отличается от других операторов действия лишь тем, что задает целую последовательность действий, используя дополнительные внутренние переменные (поэтому иногда блок называют "составным оператором). При входе в блок создаются все описанные внутри блока локальные объекты данных, затем выполняется последовательность операторов, и после их окончания созданные объекты уничтожаются. Внутри блока можно обрабатывать глобальные объекты данных, однако для этого необходимо указать их в конструкции use в начале блока.

Блоки в той или иной степени решают рассмотренные выше проблемы, связанные со структурой программ. Для выполнения однотипных действий в разных местах служат более сложные и важные программные единицы -- подпрограммы: процедуры и функции. Они существенно улучшают и решение других перечисленных проблем.

Естественное обобщение понятия блока состоит в том, чтобы рассматривать его не как описание непосредственно выполняемых в данном месте операторов, а скорее как описание действия, которое лишь необходимо в какой-то момент выполнить. Можно было бы возбудить требуемое действие, указав его имя в тех местах программы, где требуется выполнить само действие.

Такое описание называется процедурой, а ее возбуждение -- вызовом процедуры. Процедуры являются важнейшим элементом любого языка программирования. Первоначально они были введены только для исключения многократного дублирования одинаковых совокупностей команд. В настоящее время им придается еще большее значение в качестве средства структурирования программы. При последовательном уточнении программы каждое действие высоком уровня может быть обозначено в тексте с помощью вызова процедуры. Далее каждый этап уточнения будет состоять из определения процедур, которые вызывались на предыдущем этапе, возможно, в терминах обращения к процедурам более низкого уровня. Таким образом, программа организуется в виде иерархии определений процедур. Каждая процедура может быть выражена в компактном виде, что делает всю программу более понятной и удобной для сопровождения.

Описание процедуры помещается среди других описаний объемлющей программной единицы, отличается от описания блока тем, что в ее заголовке указывается имя.

Вызов процедуры осуществляется специальным оператором действия -- оператором вызова, который в простейшем случае представляет собой просто указание имени процедуры.

────────────────────

П р и м е р 1.7. Описание процедуры, переставляющей значения глобальных переменных 1 и ~, и ее использование:

block

I,J: integer;

procedure ПЕРЕСТАВИТЬ is -- заголовок

ТЕМР: integer;

begin

ТЕМР:=I;

I:=J;

J:=ТЕМР;

end procedure;

begin

I:=1; J:=2;

-- здесь I=1, J=2

ПЕРЕСТАВИТЬ; -- первый вызов процедуры

-- теперь I=2, J=1

ПЕРЕСТАВИТЬ; -- второй вызов процедуры

-- теперь снова I=1, J=2

end block;

──────────────────

Программа в примере 1. 7, конечно, значительно короче и яснее, чем если бы вместо процедуры использовались блоки.

Главный недостаток процедуры ПЕРЕСТАВИТЬ заключается в том, что из ее вызова явно не видно, значения каких переменных она переставляет. Чтобы узнать это, надо обращаться к описанию процедуры. Таким образом, процедура ПЕРЕСТАВИТЬ неявно взаимодействует со средой, модифицируя глобальные переменные 1 и 3. Как следствие, эту процедуру нельзя применять для перестановки значений других переменных, что, конечно, было бы желательно. Чтобы исправить этот недостаток, используются специальные конструкции -- параметры.

──────────────────────

П р и м е р 1. 8. Описание и использование процеду-

ры с параметрами:

block

I, J, К: integer;

procedure ПЕРЕСТАВИТЬ (M, N: in out integer) is

ТЕМР: integer;

begin

ТЕМР:=M; M:=N; N:=ТЕМР;

end procedure;

begin

I:=1; J:=2; К:=3;

ПЕРЕСТАВНТЬ(I, J); --- здесь I=2, J=1, К=З

ПЕРЕСТАВИТЬ(J, К); --- здесь I=2, J=3, К=1

ПЕРЕСТАВИТЬ(К, I); --- здесь I=1, J=3, К=2

end block;

────────────────────

Прежде всего нужно объяснить способ спецификации параметров. Перед типом параметров стоят слова in и out, которые указывают, что эти параметры используются как для получения значения из внешней среды, так и для возвращения результатов в среду, откуда произошло обращение -- модифицируемые параметры. Эти слова можно указывать и отдельно при описании параметров: если указано in -- параметр входной, если out -- выходной.

Как работает механизм параметров? При вызове процедуры с каждым параметром связывается соответствующий аргумент, указанный в операторе вызова. В примере 1. 8 при первом вызове процедуры ПЕРЕСТАВИТЬ с параметром М связывается переменная I, а с параметром N -- переменная J Дальнейшая обработка идет так, как будто вместо параметров стоят соответствующие аргументы. При окончании работы процедуры связь параметров с аргументами разрывается.

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

──────────────────────

П р и м е р 1.9. Использование процедуры для вы-

числения единственного значения:

block

I, J, К: integer;

ТЕMР1, ТЕMР2, MAX2: integer;

procedure MAX;

(PAR1,PAR2: in integer; REZ out integer) is

begin

if PAR1>PAR2 then

REZ:=PAR1;

else

REZ:=PAR2;

end if;

end procedure;

begin

........

MAX(I, J, TEMP1);

MAX(К, TEMP1, TEMP2);

MAX2:=2*TEMP2;

end block;

В этой программе вычисляется удвоенный максимум из трех чисел, который помещается в переменную MAX2; при этом исполыуются дополнительные переменные TEMP1 и TEMP2.

──────────────────────

Чтобы упростить запись подобных программ, базовый механизм процедур расширяется введением специальной конструкции -- функции. Функция -- это специальная форма процедуры, предназначенная для вычисления одного значения. Для вызова функции, в отличие от процедуры, ее имя нужно записать в виде операнда выражения. Вычисленное функцией значение связывается с именем самой функции, что позволяет обходиться без промежуточных переменных для сохранения выходном значения.

──────────────────────────

П р и м е р 1. 10. Описание и использование функции:

block

I, J, К: integer;

MAX2: integer;

function MAX (PAR1,PAR2: in integer)

return (REZ: out integer) is

begin

if PAR1 > PAR2 then

REZ:=PAR1;

else

REZ:=PAR2;

end if;

end function;

begin

............

MAX2:= 2*MAX(K,MAX(I,J));

............

end block;

──────────────────────────────

Отличие функции в примере 1. 10 от процедуры из примера 1.9 чисто синтаксическое. Так как функция предназначена для вычисления одного значения (т.е. не допускает использования параметров вида out и in out, кроме одного, особо выделенного параметра вида out), то слова in и out в описании параметров можно опускать. Далее будем везде, кроме выходном параметра функций, полагать, что пропуск слов in, out, in out означает описание входного параметра (или входного глобального объекта в блоке), т.е. по умолчанию принимается in.

Часто различные программы связаны между собой: они либо выполняют набор дополняющих друг друга операций, либо обрабатывают одни и те же данные. Поэтому в современных языках программирования введено специальное средство для представления совокупности логически связанных вычислительных ресурсов -- пакеты. Пакеты могут объединять как подпрограммы, так и объекты данных и даже типы данных. Чтобы получить возможность использовать в программе пакет, достаточно указать его имя при описании программы.