Создание и использование модулей

Цель работы

17.1.1 Познакомиться со структурой модуля;

17.1.2 Разработать, скомпилировать и использовать модуль.

Приборы и оборудование

17.2.1 Free Паскаль

17.2.2 ПЭВМ IBM PC/XT

17.2.3 Microsoft Word

17.2.4 Задание на выполнение работы в электронном варианте.

Порядок выполнения работы

17.3.1 Выполните задания поэтапно согласно описания

17.3.2 Составьте программу, используя язык программирования Free Паскаль

17.3.3 Отладить программу с использованием контрольного примера (значения переменных задайте сами).

17.3.5 Результаты работы распечатайте на принтере.

17.3.5 При оформлении лабораторной работы занесите задание и результат, а также вывод от полученного результата для сдачи преподавателю

Этапы работы

17.4.1 Создание и использование модулей

Модуль - это набор ресурсов (функций, процедур, констант, переменных, типов и т.д.), разрабатываемых и хранимых независимо от использующих их программ.

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

В основе идеи модульности лежат принципы структурного программирования.

Структура модулей

Модуль имеет следующую структуру:

UNIT <имя>;

INTERFACE

<интерфейсная часть>

IMPLEMENTATION

<исполняемая часть>

BEGIN

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

END.

Здесь UNIT - зарезервированное слово (единица); начинает заголовок модуля;

<имя> - имя модуля (правильный идентификатор);

INTERFACE - зарезервированное слово (интерфейс); начинает интерфейсную часть модуля;

IMPLEMENTATION - зарезервированное слово (выполнение); начинает исполняемую часть;

BEGIN - зарезервированное слово; начинает инициирующую часть модуля;

конструкция BEGIN Инициирующая частъ> необязательна;

END - зарезервированное слово - признак конца модуля.

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

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

Заголовок модуля состоит из зарезервированного слова UNIT и следующего за ним имени модуля.

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

Если, например, имеем заголовок

Unit Global;

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

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

Здесь USES - зарезервированное слово {использует);

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

Uses CRT, Graph, Global;

Если объявление USES... используется, оно должно открывать раздел описаний основной программы.

Модули могут использовать другие модули.

Предложение USES в модулях может следовать либо сразу за зарезервированным словом INTERFACE, либо сразу за словом IMPLEMENTATION, либо, наконец, и там, и там (т.е. допускаются два предложения USES).

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

Интерфейсная часть открывается зарезервированным словом INTERFACE.

В этой части содержатся объявления всех глобальных объектов модуля (типов, констант, переменных и подпрограмм), которые должны стать доступными основной программе и/или другим модулям.

При объявлении глобальных подпрограмм в интерфейсной части указывается только их заголовок, например:

Unit Cmplx;

Interface

tуре

complex = record

re, im : real

end;

Procedure AddC (x, у : complex; var z : complex);

Procedure MulC (x, у : complex; var z : complex);

Если теперь в основной программе написать предложение

Uses Cmplx;

то в программе станут доступными тип COMPLEX и две процедуры - ADDC и MULC из модуля CMPLX

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

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

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

Если в интерфейсной части объявляются внешние подпрограммы или подпрограммы в машинных кодах, их тела (т.е. зарезервированное слово EXTERNAL, в первом случае, и машинные коды вместе со словом INLINE - во втором) должны следовать сразу за их заголовками в исполняемой части модуля (не в интерфейсной!). В интерфейсной части модулей нельзя использовать опережающее описание.

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

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

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

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

Unit Cmplx;

Interface

type

complex = record

re, im : real

end;

Procedure AddC (x, у : complex; var z : complex);

Implementation

Procedure AddC;

begin

z.re := x.re +Y.re;

z.im := x.im +y.im

end;

end.

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

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

Инициирующая часть завершает модуль.

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

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

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

Unit FileText;

Interface

Procedure Print(s : string);

Implementation

var

f: text; const

name = 'output.txt'; Procedure Print;

begin

WriteLn(f, s)

end;

{ Начало инициирующей части: }

begin

assign(f, name);

rewrite(f);

{ Конец инициирующей части }

end.

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

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

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

В частности, определены три режима компиляции: COMPILE, MAKE и BUILD. Режимы отличаются только способом связи компилируемого модуля или основной программы с другими модулями, объявленными в предложении USES.

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

Например, если в программе (модуле) имеется предложение Uses Global; то на диске в каталоге, объявленном опцией UNIT DIRECTORIES , уже должен находиться файл GLOBAL.TPU.

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

В режиме МАКЕ компилятор проверяет наличие TPU-файлов для каждого объявленного модуля.

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

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

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

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

Режим МАКЕ, таким образом, существенно облегчает процесс разработки крупных программ с множеством модулей:

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

В режиме BUILD существующие TPU-файлы игнорируются, и система пытается отыскать (и компилировать) соответствующий РAS-файл для каждого объявленного в предложении USES модуля.

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

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

При переходе к очередному модулю система предварительно отыскивает все модули, на которые он ссылается.

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

Например, недопустимы следующие объявления:

Unit A; Unit В;

Interface Interface

Uses В; Uses А;

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

Implementation Implementation

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

end. end.

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

Unit A; Unit В;

Interface Interface

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

Implementation Implementation

Uses B; Uses A;

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

end. end.

Дело в том, что Паскаль разрешает ссылки на частично откомпилированные модули, что приблизительно соответствует опережающему описанию подпрограммы.

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