Тема 3.3 Создание оверлейных модулей

END.

BEGIN

ИНИЦИАЛИЗАЦИОННАЯ ЧАСТЬ

РЕАЛИЗАЦИОННАЯ ЧАСТЬ

ИНТЕРФЕЙСНАЯ ЧАСТЬ

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

Тема 3.1 Усложненные структуры программ и данных. Модули и оверлеи

 

 

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

А) размещения в памяти больших программ

Б)нужны библиотеки блоков с простым доступом к блокам

1.Модуль (UNIT)

Модуль (UNIT) —программная единица, текст которой компи­лируется независимо (автономно). Она включает определения констант, типов данных, переменных, процедур и функций, доступ­ных для использования в вызывающих программах. Однако внутренняя структура модуля (тексты программ и т.п.) скрыта от пользователя.

Термины UNIT и модуль являются синонимамии обозначают одно и то же понятие в разных языках.

2. Структура модуля (UNIT)

Модуль можно разделить на несколько разделов: заголовок, интерфейсная часть, реализационная часть, инициализационная часть.

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

UHIT Имя модуля;

{$N+} Глобальные директивы компилятора;

INTERFACE Начало раздела объявлений;

USES Используемые при объявлении модули;

labelПодраздел объявления доступных глобальных меток;

CONST Подраздел объявления доступных глобальных констант;

TYPE Подраздел объявления доступных глобальныхтипов;

VAR Подраздел объявления доступных глобальных переменных;

PROCEDURE Заголовки доступных процедур;

FUHCTIOH Заголовки доступных функций;

IMPLEMENTATION Начало раздела реализации;

USESИспользуемые при реализации модули;

LABEL Подраздел объявления скрытых глобальных меток;

CONST Подраздел объявления скрытых глобальных констант;

TYPE Подраздел объявления скрытых глобальных типов;

VAR Подраздел объявления скрытых глобальных переменных;

PROCEDUREТела доступных и скрытых процедур;

FUHCTIOH Тела доступных и скрытых функций;

Основной блок модуля;

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

Заголовок модуля мало отличается от заголовка программы. В модуле вместо зарезервированного словаPROGRAM используется слово UNIT. Здесь же могут присутствовать директивы компилято­ру, дающие общие установки/соглашения для всего модуля.

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

2.2. Интерфейсная часть

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

Примечание:

В рамках ИИО ТП поставляются следующие стандартные модули System, Strings, Crt, Printer, dos, WiaDos, Graph, Overlay .

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

Следом за оператором USES в интерфейсной части описывают­ся доступные извне и необходимые для описанных процедур и функций определения типов данных, констант и переменных.

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

Нет необходимости упоминать в интерфейсной части все проце­дуры и функции, используемые в реализационной части. На практи­ке возможна ситуация, когда интерфейсная часть вообще ничего не содержит, как показано в примере Unitlab.pas,, содержащем модуль Demo_unit3 . Этот модуль, конечно, лишен смысловой нагрузки, но по форме вполне корректен и работоспособен.

UNIT Demo_unit3; { Unitlab.pas}

INTERFACE {Эта часть пуста.}

IMPLEMENTATION

USES

Crt ;

BEGIN

ClrScr ;

END.

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

2.3. Реализационная часть

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

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

2.4. Инициализационная часть

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

Вернемся к нашему Demo_units-модулю.. Он содержит в своей инициализационной части операторClrScr, заключенный в функциональные скобки BEGIN ... END. Если Вы подготовите и запустите следующую программу TUTWENIG.PAS, то вначале произойдет инициализация включенного модуля Demo_units, т.е. выполнится операторClrScr, вследствие чего будет очищен экран. Затем начнет выполняться главная программа, и на экран будет выдано сообщение "Привет!!!".

PROGRAM Uses_denio_unit3; { lab2.PAS}

(Иллюстрирует правило исполнения операторов инициализационной части включенного модуля ПЕРЕД операторами, входящими в главную программу.}

USES Demo_units;

BEGIN

WriteLn('Привет!!!');

END.

Трансляция модуля. Создание выполнимой программы

Результатом трансляции модуля является файл с тем же именем и расширением имени.TPU, который ввиду длительно­го использования заносится на диск, тогда как результат трансля­ции программы в целом (.ЕХЕ-файл) может оставаться в основ­ной памяти. При его получении проверяется правильность обращения к блокам модуля (вот для чего нужна интерфейсная часть).

Общий объем модульной программы может быть много более 64 , но каждый .TPU-файл не может превышать 64 К.

В подменю Compile, которое показано ниже:

Compile A11-F9

Make F9

Build

Destination Memory

Primary file ...

для запуска трансляции предназначаются верхние 3 пункта, однако пункт Compile требует установки значения "Disk" опции Destination (вместо "Memory") для трансляции модуля; вторым этапом проводится трансляция основной программы. Удобнее пункты Make (F9) и Build; кроме того, можно использовать непосредственно пункт Run ("выполнение") подме­ню Run или заменяющие его клавиши Ctrl+F9. Во всех 3 случаях программа и модули транслируются совместно, активным должно быть окно основной программы, либо имя файла основной программы должно быть указано в опции Primary file.

Команда Make (клавиша F9) для каждого модуля проверяет:

— существование TPU-файла; если его нет, то TPU-файл создается путем трансляции исходного текста модуля;

— соответствие TPU-файла исходному тексту модуля, куда могли быть внесены изменения; если это так, TPU-файл авто­матически создается заново;

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

Если модули давно проверены и неизменны, их исходные тексты в ЭВМ не нужны — команда Make в этом случае работа­ет только с TPU-файлами, время компиляции минимально. Напротив, команда Build требует наличия исходных текстов модулей, ибо все они компилируются. Эта "перестраховка" влечет рост времени компиляции. Чтобы были понятны дальнейшие рекомендации, следует четко представить взаимодействие модулей и основной програм­мы. Изучите схему 1 (случай двух модулей М1 и М2; разделы инициализации не предусмотрены, локальные блоки в ней не отражены).В общем случае ссылки модулей на модули могут представ­лять сложную картину. В нашем примере основная программа косвенно использует модуль М2. Если бы потребовалось обращаться непосредственно в основной программе к объявле­ниям или блокам модуля М2, мы записали бы в основной программе Uses M1,M2 вместо Uses M1. Примите к сведению, что интерфейсная часть модуля M1 как бы становится началом \ описательной части основной программы, поэтому не только объявления, но и блоки модуля M1 "видны" из под блоков основной программы, где можно обращаться к ним. Однако нельзя, например, определить константу N в основной программе, а использовать в объявлении типа в модуле M1.

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

Хотя раздел реализации отсутствует, слово Implementation нужно

 

UNIT M2; INTERFACE <0бъявления, которые "видны" лишь из модуля М1> IMPLEMENTATION <Блоки, доступные для обращений из модуля М1> END.
UNIT M1; INTERFACE USES М2; <Объявления, которые "видны" из основной программы> IMPLEMENTATION <Блоки, используемые основной программой> END.
{Основная программа} USES M1; <0бъявления, которые "не видны" из модулей M1 и М2> <Блоки, недоступные для модулей M1 и М2> <Главная операторная часть> END.

Схема 1- Взаимодействия модулей и основной программы

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

вы, безусловно, сделаете блочной. Если не вкладывать большие блоки друг в друга и подчиненные блоки записывать прежде использующих их блоков, довольно просто распределить их для размещения в разные модули: выде­лив объявления в отдельный модуль, следующие за ними блоки помещаете во 2-й модуль, идущие далее по тексту — в 3-й мо­дуль и тд. При этом 2-й модуль может ссылаться лишь на 1-й, 3-й модуль может обращаться и к 1-му, и ко 2-му и т.д.; тем самым "круговые" ссылки модулей предотвращаются. Поскольку 1-й модуль, содержащий одни объявления, ни на один модуль не ссылается, его можно (и нужно) указать в предложе­нии Uses во всех модулях, где должны действовать эти объявления.

,,,,,,,,,,Поиск ошибок с помощью отладчика.

Цель задания: Научиться отлаживать программы с помощью встроенного

отладчика.

Несмотря на то что Интегрированная Инструментальная Обо­лочка Турбо Паскаля включает в себя ряд средств, облетающих разработку программ, в них все равно могут содержаться ошибки, не позволяющие корректно работать с данными программами.

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

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

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

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

2. Ошибки, проявляющиеся на этапе выполнения — ошибки, возни­кающие в связи с нарушением семантических правил написания программ на языке программирования Турбо Паскаль 7.0 (ярким примером ошибки данного типа является ситуация, когда Ваша программа пытается выполнить деление на нуль). Если написанная Вами программа обнаруживает ошибку такого типа, то она завершает свое выполнение и выводит сообщение следующего вида:

Run-time error <nnn> at<xxxx:yyyy>

Где ллл —номер ошибки выполнения,

хххх.-уууу — адрес ошибки выполнения.

Если Вы выполняете программу из ИИО ТП, то она автоматически найдет вызвавший семантическую ошибку опера­тор (так же как и в случае синтаксических ошибок). Если же программа выполнялась вне ИИО и в ней появилась ошибка данного типа, то необходимо запустить ИИО ТП и найти вызвавший семантическую ошибку оператор, используя коман­дуSearch/Find Error (после того как Вы активизируете коман­дуSearch/Find Error, она запросит у Вас адрес сегмента и смещения (хххх:уууу) оператора, вызвавшего семантическую ошибку).

3. Логические ошибки — это ошибки, связанные с неправильным применением тех или иных алгоритмических конструкций. ИИО ТП 7.0 не позволяет автоматически обнаруживать ошибки данного типа. Она лишь обладает рядом средств отладки, которые могут значительно облегчить процесс поиска таких ошибок.

С точки зрения программиста одно из основных преимуществ отладки программ с помощью встроенного в ИИО ТП отладчика (Debugger) заключается в возможности осуществления контроля над ходом выполнения программы. Отследив таким образом выпол­нение каждой инструкции, Вы без особого труда сможете опреде­лить, в какой части программы находится ошибка.

Встроенный в ИИО ТП отладчик позволяет:

>• выполнять команды языка Паскаль построчно (пошагово);

>• трассировать команды языка Паскаль;

>• выполнять программу до некоторой определенной строки (до некоторой точки);

>• осуществлять перезапуск программы, не закончив ее выполнение.

Эти возможности позволяют контролировать ход выполнения программы.

Рассмотрим все эти управляющие средства по очереди.

 

Пошаговая отладка программы и трассировка.

КомандыStep Over и Trace Into менюRim позволяют осуществить построчную отладку программы. Активизация командыStep Overили нажатие функциональной клавиши [F8], так же как активиза­ция командыTrace Into или нажатие функциональной клавиши [F7], вызывает выполнение отладчиком всех операторов, располо­женных в строке, помеченной маркером (указателем строки выпол­нения). Единственное отличие между выполнением программы по шагам и ее трассировкой состоит в том, как реагирует отладчик на появление в тексте программы операторов вызова процедур или функций. При пошаговом выполнении программы вызов процедуры или функции интерпретируется как вызов простого оператора, т.е. Вы можете увидеть результаты работы процедуры, но не можете пошагово проследить, каким образом этот результат был получен, в то время как при трассировке программы такая возможность предоставляется.

Рассмотрим более подробно работу команд Step Over и Trace Into на следующем примере

PROGRAM Procedure_and_Function; {FUNKPROZ.PAS}

USESCrt;

VAR a, b, Sum_nuinbers: INTEGER;

PROCEDURE Summing-up (VAR Sum:INTEGER;a,b:INTEGER);

BEGIN

Sum:=a + b;

END;

FUNCTION Sum(a,b: INTEGER):INTEGERS;

BEGIN Sum:=a + b; END;

BEGIN

ClrScr;

a := 12; b := 15;

Suinming_up (Sum_number3, a, b);

WriteLn('Сумма равна: ',Sum_numbers);

Sum_number3:=Sum(a,b);

WriteLn('Сумма равна: ',Sum_numbers);

WriteLn('Сумма равна: ',Sum(a,b)) ;

END.

Примечание:

Прежде чем проводить пошаговую отладку программы или ее трассировку, необходимо убедиться, что опцияOptions/Debug­ger/Integrated активизирована.

Введите с клавиатуры и откомпилируйте текст данной програм­мы, после чего нажмите клавишу [F8] (пошаговая отладка). Обра­тите внимание на тот факт, что маркер сразу перемещается на оператор BEGIN, расположенный в основном блоке программы. Это происходит потому, что оператор BEGIN является первым оператором, который выполняется в теле программы. Нажимая клавишу [F8], выполните эту программу до конца. Теперь вы можете попытаться оттрассировать эту же программу, нажимая клавишу [F7]. Обратите внимание на то, что трассировка програм­мы во многом аналогична ее выполнению по шагам. Единственное отличие, как мы уже говорили, состоит в том, что когда встречается оператор вызова процедуры или функции, то при трассировке эти процедуры и функции также выполняются по шагам, а при простом выполнении по шагам управление возвращается к Вам только после завершения выполнения подпрограммы.

Выполнение программы до определенной точки.

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

Во-первых, Вы можете воспользоваться командойGo to CursorменюRun (или функциональной клавишей [F4]), предварительно установив курсор на так называемую строку останова (т.е. строку, до которой вы хотите выполнить программу). После активизации командыGo to Cursor программа будет выполняться до тех пор, пока не достигнет строки останова, в которой ее выполнение будет приостановлено. Начиная с этого момента, у Вас появится возмож­ность управлять ходом событий. Например Вы можете продолжить выполнять данную программу пошагово до некоторой новой точки или перезапустить программу (о том, как перезапустить программу, не закончив ее выполнение, Вы можете прочитать в следующем разделе).

Во-вторых, Вы можете установить в некоторой строке (или сразу в нескольких строках)так называемую точку останова (Breakpoint). Запущенная программа будет выполняться до тех пор, пока не достигнет строки, в которой установлена точка остано­ва.

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

Установить в тексте программыBreakpoint можно любым из ниже перечисленных способов:

а). Установите курсор на строке, в которую Вы хотите поместить Breakpoint. Откройте локальное меню и активизируйте коман­дуToggle breakpoint.

б). Установите курсор на строке, в которую Вы хотите поместить Breakpoint, и активизируйте клавиатурную комбинацию [Ctrl+F8].

в). Установите курсор на строке, в которую Вы хотите поместить Breakpoint, и активизируйте командуAdd breakpoints меню Debug.

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

>• Breakpoint list:

Имя файла, в котором установлена точка останова;

>• Line:

Номер строки, в которой установлена точка останова;

>- Condition:

Условие, при выполнении которого осуществляется останов программы. Например в качестве условия может быть исполь­зовано выражение следующего типа:

X > О или

(X <= ) OR (KeyPresaed)

>- Pass:

Счетчик числа проходов.

Задание для точки останова счетчика проходов сообщает отлад­чику, что останавливать программу нужно не при каждом достижении точки останова, а только при N-ом ее проходе. Например Breakpoint, установленный в теле циклаFOR ... ТО ... DO

В окнеBreakpoints пользователь может модифицировать (кнопка Edit), удалить (кнопкаDelete илиClear all — если Вы хотите удалить все точки останова) или просмотреть (кнопкаView) место­положение какой-либо точки останова.

Примечание:

Чтобы удалить точку останова, установите курсор на содержа­щую ее строку и активизируйте комбинацию клавиш [Ctrl+F8].

Тема:3.2 долговременно хранимые модули

Занятие -,,,,,,,часа

Цель работы Научиться использовать стандартные модули Турбо Паскаля

 

Стандартный модуль System - единственный, который не нужно указывать в предложении Uses -содержит "библиотеку времени выполнения" (стандартные математические функции и т.п.). Имеются следующие стандартные модули: System, dos, Crt, Overlay, Printer, Graph, Turbo3 и Graph3. Они, кроме З последних, содержатся в файле Turbo.TPL ("библиотека модулей"), .a Graph.TPU — в директории BGI. ТигbоЗ и Graph3 даны для совместимости с ранней версией Турбо Паскаля.

Модуль dos содержит блоки, обеспечивающие доступ ко всем средствам операционной системы PC DOS. Блоки "даты-времени", позволяющие датировать последовательные версии файла, распечатки программы, изме­рять время выполнения ее частей.

Модули Strings (библиотека блоков для работы со строками типа PChar) и WinDos — с целью реализа­ции возможностей системы MS DOS с использованием строк типа PChar. Модуль WinDos используется взамен модуля dos.

Пример. Процедура GetTime дает текущее время: час, минуты, секунды, доли секунды. Измерим время выполнения "бессодержательного" цикла:

………

Uses dos;

Var

hour, min, sec, dec: Word;

j, t1: longint;

Begin

GetTime(hour min,sec,dec);

t1:= hour*3600 + min*60 + sec;

For j:= 1 to 10000000 do; {"Пустой" цикл}

GetTime(hour,min,sec,dec);

Writeln(h6ur*3600 + min*60 +sec -t1)

End.

Библиотечный файл TURBO.TPL можно расширять. Длительно и коллективно используемые библиотеки блоков лучше хранить не в виде TPU-файлов, а "встроить" в систему путем помещения их в файл Turbo.TPL. Вам поможет это сделать утилита (вспомогательная системная программа) TPUMOVER. В результате упрощается использо­вание библиотечных блоков.

Следует иметь в виду, что файл Turbo.TPL автоматически загружается компилятором в оперативную память и чрезмерное его увеличение нежелательно.

Вопросы для самопроверки

1.Какие стандартные модули имеются в Турбо Паскале

2.Какие из них необязательно объявлять в предложении Uses

3.Какие из стандартных модулей содержатся в файле Turbo.tpl