ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП |
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы. |
Часть 11 Глава 9. Программы и модули Синтаксис программ Программа в Турбо Паскале имеет такой же вид, как описание процедуры или функции, за исключением заголовка программы и необязательных операторов uses. ЪДДДДДДДДДДДДДДДДДДДї ХНННё ЪДДДДДДДДї программа ДВізаголовок программыГДДі ; ГДДДВДДДґ модуль ГДДДДД і АДДДДДДДДДДДДДДДДДДДЩ ФНННѕ і АДДДДДДДДЩ і і і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДЩ АДДДДДДДї і ЪДДДДДДДДДї і і і операторі і АДДДі uses іДДЩ АДДДДДДДДДЩ Заголовок программы Заголовок программы определяет имя программы и ее параметры. ХНННННННННё ЪДДДДДДДДДДДДДДДї заголовок ДДі program ГДі идентификатор ГДВДДДДДДДДДДДДДДДДДД ФНННННННННѕ АДДДДДДДДДДДДДДДЩ і і і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і і і і ХНННё ЪДДДДДДДДДДДДДДДДДДДДДї ХНННё і АДі ( ГДі параметры программы ГДі ) ГДЩ ФНННѕ АДДДДДДДДДДДДДДДДДДДДДЩ ФНННѕ ЪДДДДДДДДДДДДДДДДДДДДДДДДї параметры программы ДДі список идентификаторов іДДДДДДДДДДДДДД АДДДДДДДДДДДДДДДДДДДДДДДДЩ Если заголовок программы присутствует, он является чисто декоративной деталью и компилятор его игнорирует. Оператор uses Оператор uses идентифицирует все модули, используемые программой, включая непосредственно используемые модули и модули, используемые этими модулями. ХННННННё ЪДДДДДДДДДДДДДДДї ХНННё оператор ДДДДДДі uses ГДДі идентификатор ГДДДВДі ; ГДДДДДД uses ФННННННѕ АДДДДДДДДДДДДДДДЩ і ФНННѕ і ХНННё і АДДДДДДДі , ГДДДДДДДДЩ ФНННѕ Модуль System всегда используется автоматически. Для поддержки таких средств, как файловый ввод-вывод, обработка строк, операции с плавающей запятой, динамическое распределение памяти и других этот модуль реализует весь нижний уровень, а также обслу живающие фоновые программы. Паскаль, в свою очередь, обслуживает многие стандартные модули, такие, как WinDos, WinTypes и WinProcs. Это не происходит автоматически: вы должны обязательно включить их в оператор uses. Например: uses WinTypes, WinProcs; { теперь могут быть доступны средства модулей WinDos и WinProcs } Примечание: См. далее раздел "Секция инициализации". Синтаксис модулей Модули являются в Турбо Паскале основой модульного программирования. Они используются для создания библиотек, которые могут включаться в различные программы (при этом становится необязательным иметь в наличии исходный код), а большие программы могут подразделяться на логически связанные модули. ЪДДДДДДДДДДДДДДДДДДї модуль ДДДі заголовок модуля ГДДДДДДДДДДДї АДДДДДДДДДДДДДДДДДДЩ і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і і ХНННё ЪДДДДДДДДДї ЪДДДДДДДДї ЪДДДДДДДДї АДДі ; ГДДі интер- і і секция і і секция і ХНННё ФНННѕ і фейсная ГДДі реали- ГДДі иници- ГДДДі . ГДД і секция і і зации і і ализа- і ФНННѕ АДДДДДДДДДЩ АДДДДДДДДЩ і ции і АДДДДДДДДЩ Заголовок модуля В заголовке модуля определяется имя модуля. ХННННННё ЪДДДДДДДДДДДДДДДДДДДДДДї заголовок ДДДі unit ГДДі идентификатор модуля ГДДДДДДДДДДДДД модуля ФННННННѕ АДДДДДДДДДДДДДДДДДДДДДДЩ Имя модуля используется при ссылке на модуль в операторе uses. Это имя должно быть уникальным, так как два модуля с одним именем не могут одновременно использоваться. Интерфейсная секция ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД В интерфейсной секции описываются те константы, типы, переменные, процедуры и функции, которые являются глобальными, то есть доступными основной программе (программе или модулю, которые используют данный модуль). Основная программа имеет доступ к эт им элементам, как если бы они были описаны в модуле, являющимся вложенным по отношению к данной программе. интерфейсная секция і ХНННННННННННё і interface ГВДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВДДДД ФНННННННННННѕі і і і і і і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і і і і і ГДДі секция описания констант ГДґ і і і і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і і і і і і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і і ЪДДДДДДДДДДДДЩ і і ГДДі секция описания типов ГДґ і і і і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і і і і і і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і і і і і ГДДі секция описания переменных ГДґ і і і і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і і і ЪДДДДДДДДДДї і і і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДї і і і і оператор і і і АДДі секция заголовков процедур ГДЩ і Аі uses ГДЩ і і и функций і і АДДДДДДДДДДЩ і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ ЪДДДДДДДДДДДї секция заголовков ДВДі заголовок і ХНННё процедур и функций і і процедуры ГДДі ; ГДДДДВДДДДДДДДДДДДДД ЪДДДДДДДДДДДЩ АДДДДДДДДДДДЩ ФНННѕ і і і і і і ЪДДДДДДДДДДДДДДДДДДДДДї і і і АДДі заголовок функции ГДДЩ і і АДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ і і ЪДДДДДДДДДДДДДДДДДї ХНННё і АДДДі директива ГДДі ; ГДДДДДДДЩ і inline і ФНННѕ АДДДДДДДДДДДДДДДДДЩ В том случае, если процедура или функция не является процедурой или функцией типа inline, в интерфейсной секции содержится только список заголовков процедур или функций. Модуль процедуры или функции следует дальше в секции реализации. Секция реализации В секции реализации определяются модули всех глобальных процедур или функций. В ней также описываются константы, переменные, процедуры и функции, являющиеся локальными, то есть недоступными основной программе. секция реализации і ХННННННННННННННННё і implementation ГВДДДДДВДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДВД ФННННННННННННННННѕі і ЪДДДДДДДДДДДДДДДДДДДДДДДї і і і і ГДі раздел описания меток ГДі і ЪДДДДДДДДДДДДДДДЩ і і і АДДДДДДДДДДДДДДДДДДДДДДДЩ і і і і і і ЪДДДДДДДДДДДДДДДДДДДДДДДї і і і і і ГДі раздел описания і і і і і і і і констант ГДі і і ЪДДДДДДДДДДДДДї і і і АДДДДДДДДДДДДДДДДДДДДДДДЩ і і і і оператор і і і і ЪДДДДДДДДДДДДДДДДДДДДДДДї і і Аі uses іДЩ і ГДі раздел описания типов ГДі і АДДДДДДДДДДДДДЩ і і АДДДДДДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДДДДДДДДДДДї і і і ГДі раздел описания і і і і і і переменных ГДі і і і АДДДДДДДДДДДДДДДДДДДДДДДЩ і і і і ЪДДДДДДДДДДДДДДДДДДДДДДДї і і і АДі раздел описания і і і і і процедур и функций ГДДЩ і і АДДДДДДДДДДДДДДДДДДДДДДДЩ і і і АДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДЩ По механизму действия описания процедур и функций в интерфейсная секция аналогична опережающему описанию, хотя директива forward не указывается. Таким образом, эти процедуры и функции могут быть определены (и к ним можно обращаться в любой последова тельности) в секции реализации. Допускается дублирование заголовков процедур и функций из интерфейсной части. Вам не нужно при этом задавать список формальных параметров, но если вы это делаете, компилятор на этапе компиляции в случае несовпадения описаний в интерфейсной части и с екции реализации будет выдавать сообщение об ошибке. Секция инициализации Секция инициализации является последней секцией модуля. Она может состоять либо из зарезервированного слова end (в этом случае модуль не содержит кода инициализации), либо из операторной части, которая должна выполняться для инициализации модуля. ХНННННё секция инициализации ДДВДДДДДДДДДДДДі еnd ГДДДДДДДДДДДДДДДДДД і ФНННННѕ і ЪДДДДДДДДДДДДДДДДДДДДДДДДДДї і АДі операторная часть ГДЩ АДДДДДДДДДДДДДДДДДДДДДДДДДДЩ Секции инициализации модулей, которые используются программой, выполняются в том же порядке, в каком модули указаны в операторе uses. Косвенное использование модулей В операторе uses в основной программе должны содержаться имена всех модулей, непосредственно или косвенно используемых основной программой. Рассмотрим следующий пример: Program Prog; uses Unit1; 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. В данном примере модуль Unit2 непосредственно зависит от Unit1, а Prog непосредственно зависит от модуля Unit2. Кроме того, программа Prog косвенно зависит от модуля Unit1 (через Unit2), хотя ни один из идентификаторов, описанных в Unit2, в Prog нед оступен. Чтобы скомпилировать модуль, Турбо Паскаль должен иметь возможность найти все модули, от которых зависит данный модуль (прямо или косвенно). Поэтому для компиляции приведенной выше программы Prog компилятор должен иметь возможность найти модули Unit 1 и Unit2, в противном случае происходит ошибка. Когда в интерфейсную часть модуля вносятся изменения, другие модули, использующие этот модуль, должны быть заново скомпилированы. Однако, если изменения коснулись только секции реализации или секции инициализации, то другие модули, в которых использ уется этот модуль, перекомпилировать не нужно. В предыдущем примере, если интерфейсная часть модуля Unit1 изменилась (например, с = 2), то модуль Unit2 нужно перекомпилировать. Изменение же секции реализации (например, d = 1) не требует перекомпиляции Un it2. При компиляции модуля в Турбо Паскале на основе контрольной суммы интерфейсной секции вычисляется номер версии модуля. В предыдущем примере при компиляции модуля Unit2 в скомпилированной версии модуля Unit2 сохраняется номер версии модуля Unit1. При компиляции основной программы номер версии модуля Unit1 сравнивается с номером версии, сохраненным в модуле Unit2. Если номера версий не совпадают, что свидетельствует об изменении в интерфейсной части модуля Unit1 со времени последней компиляции модуля Unit2, компилятор, в зависимости от режима компиляции, выдает сообщение об ошибке или перекомпилирует модуль Unit2. Перекрестные ссылки на модули Размещение в секции реализации оператора 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; { содержит простую программу вывода информации на экран } 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) ссылаются друг на друга. Эти два модуля могут ссылаться друг на друга в секции реализации благодаря тому, что Турбо Паскаль может для обеих модулей выполнять п олную компиляцию интерфейсных секций. Другими словами, компилятор Турбо Паскаля воспринимает ссылку на частично скомпилированный модуль A в секции реализации модуля В, если интерфейсные секции модуля A и модуля В не зависят друг от друга (и, следовательн о, строго соблюдаются правила Турбо Паскаля, касающиеся порядка описания). Совместное использование описаний Можно модифицировать процедуру 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 ссылаются друг на друга только в соответствующих секциях реализации. |