Внешний библиотечный модуль.
unit MyLibr; { имя библиотечного модуля }
interface { --- секция интерфейса --- }
procedure Push(const arg : string); { заголовок процедуры }
function Pop(var arg : string): boolean; { заголовок функции }
{- – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – - – -}
implementation { --- секция реализации --- }
type PRec = ^TRec; { Тип указатель на запись }
TRec = record { Тип запись для хранения связанных строк }
mStr : string; { хранимая строка }
mNext : PRec; { указатель на следующую запись }
end;
var Stack : PRec; { Голова стека }
{ Процедура размещения строки в стеке }
procedure Push(const arg : string);
var p : PRec;
begin
New(p); { создаем новую переменную-запись }
p^.mStr:= arg; { размещаем строку }
{ размещаем в голове стека }
p^.mNext:= Stack; { указатель на предыдущую запись }
Stack:=p; { текущая запись в голове стека }
end;
{ Процедура извлечения строки из стека }
function Pop(var arg : string): boolean;
var p : PRec;
begin
Pop:= Assigned(Stack); { Если стек не пуст, то TRUE }
{ Если стек не пуст… }
if Assigned(Stack) then begin
arg:= Stack^.mStr; { извлекаем данные из головы стека }
p:= Stack; { временно копируем указатель на голову }
Stack:= Stack^.mNext; { переключаем голову на следующий элемент }
Dispose(p); { удаляем ненужный элемент }
end
end;
begin { --- секция инициализации модуля --- }
Stack:= nil; { Инициализация стека пустым значением }
end.
Теперь в интерфейсной части модуля маячат лишь процедура Push и функция Pop. Первичный файл проекта с главной программой станет таким.
{ P_59_1 – Первичный файл проекта }
uses MyLibr;
var F : text; S : string;
begin {--- Главная программа ---}
{ Открываем входной файл }
Assign(F, 'P_56_1.pas'); Reset(F);
{ Пока не конец файла, читаем строки и помещаем в стек }
while not Eof(F) do begin
Readln(F, S); Push(S);
end;
Close(F);
{ Открываем выходной файл }
Assign(F, 'P_56_1.out'); Rewrite(F);
{ Пока стек не пуст, извлекаем и печатаем строки }
while Pop(S) do Writeln(F, S);
Close(F);
end.
Откомпилируйте проект, запустите и проверьте, жива ли распиленная «дамочка»?
Структура модуля
Обретя первый опыт модульного программирования, воспарим над частностями и окинем взглядом всю модульную технологию.
Прежде всего, уточним структуру модуля. Из рис. 148 следует, что она схожа со структурой программы. В состав модуля, по мере необходимости, включаются те же самые персонажи: константы, типы данных, переменные, процедуры и функции. Все это может располагаться в одной из двух секций. То, что требует экспорта, выставляют напоказ в секции интерфейса, а остальное прячут в секции реализации. Что касается процедур и функций, то в секцию интерфейса выносят при необходимости лишь копии их заголовков, а сами подпрограммы поселяют в секции реализации. Константы, типы и переменные, объявленные в секции интерфейса, в секции реализации не повторяют.
О совпадении имен
Настало время ответить на отложенный вопрос: зачем прятать часть модуля, почему бы не выставить все напоказ? На это есть две причины, и обе веские.
Первая причина такова. Большие программы собирают из десятков библиотечных модулей, их создают разные люди, каждый из которых выбирает названия для своих объектов на свой вкус, не советуясь с другими. Если все эти имена сделать видимыми за пределами модуля, то некоторые из них совпадут и учинят невероятную путаницу.
Компилятор ищет идентификаторы сначала в текущем файле, а если их там нет, то в модулях из списка импорта USES. Причем перебирает модули в том порядке, в котором они перечислены. Есть вероятность, что вместо переменной, объявленной в одном модуле, компилятор наткнется на процедуру или функцию с тем же именем в другом модуле. Это может быть воспринято как ошибка и программа не скомпилируется.
Но хуже, если программа скомпилируется! В этом состоит вторая причина сокрытия лишних имен. Если компилятор найдет искомое, но не в том модуле, в котором вы предполагали – то-то будет морока с отладкой!
Отсюда вывод: не выставляйте напоказ ничего лишнего, будьте скромнее, – так поступают профессионалы. И все же полностью исключить нежелательное совпадение имен удается не всегда. Как быть? Выход есть – используйте префикс с именем модуля. Префикс – это приставка перед идентификатором, отделяемая от него точкой. Например, в главной программе нашего проекта вызовы процедур можно записать так:
MyLibr.Push(S);
while MyLibr.Pop(S) do...
Этим мы подсказали компилятору, что процедуры Push и Pop берутся из модуля MyLibr и боле ниоткуда.
Рис.148 – Общая структура библиотечного модуля
Модуль, указанный в префиксе, должен упоминаться в списке USES. Но есть одно исключение – это модуль по имени SYSTEM. В этом библиотечном модуле собраны процедуры и функции, встроенные в Паскаль. Модуль SYSTEM в списке USES никогда не упоминают.
Иногда программисты называют свои процедуры и функции так же, как встроенные в модуль SYSTEM, – это не запрещено. И тогда для уточнения имен пользуются префиксами с именами библиотек, например:
System.Writeln(F); { стандартная процедура }
MyModule.Writeln(S); { моя «самоделка» }
Завершая обзор структуры модуля, обратим внимание на необязательные списки импорта USES в секциях интерфейса и реализации (рис. 148). Через эти списки библиотечный модуль импортирует нужные ему элементы из других модулей. Составляя списки, следуйте простому правилу: если внешний модуль требуется только в секции реализации, упоминайте его в списке USES секции реализации, а иначе – в секции интерфейса. Упоминать модуль в обоих списках нельзя. А когда импортировать нечего, список импорта не вставляют.
Сборочный цех
Оглядев структуру модуля, войдем теперь в сборочный цех IDE и рассмотрим порядок соединения модулей в единую программу – исполняемый файл.
Рис. 149 – «Цех» компиляции и сборки проекта
Перед сборкой проекта все входящие в него библиотечные модули компилируются, в результате получаются файлы, расширения которых зависит от используемого компилятора. Так, для Borland Pascal файлы получат расширение TPU (это сокращение от «Turbo Pascal Unit»). Для Free Pascal это будут пары файлов с расширениями O и PPU. Модули можно компилировать как по отдельности, так и вместе со всем проектом. Рассмотрим оба случая.
Для компиляции отдельного модуля откройте его в редакторе и нажмите сочетание Alt+F9, или выберите пункт меню Compile –> Compile. Компилятор выполнит свою обычную работу по проверке ошибок и, при отсутствии таковых, сформирует библиотечный файл. На экране появится сообщение об успешной компиляции (рис. 150).