Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ответы на вопросы.doc
Скачиваний:
72
Добавлен:
13.03.2016
Размер:
393.22 Кб
Скачать

Процедурные типы

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

только как части программы, которые можно выполнять с помощью вы-

зова процедуры или функции. В Borland Pascal процедуры и функции

трактуются гораздо шире: здесь допускается интерпретация процедур

и функций, как объектов, которые можно присваивать переменным и

передавать в качестве параметров. Такие действия можно выполнять

с помощью процедурных типов.

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

ции - результат функции.

процедурный тип

¦

¦ ----------

LT>¦procedure+-T----------------------------------------------->

¦ L---------- ¦ ----------------------------- ^ ^

¦ L->¦список формальных параметров+-- ¦

-- L----------------------------- L-

¦ --------- ---- ----------¦

L>¦function+T-------------------------------->¦ : +>¦результат+-

L---------¦ -----------------------------^ L---- L----------

L>¦список формальных параметров+-

L-----------------------------

Характерно, что синтаксис записи процедурного типа в точнос-

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

опускается идентификатор после ключевого слова procedure или

function. Приведем некоторые примеры описаний процедурного типа:

type

Proc = procedure;

SwapProc = procedure(var X, Y: Integer);

StrProc = procedure(S: String);

MathFunc = function(X: Real): Real;

DeviceFunc = function(var F: text): Integer;

MaxFunc = function(A, B: Real; F: MathFunc): Real;

Имена параметров в описании процедурного типа играют чисто

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

Borland Pascal не позволяет описывать функции, которые возв-

ращают значения процедурного типа. Результат функции должен быть

строкового, вещественного, целого, символьного, булевского типа,

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

лем.

Процедурные значения

Переменной процедурного типа можно присвоить процедурное

значение. Процедурные значения могут быть следующими:

* значениями nil;

* ссылкой на переменную процедурного типа;

* идентификатором процедуры или функции.

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

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

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

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

var

P: SwapProc;

F: MathFunc;

procedure Swap(var A, B: Integer); far;

var

Temp: Integer;

begin

Temp := A;

A := B;

B := Temp;

end;

function Tan(Angle: Real); far;

begin

Tan := Sin(Angle) / Cos(Angle);

end;

Переменным P и F можно присвоить значения следующим образом:

P := Swap;

F := Tan;

а вызовы с помощью P и F можно выполнить так:

P(I, J); { эквивалентно Swap(I, J) }

X := F(X); { эквивалентно X := Tan(X) }

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

вызова процедуры или функции присваивается значение nil, приводит

к ошибке. Значение nil предназначено для указания того, что про-

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

ная может получить значение nil, участвующие в этой процедурной

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

if @P <> nil then P(I, J);

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

того, что P проверяется, а не вызывается.

Модули.

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

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

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

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

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

  идентификатор модуля, указанный в заголовке (unit), должен совпадать с именами файлов, содержащих исходный (.pas) и объектный (.tpu, .tpp, .tpw) коды;

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

Рассмотрит общую структуру модуля.

Unit имямодуля;

{ Интерфейсный отдел }

interface

{ Описывается взаимодействие модуля с другими модулями и основной программой }

{ Список импорта интерфейсного раздела }

uses

{ Через запятую перечисляются имена модулей, информация которых должна быть доступна в данном модуле}

{ Список экспорта интерфесного раздела}

const

type

var

procedure

function

{ Список всех типов переменных, которые определены в данном

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

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

{ Раздел реализаций }

implementation

{ Внутренняя часть описаний данного модуля}

{ Список импорта раздела реализаций }

uses

{ Через запятые перечисляются имена модулей, информация

интерфейсных частей которых должна быть доступна в

данном модуле}

{ Подразделы внутренних для модуля описаний }

label

const

type

var

procedure

function

{ Описываются все типы переменных, которые описывают

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

Эти описания недоступны ни одному другому модулю}

{ Раздел инициализаций}

begin

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

для запуска корректной работы модуля }

end.

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

Приведем пример модуля, содержащего описания процедуры и функции, рассмотренных ранее.

Unit primer;

Interface

Procedure line(n:integer; c:char);

Function factor(n:integer): integer;

Implementation

Uses crt;

Procedure line(n:integer; c:char);

var

i:integer;

begin

for i:=1 to n do write( c);

writeln;

end;

Function factor(n:integer): integer;

var

i, f: integer;

begin

f:=1;

for i:=2 to n do f:=f*i;

factor:=f;

end;

end.

Приемочные тесты (ранее их также называли Функциональные) пишутся на основе User Story. Они рассматривают систему как черный ящик. Заказчик ответственен за проверку корректности функциональных тестов. Эти тесты используются для проверки работоспособности системы перед выпуском ее в производство. Функциональные тесты автоматизируются так, чтобы имелась возможность их часто запускать. Результат сообщается команде и команда отвечает за планирование исправлений функциональных тестов.

Принципы и методы структурного программирования. Восходящее и нисходящее проектирование

    На этом шаге мы рассмотрим методы восходящего и нисходящего проектирования.

    Другой метод улучшения качества программирования заключается в применении нисходящего проектирования (Top-Down Programming - программирование "сверху вниз").

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

Вызвали подпрограмму номер ... .

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

    При другом методе - восходящем проектировании (программировании "снизу вверх") - Вы вначале пишете подпрограммы нижнего уровня и тщательно их тестируете и отлаживаете. Далее Вы добавляете подпрограммы более высокого уровня, которые вызывают подпрограммы нижнего уровня, и так до тех пор, пока Вы не достигнете программы самого верхнего уровня. Метод проектирования "снизу вверх" пригоден при наличии больших библиотек стандартных подпрограмм.

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

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

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

    Метод "снизу вверх", хотя и требует большого труда, бывает очень полезен на первых порах. Пусть даже половину составленных Вами подпрограмм придется потом "выбросить", но зато Вы хорошо почувствуете, какие подпрограммы для исходной задачи необходимы. Да и отлаживать каждую написанную подпрограмму можно сразу: ведь все, что "под ней", уже описано (а обычно и отлажено). Словом, любишь кататься "сверху вниз" - люби и саночки возить (в обратном направлении). Опытные программисты иногда применяют метод "снизу вверх" для того, чтобы заранее заготовить для новой задачи набор подпрограмм, которые могут понадобиться в различных случаях. Так что "возить саночки" приходится не только новичкам!

Описание констант

Раздел описания CONST позволяет ввести в программу идентификаторы, являющиеся синонимами (представителями) определенных значений. Описание константы представляет собой пару "идентификатор - значение", разделителем пары служит символ "=".

Синтаксис описания констант:

CONST   ИмяКонстанты1 = Значение1;   ИмяКонстанты2 = Значение2;

или

  ИмяКонстанты = ЗначениеВыражения;

Примеры описания констант:

CONST   Min = 0;  { константа - целое число }   Max = 100;{ константа - целое число }   e = 2.7;  { константа - вещественное число }   SpecChar = '\'; {константа - символ }   HelpStr = 'Нажмите клавишу F1'; {константа - строка }   OK = True; { логическая константа "истина" }  

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

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

CONST   Interval = Max - Min + 1;   e2 = e*e;   BigHelpStr = HelpStr + ' для подсказки';

В выражениях могут использоваться все математические операции (+, -, /, *, div, mod), логические операции (not, or, and, xor) и операции отношения.

Описанные ранее константы можно использовать для построения индексов массивов, например:

CONST   N = 100; VAR   V : array[1..N] of Byte;

Описание переменных

Переменные вводятся в программу для хранения и передачи данных внутри нее. Все переменные, которые предполагается использовать в программе должны, прежде всего, быть определены в разделе описания переменных. Описание переменных начинается со служебного слова VAR, вслед за которым располагается последовательность самих определений переменных.  Определение переменной заключается в указании ее имени (идентификатора) и типа. Имя и тип разделяются двоеточием. После объявления и описания переменной должен стоять символ ";". Концом блока описания будет начало какого-либо другого блока программы или описание процедур и функций.

Синтаксис описания переменных:

VAR   ИмяПеременной1 : ИмяТипа1;   ИмяПеременной2 : ИмяТипа2;   . . .   ИмяПеременнойN : КонструкцияТипа;

или

VAR   ИмяПеременной1,   ИмяПеременной2,   ИмяПеременной3  : ИмяТипа;

Имя типа может быть именем стандартного типа языка или введенного программистом в предшествующем блоке описания типов TYPE.

Однотипные переменные могут перечисляться через запятую перед объявлением их типа.

Примеры описания переменных:

VAR   X : Real;          { вещественная переменная }   i, j, k : Integer; { три целочисленных переменных }   T : MyType; { переменная определенного ранее типа MyType }   D : 1..10;  { целочисленная переменная ограниченного типа }   M : array[1..5] of Byte; { переменная типа "массив" }   Data : RECORD            X, Y : Byte;            TextStr : String { переменная тпиа "запись" }          END