Мир программирования

 


Найти: на:


Меню
Партнеры
Счетчики
Реклама

ГЛАВА 9. ПРОГРАММЫ И МОДУЛИ


 Предыдущая страница     |     Следующая страница
Добавить в избанное Обсудить в форуме Написать автору сайта Версия для печати

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

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

 программа

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

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

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

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

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

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

[начало] [оглавление]

  

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

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

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

 │

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

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

     └───────┘   └─────────────┘ │  ┌─┐   ┌─────────┐   ┌─┐ °

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

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

                                          └─────────┘

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

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

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

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

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

[начало] [оглавление]

    

Предложение uses.

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

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

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

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

                             │      ┌─┐           │

                             └─────Ў│,├───────────┘

                                    └─┘

      Модуль System   всегда   используется   автоматически.  System реализует весь   нижний   уровень,   поддержку   программ   времени выполнения для  поддержки  таких средств,  как файловый ввод/вывод, обработка  строк,  операции  с  плавающей   запятой,   динамическое распределение памяти и других. Кроме System, Turbo Pascal реализует многие стандартные модули,  такие как Printer,  Dos и Crt.  Они  не используются автоматически:  Вы  должны  обязательно  включить их в предложение uses, например:

      uses Dos, Crt; {теперь получен доступ к средствам Dos и Crt}

      Порядок перечисления модулей  в  uses  определяет  порядок  их инициализации. См. раздел "Раздел инициализации".

[начало] [оглавление]

  

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

      Модули являются   в   Turbo    Pascal    основой    модульного программирования.  Они используются для создания библиотек, которые могут  включаться  в  различные  программы  (при  этом   становится необязательным  иметь в наличии исходный код),  а большие программы могут подразделяться на логически связанные модули.

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

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

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

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

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

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

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

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

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

[начало] [оглавление]

    

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

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

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

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

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

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

[начало] [оглавление]

    

Интерфейсный раздел.

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

 интерфейсный раздел

 │

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

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

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

    └─────────┘ └─Ў│предложение├┘ │ ├─Ў│раздел объявления ├──┤ │

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

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

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

                                  │ ├─Ў│раздел объявления ├──┤ │

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

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

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

                                  │ ├─Ў│раздел объявления ├──┤ │

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      Если процедура  или  функция  не  объявлена  как  inline,   то интерфейсный   раздел   только  перечисляет  заголовки  процедур  и функций. Тела процедур и функций находятся в разделе реализации.

[начало] [оглавление]

    

Раздел реализации.

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

 раздел реализации

 │

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

 └─Ў│implemen-├─┬────────────────────┬─────────────────────────┬─>

    │ tation  │ │  ┌───────────┐ ° ° │  ┌──────────────────┐ ° │                       ° │

    └─────────┘ └─>│предложение├─┘ │ ├─>│раздел объявления ├─┤ │

                   │   uses    │   │ │  │    меток         │ │ │

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

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

                                   │ ├─>│раздел объявления ├─┤ │

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

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

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

                                   │ ├─>│раздел объявления ├─┤ │

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

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

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

                                   │ ├─>│раздел объявления ├─┤ │

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

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

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

                                   │ └─>│раздел объявления ├─┘ │

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

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

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

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

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

[начало] [оглавление]

  

Раздел инициализации.

      Раздел инициализации является последним  разделом  модуля.  Он может  состоять либо из зарезервированного слова end (в этом случае модуль не содержит кода инициализации),  либо из операторной части, которая должна выполняться для инициализации модуля.

                             ┌───┐

раздел инициализации ───┬──>│end├──────────────────>

                        │   └───┘              °

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

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

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

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

[начало] [оглавление]

  

Косвенные ссылки на используемые модули.

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

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

                program Prog;

               uses Unit2;

               const a = b;

               begin

               end.

                unit Unit2;

               interfase

               uses Unit1;

               const b = c;

               implementation

               end.

                unit Unit1;

               interfase

               const c = 1;

               implementation

               const d = 2;

               end.

      В приведенном выше примере Unit2 явно зависит от Unit1, а Prog явно  зависит  от Unit2.  Более того,  Prog неявно зависит от Unit1 (через Unit2),  хотя ни  один  из  идентификаторов,  объявленных  в Unit1, недоступен Prog.

     Чтобы откомпилировать модуль,  Turbo Pascal должен  найти  все модули,  от  которых  этот  модуль зависит (явно или неявно).  Так, чтобы откомпилировать Prog,  компилятор должен найти Unit1 и Unit2, в противном случае произойдет ошибка.

     Когда в интерфейсную часть модуля вносятся  изменения,  другие модули,    использующие    этот    модуль,   должны   быть   заново откомпилированы. Однако,  если изменения коснулись  только  раздела реализации или раздела инициализации,  то другие модули,  в которых используется этот модуль,  перекомпилировать не нужно. В предыдущем примере,  если интерфейсная часть модуля Unit1 изменялась (например С = 2),  то модуль  Unit2  нужно  перекомпилировать.  Изменение  же раздела реализации (например, D=1) не требует перекомпиляции Unit2.

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

[начало] [оглавление]

    

Круговые ссылки модулей.

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

     Следующая программа   показывает,   как   два   модуля   могут "использовать" друг друга. Основная программа, Circular, использует модуль Display.  Display содержит одну программу,  WriteXY, которая имеет три параметра: пару координат (X,Y) и текстовое сообщение для вывода.  Если  точка  с координатами (X,Y) находится на экране,  то WriteXY передвигает курсор в (X,Y) и выводит сообщение, в противном случае она вызывает простую программу - обработчик ошибок.

     До сих пор нет ничего сложного - WriteXY  находится  в  Write. Где   же   здесь   встречается   круговая   ссылка  модулей  и  как программа-обработчик  ошибок  выведет  свое  сообщение  об  ошибке? Использованием  WriteXY  снова.  Таким  образом,  имеется  WriteXY, которая вызывает программу  обработчик  ошибок  ShowError,  которая вызывает WriteXY, чтобы поместить сообщение об ошибке на экран.

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

     Основная программа Circular,  очищает экран и трижды  вызывает WriteXY :

           program Circular;

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

          uses

             Crt, Display;

          begin

             ClrScr;

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

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

             WriteXY(81 - Length('Возврат на экран'), 15,

                                 'Back to reality');

          end.

        Посмотрите на  координаты  (X,Y)  во  втором  вызове  WriteXY. Трудно вывести текст в точке (100,100) на экран 80x25 строк. Далее, давайте посмотрим,  как работает WriteXY.  Приведем исходный  текст модуля Display, содержащий процедуру WriteXY. Если координаты (X,Y) действительны, то он выводит на экран сообщение; в противном случае WriteXY выводит сообщение об ошибке :

           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

                GoToXY(X, Y);

                Write(Message);

             end;

             else

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

           end;

           end.

      Процедура ShowError,    вызываемая     процедурой     WriteXY, объявлена в  модуле Еrror.  ShowError всегда выводит свое сообщение об ошибке на 25 строке экрана :

                unit Error;

               {содержит простую программу-обработчик ошибок}

               interface

               procedure ShowError(ErrMsg: String);

               implementation

               uses

                  Display;

               procedure ShowError(ErrMsg: String);

               begin

                  WriteXy(1, 25, 'Error: ' + ErrMsg);

               end;

               end.

      Заметим, что  предложение uses в разделах реализаций Display и Error ссылаются друг на друга.

     Эти два  модуля могут ссылаться друг на друга в своих разделах реализации, потому что  Turbo  Pascal  может  компилировать  полные разделы interface  для обоих модулей,  другими словами Turbo Pascal допускает ссылку на частично откомпилированный модуль А  в  разделе реализации  модуля  В,  пока  интерфейсные разделы модулей А и В не зависят друг от друга (и это следует строгим правилам  Паскаля  для порядка объявления).

[начало] [оглавление]

    

Разделение других объявлений.

      Предположим, что Вы захотели изменить WriteXY и ShowError так, чтобы ввести дополнительный параметр,  который задает прямоугольное окно на экране :

     procedure WriteXY(SomeWindow: WindRec; X, Y: Integer;

                      Message: String);

    Procedure ShowError (SomeWindow: WindRec;

                         ErrMsg: String);

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

               unit WindData;

               interface

               type

                  WindRec = record

                     X1, Y1, X2, Y2: Integer;

                     ForeColor, BackColor: Byte;

                     Activ: Boolean;

                  end;

               implementation

               end.

     Вдобавок к  модификации   кода   WriteXY   и   ShowError   для использования  нового  параметра,  интерфейсные  разделы  и  модуля Display,  и модуля Error могут теперь "использовать" WindData.  Это стало возможным потому, что модуль WindData не имеет зависимостей в предложении uses,  а модуль Display и Error ссылаются друг на друга только в соответствующих разделах реализации.

[начало] [оглавление]


Предыдущая страница     |     Следующая страница


Добавить в избанное Обсудить в форуме Написать автору сайта Версия для печати

Опрос

Конкурсы
Реклама

 

Web дизайн: Бурлаков Михаил    

Web программирование: Бурлаков Михаил

Используются технологии uCoz