Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Руководство по языку Паскаль 1.doc
Скачиваний:
12
Добавлен:
22.04.2019
Размер:
2.48 Mб
Скачать

Глава 10. Программы и модули

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

Синтаксис программ

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

Программа в Borland Pascal состоит из заголовка программы,

необязательного оператора uses и основного блока.

программа

│ ┌─────────┐ ┌───┐ ┌────┐ ┌───┐

└───┬─>│заголовок├──>│ ; ├───┬─────────────────>│блок├─>│ . ├─>

│ │программы│ └───┘ ^ │ ┌───────────┐ ^ └────┘ └───┘

│ └─────────┘ │ └─>│предложение├─┘

└──────────────────────┘ │ uses │

└───────────┘

Заголовок программы

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

Заголовок программы определяет имя программы и ее параметры.

заголовок программы

│ ┌───────┐ ┌─────────────┐

└──>│program├──>│идентификатор├─┬──────────────────────────────>

└───────┘ └─────────────┘ │ ┌───┐ ┌─────────┐ ┌───┐ ^

└─>│ ( ├─>│параметры├─>│ ) ├─┘

└───┘ │программы│ └───┘

└─────────┘

┌───────────────┐

параметры программы ────>│ список ├────>

│идентификаторов│

└───────────────┘

Если заголовок программы присутствует, он является чисто де-

коративной деталью и компилятор его игнорирует.

B.Pascal 7 & Objects/LR - 171 -

Оператор uses

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

Оператор uses идентифицирует все модули, используемые прог-

раммой, включая непосредственно используемые модули и модули, ис-

пользуемые этими модулями.

┌────┐ ┌─────────────┐ ┌───┐

предложение uses ──>│uses├──┬──>│идентификатор├─────>│ ; ├───>

└────┘ │ └─────────────┘ ^ └───┘

│ ┌───┐ │

└─────>│ , ├─────────┘

└───┘

Модуль System всегда используется автоматически. Для под-

держки таких средств, как файловый ввод-вывод, обработка строк,

операции с плавающей запятой, динамическое распределение памяти и

других этот модуль реализует весь нижний уровень, а также обслу-

живающие фоновые программы.

Паскаль, в свою очередь, обслуживает многие стандартные мо-

дули, такие, как Dos и Crt. Это не происходит автоматически: вы

должны обязательно включить их в оператор uses. Например:

uses Dos,Crt; { теперь могут быть доступны средства модулей

Dos и Crt }

Чтобы найти файл, содержащий скомпилированный модуль, компи-

лятор усекает указанное в операторе uses имя модуля до первых

восьми файлов и добавляет расширение файла. Если целевой платфор-

мой является DOS, расширением будет .TPU. Если целевая платформа

- Windows, то расширением файла будет .TPW. Если целевой платфор-

мой является защищенный режим DOS, то расширением файла будет

.TPP. Хотя имена файлов усекаются, в операторе uses должен указы-

ваться полный идентификатор модуля.

B.Pascal 7 & Objects/LR - 172 -

Синтаксис модулей

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

Модули являются основой модульного программирования. Они ис-

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

различные программы (при этом становится необязательным иметь в

наличии исходный код), а большие программы могут подразделяться

на логически связанные модули.

┌─────────┐ ┌───┐ ┌──────────┐

модуль ─────>│заголовок├──>│ ; ├──>│интерфейс-├───┐

│ модуля │ └───┘ │ный раздел│ │

└─────────┘ └──────────┘ │

┌──────────────────────────────────────┘

│ ┌──────────┐ ┌─────────────┐ ┌───┐

└─>│ раздел ├───>│ раздел ├──>│ . ├──>

│реализации│ │инициализации│ └───┘

└──────────┘ └─────────────┘

Заголовок модуля

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

В заголовке модуля определяется имя модуля.

┌────┐ ┌────────────────────┐

заголовок модуля ───>│unit│──>│идентификатор модуля│────>

└────┘ └────────────────────┘

Имя модуля используется при ссылке на модуль в предложении

использования. Это имя должно быть уникальным, так как два модуля

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

Имя исходного файла модуля и двоичного файла должны совпа-

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

Если это не так, то компилятор не сможет найти исходный и/или

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

B.Pascal 7 & Objects/LR - 173 -

Интерфейсная секция

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

В интерфейсной секции описываются те константы, типы, пере-

менные, процедуры и функции, которые являются глобальными, то

есть доступными основной программе (программе или модулю, которые

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

элементам, как если бы они были описаны в модуле, являющимся вло-

женным по отношению к данной программе.

интерфейсная секция

│ ┌─────────┐

└─>│interfaсe├─┬─────────────────────────────────────────────┬─>

│ │ │ ┌───────────┐^ ^ │ ┌──────────────────┐ ^ │

└─────────┘ └─>│ оператор ├┘ │ ├─>│ раздел описания ├─┤ │

│ uses │ │ │ │ констант │ │ │

└───────────┘ │ │ └──────────────────┘ │ │

│ │ ┌──────────────────┐ │ │

│ ├─>│ раздел описания ├─┤ │

│ │ │ типов переменных │ │ │

│ │ └──────────────────┘ │ │

│ │ ┌──────────────────┐ │ │

│ ├─>│ раздел описания ├─┤ │

│ │ │ переменных │ │ │

│ │ └──────────────────┘ │ │

│ │ ┌──────────────────┐ │ │

│ └─>│раздел заголовков ├─┘ │

│ │процедур и функций│ │

│ └──────────────────┘ │

└───────────────────────────┘

раздел заголовков

процедур и функций

│ ┌─────────┐ ┌───┐

└────┬──>│заголовок├──────────>│ ; ├─┬───────────────────────>

│ │процедуры│ ^ └───┘ │ ┌─────────┐ ┌───┐ ^

│ └─────────┘ │ └─>│директива├──>│ ; ├─┘

│ ┌─────────────────┐ │ │ inline │ └───┘

└─>│заголовок функции├─┘ └─────────┘

└─────────────────┘

В том случае, если процедура или функция является процедурой

или функцией типа inline, в интерфейсной секции содержится только

список заголовков процедур или функций. Модуль процедуры или

функции следует дальше в секции реализации. Заметим, что заголо-

вок процедуры или функции может дублироваться и быть здесь таким

же, как в интерфейсной секции. Вам не нужно задавать здесь список

формальных параметров, но если вы это сделали и если описание в

интерфейсной секции и секции реализации не совпадают, то компиля-

тор во время компиляции выдаст сообщение об ошибке.

B.Pascal 7 & Objects/LR - 174 -

Секция реализации

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

В секции реализации определяются модули всех глобальных про-

цедур или функций. В ней также описываются константы, переменные,

процедуры и функции, являющиеся локальными, то есть недоступными

основной программе.

Секция реализации

│ ┌──────────────┐ ┌──────────────────┐

└─>│implementation├─┬──────────────────>│ раздел описаний ├──>

└──────────────┘ │ ┌───────────┐^ └──────────────────┘

└─>│ оператор ├┘

│ uses │

└───────────┘

По механизму действия описания процедур и функций в интер-

фейсная секция аналогична опережающему описанию, хотя директива

forward не указывается. Таким образом, эти процедуры и функции

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

вательности) в секции реализации.

Допускается дублирование заголовков процедур и функций из

интерфейсной части. Вам не нужно при этом задавать список фор-

мальных параметров, но если вы это делаете, компилятор на этапе

компиляции в случае несовпадения описаний в интерфейсной части и

секции реализации будет выдавать сообщение об ошибке.

B.Pascal 7 & Objects/LR - 175 -

Секция инициализации

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

Секция инициализации является последней секцией модуля. Она

может состоять либо из зарезервированного слова end (в этом слу-

чае модуль не содержит кода инициализации), либо из операторной

части, которая должна выполняться для инициализации модуля.

┌───┐

секция инициализации ───┬──>│end├──────────────────>

│ └───┘ ^

│ ┌─────────────────┐ │

└─>│операторная часть├─┘

└─────────────────┘

Секции инициализации модулей, которые используются програм-

мой, выполняются в том же порядке, в каком модули указаны в опе-

раторе uses.

Косвенные ссылки на модули

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

В операторе uses в основной программе должны содержаться

имена всех модулей, непосредственно или косвенно используемых ос-

новной программой. Рассмотрим следующий пример:

Program Prog;

uses Unit1, Unit2

const a = b;

begin

end.

end.

unit Unit2;

interface

uses Unit1;

const b = c;

implementation

end.

unit Unit1;

interface

const c = 1;

implementation

const d = 2;

end;

В данном примере Unit12 непосредственно зависит от Unit1, а

Prog непосредственно зависит от Unit2. Кроме того, Prog зависит

косвенно от Unit1 (через Unit1), хотя ни один из описанных в

Unit1 идентификаторов в Prog не доступен.

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

B.Pascal 7 & Objects/LR - 176 -

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

Поэтому, для компиляции Prog компилятор должен иметь возможность

найти и Unit1, и Unit2, иначе возникнет ошибка.

Когда в интерфейсную часть модуля вносятся изменения, другие

модули, использующие этот модуль, должны быть заново скомпилиро-

ваны. При использовании команд Make или Build компилятор делает

это автоматически. Однако, если изменения коснулись только секции

реализации или секции инициализации, то другие модули, в которых

используется этот модуль, перекомпилировать не нужно. В предыду-

щем примере, если интерфейсная часть модуля Unit1 изменилась

(например, с = 2), то модуль Unit2 нужно перекомпилировать. Изме-

нение же секции реализации (например, d = 1) не требует переком-

пиляции Unit2.

При компиляции модуля в Borland Pascal на основе контрольной

суммы интерфейсной секции вычисляется номер версии модуля. В пре-

дыдущем примере при компиляции модуля Unit2 в скомпилированной

версии модуля Unit2 сохраняется номер версии модуля Unit1. При

компиляции основной программы номер версии модуля Unit1 сравнива-

ется с номером версии, сохраненным в модуле Unit2. Если номера

версий не совпадают, что свидетельствует об изменении в интер-

фейсной части модуля Unit1 со времени последней компиляции модуля

Unit2, компилятор, в зависимости от режима компиляции, выдает со-

общение об ошибке или перекомпилирует модуль Unit2 (в зависимости

от режима компиляции).

B.Pascal 7 & Objects/LR - 177 -

Перекрестные ссылки на модули

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

Размещение в секции реализации оператора uses позволяет

"скрыть" внутренние детали модуля, поскольку используемые в сек-

ции реализации модули оказываются "невидимыми" для того, кто этот

модуль использует. Более важным, однако, является то, что это

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

В следующей программе показаны два модуля, которые "исполь-

зуют" друг друга. Основная программа Circular использует модуль с

именем Display. Модуль Display содержит в своей интерфейсной сек-

ции одну программу WriteXY, которая имеет три параметра: пару ко-

ординат (x,y) и сообщение для вывода на экран. WriteXY перемещает

курсор в точку (x,y) и выводит там сообщение. В противном случае

она вызывает простую программу обработки ошибки.

Пока мы не видим здесь ничего интересного: процедура WriteXY

просто используется вместо процедуры Write. Однако далее, когда

программа обработки ошибки будет выводить сообщение на экран, на-

чинаются перекрестные ссылки (ведь при этом она снова использует

WriteXY). Таким образом, мы имеем процедуру WriteXY, вызывающую

процедуру обработки ошибки SwapError, которая в свою очередь вы-

зывает WriteXY для вывода сообщения на экран. Если у вас уже от

всего этого закружилась голова, не беда. Давайте рассмотрим ис-

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

Основная программа Circular очищает экран и выполняет три

обращения к процедуре WriteXY:

program Circular;

{ выводит текст, используя WriteXY }

uses

WinCrt, Display;

begin

ClrScr;

WriteXY(1, 1, 'Левый верхний угол экрана');

WriteXY(100, 100, 'За пределами экрана');

WriteXY(81 - Lenght('Снова в экран..'), 15,

'Снова в экран..');

end.

Взгляните на координаты (x,y) при втором обращении к проце-

дуре WriteXY. В точке с координатами (100,100) на 80х25-символь-

ном экране вывести текст невозможно. Давайте теперь посмотрим,

как работает процедура WriteXY. Далее приведен текст исходного

кода модуля Display, в котором содержится процедура WriteXY. Если

координаты (x,y) являются допустимыми, она выводит на экран сооб-

щение. В противном случае она выводит сообщение об ошибке.

unit Display;

B.Pascal 7 & Objects/LR - 178 -

{ содержит простую программу вывода информации на экран }

interface

procedure WriteXY(X,Y : integer, Message : string);

implementation

uses

Crt, Error;

procedure WriteXY(X,Y : integer, Message : string);

begin

if (X in [1..80] and Y in [1..25] then

begin

Goto(X,Y);

Write(Message);

end;

else

ShowError('Неверные координаты в процедуре WriteXY');

end;

end.

Процедура ShowError, вызываемая в процедуре WriteXY, показа-

на в приведенном далее исходном коде модуля Error. Она всегда вы-

водит сообщение об ошибке на 25-й строке экрана.

unit Error;

{ содержит простую программу сообщения об ошибке }

interface

procedure ShowError(ErrMsg : string);

implementation

uses

Display;

procedure ShowError(ErrMsg :string);

begin

WriteXY(1,25, 'Ошибка: '+ ErrMsg);

end;

end.

Обратите внимание, что операторы uses в секции реализации

обоих модулей (Display и Error) ссылаются друг на друга. Эти два

модуля могут ссылаться друг на друга в секции реализации благода-

ря тому, что Borland Pascal может для обеих модулей выполнять

полную компиляцию интерфейсных секций. Другими словами, компиля-

тор воспринимает ссылку на частично скомпилированный модуль A в

секции реализации модуля В, если интерфейсные секции модуля A и

модуля В не зависят друг от друга (и, следовательно, строго соб-

B.Pascal 7 & Objects/LR - 179 -

людаются правила Паскаля, касающиеся порядка описания).

В случае взаимозависимости интерфейсных секций модулей вы

получите ошибку из-за перекрестных ссылок.

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

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

Можно модифицировать процедуру WriteXY таким образом, чтобы

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

окно на экране:

procedure WriteXY(SomeWindow : WindRec;

X, Y : integer;

Message : string);

procedure ShowError(Somewindow : WindRec; ErrMsg : string);

Нужно учитывать, что две процедуры находятся в разных моду-

лях. Даже если вы описываете WindData в интерфейсной секции одно-

го модуля, то нет такого допустимого способа, с помощью которого

это описание могло бы быть доступно в другом модуле. Решение сос-

тоит в том, чтобы описать третий модуль, в котором содержится

только определение записи WindRec:

unit WindData;

interface

type

WindRec = record

X1, Y1, X2, Y2 : integer;

ForeColor,

BackColor : byte;

Active : boolean;

end;

implementation

end.

В добавление к тому, что модификация кода процедур WriteXY и

ShowError позволяет использовать новый параметр, в интерфейсной

секции модулей Display и Error теперь может использоваться

WindData. Это допустимо, так как модуль WindData не зависит от

своего оператора uses, а модули Display и Error ссылаются друг на

друга только в соответствующих секциях реализации.

Взаимозависимые модули могут быть полезны в отдельных ситуа-

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

их так, где это не требуется, программу станет сложней обслужи-

вать, и она будет больше подвержена ошибкам.

B.Pascal 7 & Objects/LR - 180 -

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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]