9741

Общая структура модуля в языке Turbo Pascal

Реферат

Информатика, кибернетика и программирование

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

Русский

2013-03-15

335.5 KB

14 чел.

Модули

Введение

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

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

С этой точки зрения, введение понятия модуля в Turbo Pascal, которое было проведено, начиная с 4-ой версии системы, явилось решающим шагом на пути его превращения в язык, пригодный для крупных разработок производственного и коммерческого назначения на современном уровне технологии программирования. Стал возможным современный стиль реализации программных пакетов различного назначения и ориентации, легко подключаемых к любой программе. Кроме того, за счет введения модулей удалось ослабить ограничения на суммарный объем готовых программ.

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

Общая структура модуля

В языке Turbo Pascal модуль (unit) по определению считается отдельной программой. Если подпрограмма является структурным элементом Pascal-программы и не может существовать вне ее, то модуль представляет собой отдельно хранимую и независимо компилируемую единицу. С учетом этого факта можно дополнить рассмотрение общей структуры Pascal-программы следующей синтаксической диаграммой для случая языка Turbo Pascal:

Программа на языке Turbo Pascal

В самом общем виде модуль представляет собой совокупность (коллекцию) программных ресурсов, предназначенных для использования другими модулями и программами. Под ресурсами в данном случае понимаются любые программные объекты языка Turbo Pascal - константы, типы, переменные, подпрограммы. Важно понимать, что модуль сам по себе не является выполняемой программой - его объекты ИСПОЛЬЗУЮТСЯ другими программными единицами.

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

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

Заголовок модуля составляется из служебного слова unit и следующего за ним идентификатора, являющегося именем модуля. Заголовок завершается символом ';' (точка с запятой). Интерфейсная часть начинается со служебного слова interface, за которым следует совокупность обычных описаний. Часть реализации начинается служебным словом implementation, за которым идут описания скрытых объектов. Завершает модуль, как и программу, служебное слово end и символ '.' (точка).

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

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

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

unit Calendar;

interface

 type

Days = (Mon,Tue,Wed,Thu,Fri,Sat,Sun);

WorkingDays = Mon..Fri;

Months = (Jan,Feb,Mar,Apr,May,June,

         July,Aug,Sept,Oct,Nov,Decem);

Summer = June..Aug;

Autumn = Sep..Nov;

Spring = Mar..May;

DayNo = 1..31;

YearNo = 1900..2000;

Date = record

      Day : DayNo;

      Month : Months;

      Year : YearNo

end;

implementation

end.

Данный модуль, ввиду своей простоты, не содержит разделов реализации и инициализации. Механизм использования модулей в других программах будет описан далее.

14.3    Подпрограммы в модулях

Процедуры и функции могут использоваться в модулях наравне с другими Pascal-объектами. Однако для них имеются особенности, обусловленные их структурой. Как уже отмечалось, заголовок подпрограммы содержит всю информацию, необходимую для ее вызова: ее имя, количество и типы параметров и (для функций) тип результата. С другой стороны, тело подпрограммы содержит блок, раскрывающий ее алгоритм. Можно считать, что заголовок подпрограммы является ее интерфейсом, а тело - реализацией. В соответствии с этой точкой зрения в интерфейсной части модуля должны быть представлены только ЗАГОЛОВКИ процедур и функций, видимые (доступные) для других программ (аналогично предварительным описаниям, но без служебного слова forward), а их полные описания будут содержаться в разделе реализации. При этом полное описание подпрограммы может иметь СОКРАЩЕННЫЙ заголовок, состоящий только из служебного слова procedure или function, имени подпрограммы и символа ';'. (Разумеется, можно повторить полный заголовок подпрограммы, но тогда он должен быть точно таким же, как и заголовок в интерфейсной части).

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

unit CmplVals;

interface

 type

   Complex = record { способ представления
                      комплексных чисел   }

                Re, Im : real

             end;

 { Заголовки процедур, реализующих

   операции над комплексными числами }

 procedure InitC (R,I:real; Var C:Complex);

 procedure AddC (Cl,C2:Complex;var R:Complex);

 procedure MultC (Cl,C2:Complex;var R:Complex);

 procedure DivC (Cl,C2:Complex;var R:Complex);

 procedure WriteC(C:Complex);

implementation

 { Полные описания процедур

   (с сокращенными заголовками) }

 procedure InitC;

 begin

   with C do

   begin

     Re:=R; Im:=I

   end

 end;

 procedure AddC;

 begin

   with R do

   begin

     Re := Cl.Re + C2.Re;

     Im := Cl.Im + C2.Im

   end

 end;

 procedure MultC;

 begin

   with R do

   begin

     Re := Cl.Re*C2.Re+Cl.Im+C2.Im;

     Im := Cl.Im*C2.Re+Cl.Re*C2.Im

   end

 end;

 procedure DivC;

 var

    Tmp : real;

 begin

   with C2 do Tmp:=Re*Re+Im*Im;

   with R do

   begin

     Re := (Cl.Re*C2.Re+Cl.Im*C2.Im)/Tmp;

     Im := (C2.Re*Cl.Im+Cl.Re*C2.Im)/Tmp

   end

 end;

 procedure WriteC;

 begin

   with С do

   begin

     Write(Re);

     if Im=0 then Exit;

     if Im>0 then Write(’+’);

     Write(Im);

     Write('i')

   end

 end;

end.

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

предоставив в распоряжение использующих программ строго определенную совокупность интерфейсных объектов. Если необходимо, например, расширить модуль CmplVals введением новых процедур или изменить реализацию какой-либо процедуры, то если интерфейс модуля при этом останется неизменным, такая модификация НИКАК НЕ ОТРАЗИТСЯ на использующих программах.

Компиляция и использование модулей

Модуль компилируется точно таким же образом, как и обычные подпрограммы; возможна компиляция из интегрированной среды или с помощью компилятора командной строки. Но так как модуль не является непосредственно выполняемой единицей, то в результате его компиляции образуется дисковый файл с расширением .TPU (Turbo Pascal Unit), при этом имя файла берется из имени файла с исходным текстом модуля.

Для того, чтобы получить доступ к интерфейсным объектам модуля, необходимо указать в программе имя нужного ТРU-файла. Соответствующая конструкция называется спецификацией используемых модулей и имеет следующий общий вид:

uses U1, U2, U3;

где uses - служебное слово, U1, U2, - идентификаторы используемых модулей. Эта спецификация должна идти непосредственно после заголовка программы; если некоторый модуль использует объекты другого модуля, то такая спецификация должна следовать сразу после служебного слова interface.

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

Следующий пример иллюстрирует использование модуля CmplVals:

program DaingComplex;

uses

 CmplVals;

var

 C1, C2, C3 : Complex;

begin

 InitC(1,2,C1);    InitC(3,4,C2);

 MultC(C1,C2,C3);  WriteC(C3);

 DivC(C1,C2,C3);   WriteC(C3)

end.

Необходимо особо отметить следующие важные моменты, связанные с использованием модулей:

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

Таким образом, идентификаторы внешнего блока программы будут "экранировать" одноименные идентификаторы модулей А и В; аналогично, идентификаторы модуля А будут перекрыты одноименными идентификаторами модуля В.

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

unit А;

interface

 var

   X:real;

implementation

  ...

end.

Далее, пусть программа, использующая этот модуль, также содержит переменную X:

program Р;

uses А;

var  X : integer;

begin

 ...

end.

Для того чтобы в программе Р иметь доступ к интерфейсной переменной X из модуля А, необходимо задать составное имя, структура которого похожа на селектор поля записи:

А.Х

Здесь А - имя модуля, X - идентификатор его интерфейсной переменной. В этом случае конфликт имен снимается, так как простое указание имени X будет означать обращение к соответствующей переменной из программы Р, например: А.Х := Round(X);

2. Возможны случаи косвенных использований. Например, пусть имеются два модуля:

unit A;

interface

 . . .

end.

unit B;

interface

 uses A;

 . . .

end.

Если некоторая программа использует модуль B, то в соответствующей спецификации использования необходимо указать только модули, НЕПОСРЕДСТВЕННО используемые в программе. В данном примере достаточной является следующая спецификация:

program P;

uses В;

 . . .

end.

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

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

unit A;

interface

 uses B;

 . . .

end.

unit B;

interface

 uses A;

 . . .

end.

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

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

Компиляция модулей: TPU-файлы

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

В отличие от программ, заголовок модуля несет семантическую нагрузку, так как программа или другой модуль, использующие данный, могут ссылаться на него в uses-спецификации. С другой стороны, при трансляции программы, использующей модули, компилятор должен каким-то образом отыскать коды этих модулей, чтобы подключить их к компилируемой программе. Поэтому принято за правило, что имя файла, содержащего исходный текст модуля, должно совпадать с именем этого модуля (расширение имени файла при этом несущественно, но по умолчанию предполагается .PAS). Компилятор помещает код модуля, полученный в результате трансляции, в файл с таким же именем и расширением .TPU. При трансляции же программы, использующей этот модуль, компилятор ищет ТРU-файл с именем, заданным в uses-спецификации, и связывает его с кодом программы. Таким образом, в спецификации использования фактически задаются не имена модулей, а имена файлов, их содержащих.

Например, для спецификации

uses MyUnit;

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

unit MyUnit;

Если все-таки необходимо хранить код модуля в файле с другим именем, то можно использовать директиву $U для переопределения имени файла. Эта директива имеет параметр, который трактуется как "настоящее" имя файла с данным модулем. Она должна находиться непосредственно перед именем модуля в спецификации использования. Например, конструкция

uses {$U MY) MyUnit;

приведет к тому, что компилятор будет искать код модуля MyUnit в дисковом файле MY. TPU.

Компиляция: поиск модулей.
Файл
TURBO.TPL

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

1) Компилятор просматривает содержимое системного библиотечного файла модулей TURBO.TPL (Turbo Pascal Library). Этот файл будет кратко описан далее в этом разделе.

2) Если искомый модуль не найден в файле TURBO. TPL, то компилятор осуществляет поиск соответствующего TPU-файла в ТЕКУЩЕМ каталоге.

3) Если в текущем каталоге нужный файл не найден, то поиск продолжается в каталогах, заданных в альтернативе Options/ Directories/Unit Directories для интегрированной среды или в параметре /U вызова ТРС–компилятора.

4) Если на предыдущих шагах файл не найден, то компилятор прекращает работу и выдает диагностическое сообщение об ошибке.

5) Если компилятор активизирован посредством альтернатив Compile/Make или Compile/Build, то вышеуказанные шаги проводятся в поисках ИСХОДНЫХ ТЕКСТОВ используемых модулей, которые будут оттранслированы перед трансляцией самой программы. При этом подразумевается, что имя файла с текстом модуля совпадает с именем модуля и имеет расширение .PAS.

Как было указано, первый шаг компилятора при поиске используемых модулей состоит в анализе системного файла TURBO.TPL. Этот файл имеет специальную структуру и предназначен для компактного хранения и быстрого доступа к наиболее часто используемым модулям. Обычно в этом файле содержатся несколько системных (стандартных) модулей, однако с помощью специальной служебной программы TPUMOVER можно произвольным образом конструировать файл TURBO.TPL, включая в него нужные модули и удаляя неиспользуемые.

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

Стандартные модули

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

SYSTEM

DOS

CRT

PRINTER

OVERLAY

GRAPH

TORBO3

GRAPHS

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

Каждый модуль хранится в одноименном TPU-файле в системном каталоге Turbo Pascal. Кроме того, обычно модули System, Dos, Crt, Printer и Overlay входят в состав системного библиотечного файла TURBO. TPL. Для того, чтобы воспользоваться ресурсами стандартного модуля, необходимо указать его имя в спецификации использования по обычным правилам. Исключение сделано для модуля System, имя которого можно не указывать, так как содержащиеся в нем ресурсы подключаются автоматически к любой программе.

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

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

Модуль Dos содержит средства доступа к операционной системе и по существу является программным представлением системного интерфейса MS-DOS.

Модуль Crt обеспечивает практически полный спектр возможностей для доступа к экрану дисплея в текстовом режиме. Кроме того, в данный модуль включены средства чтения информации с клавиатуры (включая расширенные коды клавиш) и простейшего управления звуком.

Модуль Printer содержит единственный интерфейсный элемент - переменную Lst стандартного типа text, системно связанную с логическим устройством PRN (то есть с печатающим устройством, если оно имеется в конфигурации). Использование этой переменной в стандартных процедурах Write и WriteLn приводит к выводу информации на печать.

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

Модуль Graph объединяет многочисленные программные средства управления графическим режимом работы дисплея. Данный модуль обеспечивает использование всех возможностей наиболее распространенных типов дисплейных адаптеров - CGA, EGA, VGA, Hercules и т.п. как для монохромных, так и для цветных дисплеев, и позволяет создавать разнообразные и эффективные графические программы.

Модули Turbo3 и Graph3 обеспечивают совместимость с данной версией системы Turbo Pascal тех программ, которые были разработаны для ранней версии 3.0.

Пример модуля

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

unit StackOps; { Операции над стеком целых }

interface

 procedure Push ( Elem:integer );

 function Pop : integer;

 function Empty : boolean;

 function Full : boolean;

implementation

 { Стек реализован в виде линейного массива элементов;

   переменная Тор отмечает текущую вершину стека }

 const

   Мах = 100;

 var

   Stack array[1..Max] of integer;

   Top : integer;

procedure Push;  { помещение элемента в вершину стека }

begin

 if Top>Max then Exit;

 Stack[Top] := Elem;

 inc(Top)

end;

function Pop;  { извлечение элемента из вершины стека }

begin

 Рop := 0 ;

 if Top=1 then Exit;

 dec(Top);

 Pop := Stack[Top]

end;

function Empty;  { проверка на пустоту стека }

begin

 Empty := (Top=1)

end;

function Full;   { проверка на заполненность стека }

begin

 Full := (Тор>Мах)

end;

begin

 { инициализация: первоначально стек пуст }

 Тор := 1

end.

Синтаксические диаграммы

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

Программа

Модуль

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

Интерфейс модуля

Спецификация использования

Элемент интерфейса

Реализация модуля

Элемент реализации

Инициализация модуля


 

А также другие работы, которые могут Вас заинтересовать

40286. Лечение алкогольных психозов 27 KB
  Лечение: 1 детоксикация применение поливидона декстрана70 декстрана40 препаратов трисоль и хлосоль изотонического раствора хлорида натрия раствора Рингера внутривенно капельно или 5 раствора глюкозы капельно по 500 1000 мл; 25 раствора сульфата магния 5 10 мл внутривенно с 10 раствором глюкозы капельно; тиосульфата натрия хлорида кальция внутривенно унитиола 5 10 мл внутримышечно; 2 немедикаментозная детоксикация очистительная клизма плазмаферез гипербарическая оксигенация поверхностная церебральная...
40287. Лечение инфекционных психозов 26 KB
  При начальных или стертых субпсихотических расстройствах показано применение транквилизаторов диазепам феназепам нитразепам при нарастании бессонницы тревоги и страха применяют нейролептические средства аминазин терален. В состоянии помраченного состояния делирий эпилептиформное или онирическое состояние показано внутривенное введение диазепама при сильном возбуждении инъекции аминазина или тералена. Изза опасности коллапса аминазин и терален необходимо сочетать с сердечнососудистыми средствами кофеин кордиамин.
40288. Лечение наркоманий и токсикоманий 31.5 KB
  Первый этап включает в себя купирование абстинентного синдрома и проведение дезинтоксикационных мероприятий направленных на нормализацию соматоневрологических нарушений и коррекцию психических расстройств. Третий этап лечения заключается в выявлении основного синдрома психической зависимости и проведении целенаправленной терапии. Патогенетически обоснованная терапия определяется химической структурой и механизмом действия наркотика а также структурой клинического синдрома. Наиболее эффективными средствами купирования опийного...
40289. Лечение при ЧМТ 27.5 KB
  Применяется также ряд препаратов оказывающих влияние на мозговое кровообращение кавинтон сермион циннаризин танакан.
40290. Лечение эпилепсии 24.5 KB
  Классические препараты: карбамазепин для лечения парциальных и больших эпилептических припадков а также сочетания этих типов приступов; вальпроат эффективен при больших эпилептических и парциальных припадках препарат выбора при абсансах и миоклонических судорогах; пролонгированная форма депакинхроно; 5 новых препаратов: вигабатрин сабрил ламотриджин ламиктал габапентин нейронтин топирамат топамакс и тиагабин габитрил.
40291. Личностные расстройства 27 KB
  Долговременный паттерн переживаний и поведения явно отклоняющийся от общепринятых в данной культуре норм поведения. Этот паттерн проявляется в двух или более областях: 1. Данный паттерн приводит к нарушениям адаптации или к ухудшению функционирования в социальной профессиональной межличностной сферах. Данный паттерн является стабильным и установился до 18 лет.
40293. Нейролептики 26 KB
  Обладая допамино адрено и серотонинблокирующим действием нейролептики препятствуют передаче нервных импульсов из лобных долей на нижележащие структуры головного мозга. Нейролептики способны оказывать противорвотное действие угнетать центр терморегуляции подавлять активирующее воздействие ретикулярной формации на спинальные рефлексы. Нейролептики применяют при многих нервнопсихических и соматических заболеваниях: острых психозах различных видах шизофрении белой горячке и других психических расстройствах.
40294. Нехимические аддикции 39 KB
  Анализ психологического состояния аддикта позволяет установить наличие у него серьёзных эмоциональных проблем центральную часть в которых занимает страх. Частично этот страх удаётся подавить. Страх существующий у аддикта подразделяется на 1 страх находящийся на уровне сознания и 2 подавленный страх находящийся в подсознании. Содержание страха различно.