Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Delphi_02_01 [2012].doc
Скачиваний:
4
Добавлен:
05.07.2019
Размер:
271.87 Кб
Скачать

Лабораторная работа № 1 Процедурные типы данных

Теоретическая часть

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

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

type

Proc = procedure;

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

StrProc = procedur (S: string);

MathFunc = function(X: Real): Real;

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

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

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

Процедурные переменные

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

var

P: SwapProc;

F: MathFunc;

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

procedure Swap(var A,B: Integer);

var

Temp: Integer;

begin

Temp := A;

A := B;

B := Temp;

end.

function Tan(Angle: Real): Real;

begin

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

end.

Описанным ранее переменным P и F теперь можно присвоить значения:

P := Swap;

F := Tan;

После такого присваивания обращение P(i,j) эквивалентно Swap(i,j) и F(X) эквивалентно Tan(X).

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

  • Это не должна быть стандартная процедура или функция.

  • Такая процедура или функция не может быть вложенной.

  • Такая процедура не должна быть процедурой типа inline.

  • Она не должна быть процедурой прерывания (interrupt).

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

type

GotoProc = procedure(X,Y: Integer);

ProcList = array[1..10] of GotoProc;

WindowPtr = ^WindowRec;

Window = record

Next: WindowPtr;

Header: string[31];

Top, Left, Bottom, Right: Integer;

SetCursor: GotoProc;

end;

var

P: ProcList;

W: WindowPtr;

С учетом этих описаний допустимы следующие вызовы процедур:

P[3](1,1);

W.SetCursor(10,10);

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

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

Процедурные типы допускается использовать в качестве типов формальных параметров процедур и функций. Чтобы использовать процедуры и функции в качестве фактических параметров они должны описываться с директивой far или компилироваться в состоянии с {$F+}. В следующем примере показывается использование параметров процедурного типа для вывода трех таблиц различных арифметических функций:

program Tables;

type

Func = function(X,Y: integer): integer;

function Add(X,Y: integer): integer; far;

begin

Add := X + Y;

end;

function Multiply(X,Y: integer): integer; far;

begin

Multiply := X*Y;

end;

function Funny(X,Y: integer): integer; far;

begin

Funny := (X+Y) * (X-Y);

end;

procedure PrintTable(W,H: integer; Operation: Func);

var

X,Y : integer;

begin

for Y := 1 to H do

begin

for X := 1 to W do Write(Operation(X,Y):5);

Writeln;

end;

Writeln;

end;

begin

PrintTable(10,10,Add);

PrintTable(10,10,Multiply);

PrintTable(10,10,Funny);

end.

При работе программа Table выводит три таблицы. Вторая из них выглядит следующим образом:

1 2 3 4 5 6 7 8 9 10

2 4 6 8 10 12 14 16 18 20

3 6 9 12 15 18 21 24 27 30

4 8 12 16 20 24 28 32 36 40

5 10 15 20 25 30 35 40 45 50

6 12 18 24 30 36 42 48 54 60

7 14 21 28 35 42 49 56 63 70

8 16 24 32 40 48 56 64 72 80

9 18 27 36 45 54 63 72 81 90

10 20 30 40 50 60 70 80 90 100

Параметры процедурного типа особенно полезны в том случае, когда над множеством процедур или функций нужно выполнить какие-то общие действия. В данном случае процедуры PrintTable представляет собой общее действие, выполняемое над функциями Add, Multiply и Funny.

Практическая часть

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

  • Приближенное решение алгебраических и трансцендентных уравнений.

  • Приближенное интегрирование функций.

Приближенное решение алгебраических и трансцендентных уравнений

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

Пусть дано уравнение

f(x) = 0, (1)

где функция f(x) определена и непрерывна в некотором конечном или бесконечном интервале а < х < b.

В некоторых случаях требуется существование и непрерывность первой производной f'(х) или даже второй производной f"(х).

Всякое значение , обращающее функцию f(x) в нуль, т. е. такое, что

f() = 0,

называется корнем уравнения (1) или нулем функции f(x).

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

Приближенное нахождение изолированных действительных корней уравнения (1) обычно складывается из двух этапов:

  1. отделение корней, т. е. установление возможно тесных промежутков [, ], в которых содержится один и только один корень уравнения (1);

  2. уточнение приближенных корней, т. е. доведение их до заданной степени точности.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]