Заголовок модуля и связь модулей друг с другом

Заголовок модуля состоит из зарезервированного слова UNIT и следующего за ним имени модуля. Здесь же могут присутствовать директивы компилятору, дающие общие установки/соглашения для всего модуля. Для правильной работы среды Турбо Паскаля и возможности подключения средств, облегчающих разработку крупных программ, это имя должно совпадать с именем дискового файла, в который помещается исходный текст модуля. Если, например, имеем заголовок

UNIT Triangle;

то исходный текст соответствующего модуля должен размещаться в дисковом файле TRIANGLE.РАS. Имя модуля служит для его связи с другими модулями и основной программой. Эта связь устанавливается специальным предложением

USES <список модулей>

где USES - зарезервированное слово;

<список модулей> - список модулей, с которыми устанавливается связь; элементами списка являются имена модулей, отделяемые друг от друга запятыми, например:

USES CRT, Grahy, Printer, Triangle;

Интерфейсная часть

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

Исполняемая часть

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

Описанию подпрограммы, объявленной в интерфейсной части модуля, в исполняемой части должен предшествовать заголовок, в котором можно опускать список формальных переменных (и тип результата для функции), так как они уже описаны в интерфейсной части. Но если заголовок подпрограммы приводится в полном виде, т.е. со списком формальных параметров и объявлением результата, он должен совпадать с заголовком, объявленным в интерфейсной части.

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

Инициирующая часть

Инициирующая часть завершает модуль. Она может отсутствовать вместе с начинающим ее словом BEGIN или быть пустой - тогда за BEGIN сразу следует признак конца модуля END.(с точкой).

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

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

В приведенном ниже примере использования модуля раздел инициализации отсутствует, так как в нем нет необходимости.

Разработка примера модуля

Пример 5.1. Построить модуль Triangle, который можно использовать в разных программах для определения параметров заданного треугольника: площади S, периметра Р, радиусов Rv и Ro вписанной и описанной окружностей. При этом должны быть реализованы четыре варианта исходных данных:

а) заданы три стороны А, В, С;

b) заданы координаты вершин а, b, с треугольника (6 координат);

с) заданы две стороны А, В и угол между ними;

d) задана сторона А и прилежащие углы.

Соответствующие вариантам a – d процедуры обозначим TR_a, TR_b, TR_c, TR_d. Запишем заголовок модуля и интерфейсный раздел.

 

UNIT TRIANGLE;

INTERFACE

Procedure TR_a (A,B,C:Real;Var S,P,Rv,Ro:Real);

Procedure TR_b (Xa,Ya,Xb,Yb,Xc,Yc:Real; Var S,P,Rv,Ro:Real);

Procedure TR_c (A,B,Ugol:Real; Var S,P,Rv,Ro:Real);

Procedure TR_d (A,Ugol1,Ugol2:Real; Var S,P,Rv,Ro:Real);

{Ниже следует раздел выполнения, использующий известные формулы}

IMPLEMENTATION

Procedure TR_a; {Не нужно повторять описание параметров, если}

Begin {оно было дано в интерфейсном разделе модуля}

Р := (А + В+ 0/2; {Определим Р - полупериметр}

S := Sqrt (Р*(Р-А)*(Р-В)*(Р-0); {Определим S - площадь}

Rv:= S/P; Ro:= A*B*C/(4*S); {Определим окружности Rv и Ro}

Р:= 2*Р; {Вычислим периметр}

End;

Function R(X1,Y1,X2,Y2:Real):Real; {Расстояние между 2 точками}

Begin R:= Sqrt(Sqr(X1-X2) + Sqr(Y1-Y2)) End;

Procedure TR_b:

Var A,B,C:Real;

Begin A:= R(Xa,Ya,Xb,Yb); {Определение длины стороны A}

B:= R(Xa,Ya,Xc,Yc); {Определение длины стороны В}

С:= R(Xb,Yb,Xc,Yc); {Определение длины стороны С}

TR_a(A,B,C,S,P,Rv,Ro) {Обращение к блоку TR_a для}

End; {получения всех искомых величин}

Procedure TR_c;

Var С: Real;

Begin

C:=Sqrt(Sqr(A)+Sqr(B)-2*A*B*Cos(Ugol));

TR_a(A,B,C,S,P,Rv,Ro); {Обращение к блоку TR_a}

End;

Procedure TR_d;

Var B,C,D:Real;

Begin

D:=Sin(pi-UgoH-Ugol2);

B:=A*Sin(Ugol1)/D; {Используем теорему синусов}

C:=A*Sin(Ugol2)/D;

TR_a(A,B,C,S,P,Rv,Ro); {Обращение к блоку TR_a}

End; {После описания конечного блока точка с запятой обязательна}

END. {Закрывающая скобка модуля}

 

Все четыре варианта вычисления сводятся к операторам, записанным в процедуре TR_a, и в трех случаях предварительно вычисляются недостающие длины сторон треугольника, которые являются локальными переменными, ибо нужны лишь на время работы процедур. В процедуре TR_b используется функция R, вычисляющая расстояние между двумя любыми заданными точками. Функция R скрыта от пользователя: ее заголовок отсутствует в интерфейсном разделе. Поэтому блок R является локальным, местного значения. Блоки TR_a и R размещены так, чтобы в разделе реализации на них можно было ссылаться: сначала идут эти блоки, а ниже - блоки, обращающиеся к ним. Если вы захотите сделать функцию R доступной и для основной программы, занесите заголовок функции R в интерфейсный раздел.

Пример 5.2.Запишем программу, которая с помощью блока из модуля Triangie определяет, какой из двух треугольников abc или def, заданных координатами вершин, имеет наибольшее отношение площади к периметру. Вывод сообщения об этом производится на принтер.

 

Program Treug; {Заголовок программы обязательно}

Uses Triangle, Printer; {должен быть перед USES !!}

Var Xa,Ya,Xb,Yb,Xc,Yc,Xd,Yd,Xe,Ye,Xf,Yf: Real;

Sabc,Pabc,Sdef,Pdef,Rv,Ro: Real;

BEGIN

Writeln (‘Введите значения координат’);

Readln (Xa,Ya,Xb,Yb,Xc,Yc,Xd,Yd,Xe,Ye,Xf,Yf);

{Здесь программист должен записать операторы для контроля значений}

{исходных данных - координат вершин треугольника}

Write (Lst,’Максимум отношения площадь/периметр’);

Write (Lst, ‘у треугольника’); {Разделена длинная строка}

TR_b (Xa,Ya,Xb,Yb,Xc,Yc,Sabc,Pabc,Rv,Ro);

TR_b (Xd,Yd,Xe,Ye,Xf,Yf,Sdef,Pdef,Rv,Ro);

If (Sabc/Pabc > Sdef/Pdef) Then Writein (Lst, ‘def)

END.

Примечание. Результаты Rv и Ro не нужны, но нельзя сокращать список параметров в процедуре.

Компиляция модулей

В среде Турбо Паскаля имеются средства, управляющие способом компиляции модулей и облегчающие разработку крупных программных проектов. Результатом компиляции модуля является файл с тем же именем и расширением имени .TPU, который заносится на диск, тогда как результат компиляции программы в целом (ЕХЕ-файл) может оставаться в основной памяти. При его получении проверяется правильность обращения к блокам модуля (вот для чего нужна интерфейсная часть).

Общий объем модульной программы может быть много более 64 кбайт, но каждый .TPU-файл не может превышать 64 кбайт. Вызовем подменю COMPILE:

 

Compile Alt-F9

Make F9

Build

Destination Memory/Disk

Primary file ...

 

Здесь первые три режима - это режимы компиляции. Они отличаются только способом связи компилируемого модуля или основной программы с другими модулями, объявленными в предложении USES.

При компиляции модуля или основной программы в режиме COMPILE все упоминавшиеся ранее модули в предложении USES должны быть предварительно откомпилированы и помещены в одноименные файлы с расширением TPU.

Если в программе (см. пример 5.2) имеется предложение

USES Triangle, Printer;

где Printer - стандартный модуль, то на диске в каталоге, объявленном опцией UNIT DIRECTORIES, уже должен находиться файл TRIANGLE.TPU. Этот файл создается автоматически в результате компиляции модуля.

В режиме MAKE компилятор проверяет наличие файлов с расширением .TPU для каждого объявленного модуля. Если файл-TPU не обнаружен, то система ищет подобный файл с расширением PAS, т.е. файл с исходным текстом модуля, и при его обнаружении компилирует его. В режиме MAKE система следит за возможными изменениями исходного текста модуля. Если в текст модуля были внесены какие-либо изменения, то система заново его компилирует и только затем приступает к компиляции основной программы. Кроме того, если были внесены изменения в интерфейсную часть модуля, то будут перекомпилированы также и все другие модули, обращающиеся к нему. Таким образом, автоматизация контроля компиляции позволяет значительно снизить нагрузку на программиста при разработке крупных программ с множеством модулей.

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

 

Unit A; Unit В;

Interface interface

Uses В; Uses A;

... ...

Implementation implementation

End. End.

 

Это ограничение можно обойти, если “спрятать” предложение USES в исполняемые части зависимых модулей:

 

Unit A; Unit В;

Interface Interface

... ...

Implementation Implementation

Uses В; Uses A:

... ...

End. End.

 

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