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


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

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



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

Классические примеры таких ситуаций дают численные методы. В подпрограммах численных методов (вычисления определенного интеграла, нахождения экстремумов и нулей функций, вывода графиков, линий уровня, таблиц функций) обрабатываемые функции задаются как параметры. Средства для использования параметров-подпрограмм имеются во всех алгоритмических языках, предназначенных для решения вычислительных задач (СИ, Фортран, ПЛ/1).

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

TYPE PROC1=PROCEDURE(a,b,c:real; var d:integer);

FUNC1=FUNCTION: REAL;

G=FUNCTION (x,y,z:real);

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

Замечания

1. Имена стандартных подпрограмм нельзя использовать в качестве фактических параметров.

2. В языках Borland Pascal и Turbo Pascal подпрограммы, используемые как фактические параметры, должны компилироваться с использованием "дальней модели памяти", поэтому в программу надо включить директивы компилятора {$F+} и {$F-} или поставить стандартную директиву far (для версий начиная с Turbo Pascal 6.0) cразу за заголовком подпрограммы.

Пример 1. Решение двух уравнений на отрезке [0,3] c погрешностью 0.0001.

program primer2_5;

Type fn=function(x:real):real;{функциональный тип, задающий

вид уравнения}

Var r1,r2:real; {коpни уpавнений}

{$F+} {опция дальнего вызова, в Object Pascal не надо}

function fx1(x:real):real; {fx1 задает первое уравнение}

begin

fx1:=1.0/(1.2*sin(x)/cos(x)+sqrt(x+1));

end;

function fx2(x:real):real; {fx2 задает второе уравнение}

begin

fx2:=(exp(-x)-sqrt(exp(x))+3.7)/3.0;

end;

{$F-} { В Object Pascal не надо }

{root – подпрограмма вычисления корня}

{уравнения fx(x)=0 на [a,b] c погрешн.е методом простых итераций}

function root(fx:fn; a,b,e:real):real;

{fx - функция – формальный параметр}

var x,x0:real;

begin

x0:=(a+b)/2; x:=fx(x0);

while abs(x-x0)>e do

begin

x0:=x; x:=fx(x0);

end;

root:=x;

end;

begin

r1:=root(fx1,0,3,1.0e-4);{fx1 - функция - факт. параметр}

r2:=root(fx2,0,3,1.0e-4);{fx2 - функция - факт. параметр}

writeln('Коpень пеpвого уpавнения r1=',r1:7:4);

writeln('Коpень втоpого уpавнения r2=',r2:7:4);

end.

Пример 2. Предположим, что функция root решения уравнения из примера 1 является библиотечной подпрограммой и не подлежит изменению. Пусть надо решить уравнение, заданное с точностью до параметра p, например, p задается вводом:

x – p cosx=0.

В программе надо обратиться к root, подставив вместо формального параметра fx фактический

g(x,p)= x – p cosx.

Но g имеет два аргумента, а fx один. Выход из этой ситуации состоит в том, чтобы параметр р считать глобальным. Программа решения уравнения приведена ниже; предполагается, что тип f n и функция root имеются в подключенной к программе библиотеке.

Var p{глобальная переменная для функции g},

E{погрешность решения уравнения}, A,B{границы отрезка}:real;

function g(x:real):real;

begin

g:=x-p*cos(x)

end;

begin

writeln(‘Введите p,A,B,E’);

readln (p,A,B,E);

writeln(‘ корень уравнения равен ‘, root(g,A,B,E));

readln

end.

Модули

Общие сведения

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

Для обеспечения возможности компиляции программы по частям в реализациях Паскаля, начиная с Турбо Паскаля, введено новое средство языка - модули (Units).

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

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

Структура модуля

Схематично структуру модуля можно изобразить следующим образом:

UNIT имя_модуля;

INTERFACE

интерфейсная_часть

IMPLEMENTATION

исполняемая_часть

[BEGIN

инициирующая_часть ]

END.

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

Модуль состоит из трех частей[19]. Первая часть содержит описания, доступные другим программам или модулям. Часто ее называют видимой (ее как бы "видят" другие программы) или интерфейсной (она начинается с ключевого слова INTERFACE, что в переводе с английского означает "внешние связи"). От процедур и функций в первую часть включаются только заголовки.

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

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

Пример

Ниже приведен модуль VECTOR, позволяющий осуществлять некоторые операции над векторами. Число компонент вектора не превышает 10. Смысл процедур поясняется в комментариях.

UnitVECTOR; {операции над векторами}

INTERFACE

Type AR=Array[1..10] of real;

Function Scpr(Var a,b:Ar;N:Integer):Real;

{вычисление скалярного произведения двух векторов}

Function Lngth(Var a:Ar; N:Integer):Real;

{вычисление длины вектора}

Function UngleRad(Var a,b:Ar; N:Integer):Real;

{вычисление угла между двумя векторами в радианах}

Function UngleGr(Var a,b:Ar;N:Integer):Real;

{вычисление угла между двумя векторами в градусах}

Procedure Sum(Var a,b,c:Ar;N:Integer);

{вычисление суммы двух векторов}

Procedure Inp(Var a:Ar; N:Integer);

{ввод координат вектора}

IMPLEMENTATION

Function Scpr;

Var I:Integer; S:Real;

Begin

S:=0;

For i:=1 To N Do

S:=S+a[i]*b[i];

Scpr:=S;

End;

Function Lngth;

Begin

Lngth:=Sqrt(Scpr(a,a,N));

End;

Function UngleRad;

Var x:Real;

Begin

x:=Scpr(a,b,N)/Lngth(a,N)/Lngth(B,N);

If x=0 then UngleRad:=pi/2

Else

UngleRad:=ArcTan(Sqrt(1-x*x)/x);

End;

Function UngleGr;

Begin

UngleGr:=UngleRad(a,b,3)/pi*180;

End;

Procedure Sum;

Var i:Integer;

Begin

For i:=1 to N Do

c[i]:=a[i]+b[i]

End;

Procedure Inp;

Var I:Integer;

Begin

For i:=1 To N Do

Read(a[i]);

Readln

End;

End.

В Объектном Паскале допустима рассмотренная структура модуля. Но можно также отмечать начало инициализирующей части ключевым словом INITIALIZATION (вместо BEGIN). Модуль Объекьного Паскаля может иметь завершающую часть, которая содержит операторы, выполняемые при завершении программы, и начинается со слова FINALIZATION.

Имя файла, содержащего исходный текст модуля, должно совпадать с именем модуля и иметь расширение. PAS (для примера предыдущего раздела VECTOR.pas). Результатом компиляции будет файл с тем же именем. Расширение откомпилированного файла. TPU (например, VECTOR.tpu) для сред Turbo и Borland Pascal и .DCU для Delphi.

Использование модулей

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

Program ppp;

Uses crt,graph; {программа ppp использует модули crt и graph}

Если модуль использует другие модули, то предложение USES может стоять либо после слова INTERFACE, либо после слова IMPLEMENTATION. Модули, подключенные в интерфейсной части, доступны в любой точке рассматриваемого модуля; модули, подключенные в исполняемой части, доступны в любом месте модуля, за исключением интерфейной части.

Чтобы файлы с расширением. TPU были доступны среде Turbo (Borland) Pascal, их следует поместить в текущий каталог или указать их содержащий каталог в диалоговом окне опции OPTIONS/DIRECTORIES/UNIT DIRECTORIES.

В Delphi существуют специальные возможности для подключения модуля к проекту; кроме того, директория местоположения модуля может быть указана в предложении USES:

Uses имя_модуля in имя директории

Пример

Ниже приведена программа, использующая модуль VECTOR из §2.6.2.

Program Primunit;

{Даны два вектора а и b в трехмерном пространстве;}

{вычисляется длина вектора с (с=а+b) и угол между вектором с и плоскостью XOY}

Uses VECTOR; {используется модуль VECTOR}

Var a,b,c,cpr:Ar;{тип ar объявлен в модуле}

Begin

Writeln(' Введите координаты исходных векторов');

Inp(a,3);Inp(b,3); {ввод а и в}

Sum(a,b,c,3); {c=a+b}

Writeln(' Длина вектора-суммы:', Lngth(c,3):10:3);

cpr[1]:=c[1]; cpr[2]:=c[2]; cpr[3]:=0;

{cpr - проекция с на плоскость XOY}

If Lngth(cpr,3)< 1.0e-6 then

Writeln('вектор c ортогонален плоскости XOY')

Else

Begin

Write(

' Угол между вектором с и плоскостью XOY:',UngleGr(c,cpr,3):6:1);

Writeln(' градусов');

End;

Readln;

End.



Поделиться:


Последнее изменение этой страницы: 2017-02-07; просмотров: 273; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.21.231.245 (0.037 с.)