- •От автора
- •1. Общая схема решения задачи на персональном компьютере
- •2. Структура программы на языке Паскаль
- •3. Арифметические типы данных. Числовые константы и переменные. Оператор присваивания. Выражение
- •4. Операторы ввода-вывода
- •5. Арифметические операции. Стандартные математические функции
- •6. Символьный тип данных
- •7. Логический тип данных. Операции сравнения. Логические операции
- •8. Условный оператор. Блок. Оператор выбора
- •9. Операторы цикла
- •10. Метки. Оператор Goto. Процедура Halt
- •11. Интервальные типы данных. Оператор Type. Массивы
- •Var a : Array[1..33000] Of Word;
- •Var a : Array[1..3] Of Real;
- •Var e,f : Massiv;
- •Var a : Array[1..10] Of Array[1..20] Of Real;
- •12. Процедуры и функции. Сфера действия описаний
- •13. Открытые массивы и нетипизированные параметры
- •14. Множества
- •15. Тип String
- •16. Графические средства языка Паскаль
- •17. Особенности вещественных вычислений
- •18. Записи
- •19. Тип "перечисление"
- •20. Модуль Crt
- •Var TextAttr : Byte
- •21. Модули. Создание и использование модулей
- •Interface
- •Implementation
- •22. Файлы
- •23. Другие средства обработки файлов и модуль dos
- •24. Процедурные типы
- •25. Указатели и динамическая память
- •26. Динамические структуры: списки, деревья
- •27.Открытые строки
- •28. Использование командной строки и вызов внешних программ
- •29. Обработка программных прерываний
- •30. Объекты
- •31.Рекурсия и динамическое программирование
- •32. Рекурсия и стек отложенных заданий
- •33. Стеки и очереди
- •34. Комбинаторные алгоритмы
- •35. Бинарные деревья
- •36. Упорядоченные бинарные деревья и приоритетные очереди
- •37. Алгоритмы сортировки
- •38. Графы
- •Рекомедуемая литература
- •Содержание
24. Процедурные типы
Язык Паскаль позволяет использовать в программе данные типа “процедура” или типа “функция”. Такие данные можно передавать как аргументы подпрограмм, можно описывать и использовать массивы процедур и массивы функций. Тип “процедура” описывается в операторе Type следующим образом:
Type имя типа=Procedure(список параметров);
Описание процедурного типа отличается от заголовка процедуры только отсутствием имени процедуры, список параметров записывается обычным образом. Если такой оператор Type есть в программе, то все дальние процедуры, записанные ниже и имеющие столько же параметров таких же типов (имена параметров значения не имеют), автоматически становятся объектами этого типа. Процедура называется дальней, если она откомпилирована в режиме F+, этого можно добиться двумя способами: или используя соответствующую опцию компилятора :
{$F+} Procedure A(x:Real; c:Char); Begin ... End; {$F-},
или записав после заголовка процедуры атрибут Far:
Procedure A(x:Real; c:Char); Far; Begin ... End;
Опция {$F+} действует до ее отмены опцией {$F-} или до конца программы, а атрибут Far - только на данную процедуру. Дальние объекты в программе имеют четырехбайтовые адреса, состоящие из сегмента и смещения, а ближние объекты имеют двухбайтовые адреса, содержащие только смещение, поскольку все они хранятся в одном сегменте данных. Если процедура находится в модуле, то она является дальней по умолчанию. Функциональный тип описывается так же, как процедурный:
Type имя типа=Function(список параметров):тип;
Данные функционального типа также обязаны иметь дальние адреса. Попробуем применить процедурные типы в реальной задаче. Вспомним алгоритм решения уравнения методом бисекции, описанный в разделе 17. Предположим, что нам требуется решить не одно уравнение, а много уравнений с различными левыми частями. Вместо того чтобы писать много практически одинаковых программ (они будут отличаться только одной функцией) или каждый раз модифицировать программу перед запуском, опишем соответствующий функциональный тип и будем передавать методу бисекции функцию как параметр. Чтобы не записывать несколько операторов вызова метода бисекции, опишем массив функций и будем обрабатывать их в цикле. Такая структура программы позволяет очень легко добавлять новые уравнения.
Const N_Func = 4; {количество уравнений - пока их четыре}
Type
T_Func = Function (x:Real):Real; {тип левой части уравнения}
T_Func_Array = Array[1..N_Func] Of T_Func; {тип массива функций}
T_Num_Array = Array[1..N_Func] Of Real; {тип числового массива}
Function f1(x:Real):Real; Far; Begin f1:=Sqr(x)*(Exp(-x)-1)+1; End;
Function f2(x:Real):Real; Far; Begin f2:=x*Sqr(Sqr(x))-Ln(2+Sqr(x)); End;
Function f3(x:Real):Real; Far; Begin f3:=Sqr(Sqr(x))*(Exp(-2*x)-1)+2; End;
Function f4(x:Real):Real; Far; Begin f4:=ArcTan(1+Sqr(x))-x*Sqr(x)/3; End;
Function Bisection(a,b:Real; f:T_Func):Real; {функция находит корень уравнения f(x)=0 на отрезке [a,b], функция f, вычисляющая левую часть уравнения, передается как параметр}
Var x,Fa,Fx : Real;
Begin
Fa:=f(a); x:=(a+b)/2;
While (x<>a)And(x<>b) Do Begin
Fx:=f(x); If Fx*Fa<0 Then b:=x Else a:=x; x:=(a+b)/2;
End;
Bisection:=x;
End;
Const
f : T_Func_Array = (f1,f2,f3,f4); {массив функций}
a : T_Num_Array =(0,0,0,0); { массив левых концов отрезка [a,b]}
b : T_Num_Array =(5,5,5,5); { массив правых концов отрезка [a,b]}
Var
n : Byte;
Root : Real;
Begin
WriteLn;
For n:=1 To N_Func Do Begin
Root:=Bisection(a[n],b[n],f[n]);
WriteLn('f',n,'(',Root:0:3,')=',f[n](Root):0:6);
End;
End.
Программа выведет
f1(1.197)=-0.000000
f2(1.022)=0.000000
f3(1.217)=-0.000000
f4(1.570)=-0.000000