Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


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



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

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

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

функция f как формальный параметр

Procedure график(х: real; function f(x: real)): real; (так писать нельзя)

Костяк универсальной процедуры построения графика может иметь следующий вид:

function f1 (...): real;

begin

...

end;

function f2 (...): real; Описания функций, для которых надо строить графики

begin

...

end;

function f3 (...): real;

begin

...

end; для построения графика функции f1(x) вызов

procedure график (x: real, function f(x: real)): real; процедуры имел бы вид: график(x, f1(x));

begin

В теле процедуры вывода графика используется один оператор вывода для всех функций (f1, f2, f3).
...

writeln(.........., f(x), ...);

end;

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

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

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

Procedure f(a: array[1..10] of char);

неверно
Procedure_plot (x: real; …

f: function (x: real); …): real;

На Паскале для этого случая нужно объявить процедурный тип.

Имя функции не указывается
Type

func = function (x: real): real;

Справа от " =" фактически приводится заголовок функции, только без имени.

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

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

procedure plot (x: real; f: func);

begin

...

writeln (..., f(x), ...);

end;

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

Примеры объявлений:

Туре

Proc_0 = Procedure; {тип-процедура без параметров}

Ргос_2 = Procedure(Var х, у); {тип-процедура с 2-мя параметрами}

Ргос_3 = Procedure(a, b: real; Var у: real); {тип-процедура с 3-мя параметрами }

Func_0 = Function: integer; {тип-функция без параметров }

Func_1 = Function(s: real): real; {тип-функция с одним параметром }

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

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

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

§ для установки правильных связей между вызывающими и вызываемыми подпрограммами вызываемые процедуры или функции (передаваемые как параметры) должны быть скомпилирована с использованием дальней модели вызовов с формированием их полного адреса, что достигается двумя путями: они должны компилироваться с директивой компилятору {SF+}

1-й путь

{$F+}

function f1(...): real;

Перед и после описания функции помещается директива {$F}
begin

...

end;

{$F-}

 

2-й путь:

function f1(...): real; far;

явно указана необходимость использования дальнего вызова в заголовке функции.

 

§ они не должны объявляться внутри других процедур или функций;

§ они не должны быть стандартными процедурами или функциями;

 

 

18.13 Директивы подпрограмм

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

1. Директива FORWARD

Директивы FAR и NEAR

Как правило, компилятор Turbo Pascal автоматически выбирает адресацию к подпрограмме. Например, если подпрограмма находится в одном файле с основ­ной программой, то она компилируется с " ближним" (near) адресом входа и воз­врата, состоящим только из смещения в текущем сегменте, а если она находится в модуле, то формируется " дальний" (far) адрес, состоящий из адреса сегмента и смещения.

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

Реже используется директива near, которая сообщает компилятору, что подп­рограмму следует компилировать с получением именно такого адреса. Эта дире­ктива эквивалентна ключу компилятора {$F-}, который выбирается по умолча­нию. Действие директивы распространяется только на одну подпрограмму.

Директива EXTERNAL

Директива external позволяет использовать в программе подпрограммы, напи­санные на языке ассемблера и скомпилированные отдельно. Эти подпрограммы должны быть скомпонованы с основной программой, используя ключ {$L < имя файла> }. Здесь имя файла - имя того файла (с расширением.OBJ), в котором находятся скомпилированные объектные модули подпрограмм, написанных на языке ассемблера.

Директива ASSEMBLER

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

Директива INLINE

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

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

6. Директива INTERRUPT

Директива interrupt предназначена для процедур, обрабатывающих прерыва­ния. Такие процедуры имеют стандартный заголовок:

procedure IntHandler(Flags, CS, IP, AX,

BX, CX, DX, SI, DI, DS, ES, BP: Word); interrupt;

begin

end;

В заголовке отдельные параметры можно опускать (но только с начала спис­ка), промежуточные параметры удалять нельзя, например:

procedure IntHandler(DI, ES, BP: Word); interrupt; {неправильный заголовок}

procedure IntHandler(DI, DS, ES, BP: Word); interrupt; {правильный заголовок}

Нельзя в заголовке процедуры обработки прерываний записывать и какие-ли­бо другие параметры.

18.14 Отладка и тестирование программ, содержащих подпрограммы

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

 

18.14.1 Нисходящее тестирование и подпрограммы-заглушки

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

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

 

18.14.2 Восходящее тестирование и программы-тестеры

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

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

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

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

18.14.3 Рекомендации по отладке программ, содержащих подпрограммы

Вот несколько рекомендаций по отладке программных систем.

  1. При создании исходного текста не забывайте использовать комментарии для документирования каждого параметра и локального идентификатора подпрограммы. Также используйте комментарии для описания операций, выполняемых подпрограммой.
  2. Пусть выполнение каждой подпрограммы оставляет след в данных вывода программной системы. Для этого в каждую из подпрограмм, в начале ее тела, поместите оператор WriteLn, который бы отображал сообщение с именем данной подпрограммы.
  3. В каждую из подпрограмм вставьте операторы, которые при входе в нее отображали бы значения всех входных параметров, а также параметров входа-выхода данной подпрограммы.
  4. Вставьте операторы, которые бы отображали значения всех выходных данных подпрограммы после передачи управления основной программе. Осуществите ручную проверку этих значений, чтобы убедиться, что они корректны. Для процедур проследите, чтобы все выходные параметры, а также: параметры входа-выхода были объявлены как параметры-переменные.
  5. Проследите, чтобы подпрограмма-заглушка присваивала значения каждому из выходных параметров.

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

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

const

Debug = True {отладка включена}

А когда надобность в отладке минует, данное описание константы дол выглядеть так:

const

Debug = False {отладка выключена}

Затем в тело основной программы, а также в подпрограммы вставьте диагностические операторы WriteLn, управляемые оператором if с Debug в качестве условия.

 

18.14.4 Использование отладчика для трассировки процедур

В качестве альтернативы отображению начальных значений входных (и входа-выхода) параметров процедуры с использованием специальных отладочным операторов, для получения соответствующей информации можно воспользоваться отладчиком Turbo Pascal и его возможностью трассировки Trace into (< F7> ). Если оператор, который должен быть выполнен следующим, представляет собой оператор вызова процедуры, нажатие клавиши < F7> обеспечит вход в эту процедуру. В результате в окне редактора появится тело этой процедуры с указателем выполнения на слове begin. Если вы укажете параметры процедуры как переменные для наблюдения, исходные значения этих параметров появятся в окне Watch. Затем, с выполнением каждого оператора процедуры (для этого каждый раз требуется. нажимать клавишу < F7> ), любое новое значение, присвоенное выходному параметру или параметру входа-выхода, будет отображено в окне Watch.

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


Поделиться:



Популярное:

  1. Bizz: Белье стирается вперемешку с чужим или как?
  2. Bizz: Допустим, клиент не проверил карман, а там что-то лежит, что может повредит аппарат. Как быть в такой ситуации?
  3. I AM HAPPY AS A KING (я счастлив как король)
  4. I. Какие первичные факторы контролируют нервную активность, то есть количество импульсов, передаваемых эфферентными волокнами?
  5. II. ЭКОЛОГИЧЕСКОЕ ПРАВО КАК КОМПЛЕКСНАЯ ОТРАСЛЬ
  6. III КАК РАСТУТ НА НОВОЙ ГВИНЕЕ
  7. III. Основные функции и полномочия Управления
  8. III. Половая связь – лишь как конечное завершение глубокой всесторонней симпатии и привязанности к объекту половой любви.
  9. IV. Как узнать волю Господню.
  10. IX. Толерантность как нравственная основа социокультурной деятельности библиотекаря
  11. PR – отношения с общественностью. Цели, задачи, функции, методы
  12. SWOT-анализ организации как метод выявления и предупреждения организационно-управленческих конфликтов.


Последнее изменение этой страницы: 2016-07-12; Просмотров: 797; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.044 с.)
Главная | Случайная страница | Обратная связь