Нетипизированные параметры

В Borland Pascal допускается использовать параметры, тип которых не указан. Такие параметры могут передаваться в подпрограмму только по ссылке, как параметры-переменные, так как в этом случае в подпрограмму реально передается адрес параметра.

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

Для приведения нетипизированного параметра к определенному типу можно использовать:

§ автоопределенное преобразование типов;

§ наложенное описание переменной определенного типа.

При автоопределенном преобразовании типов тип выражения указывают явно, например:

Procedure Proc(Var:a);

... ...

b:= Integer (a)+10; ...

Для наложения переменной определенного типа используют описание с absolute, например:

Procedure Proc(Var:a);

...

Var

r:real absolute a;...

При этом переменная r оказывается в памяти размещенной в том же месте, что и нетипизированный параметр а, и, соответственно, любое изменение r приведет к изменению а.

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

Тип массива подпрограмма будет определять по значению третьего параметра, для которого объявим специальный перечисляемый тип. В разделе описаний подпрограммы определим шаблоны для каждого случая. Шаблон представляет собой описание массива соответствующего типа максимально возможного размера 64 Кб/<размер элемента>. Оба шаблона наложены по адресу нетипизированного параметра. Если значение третьего параметра подпрограммы treal, то используется шаблон mr, а если tinteger - шаблон mi.

Unit Summa4;

Interface

Type ttype=(treal, tinteger); {описание типа третьего параметра}

Function sum(var x;n:integer;t:ttype):real;

Implementation

Function sum;

Var mr:array[l..maxint*2 div sizeof(real)] of real absolute x;

mi:array[L.maxint*2 div sizeof(integer)J of integer absolute x;

s:real;

i:integer;

begin

s:=0;

if t=treal then

for i:=l to n do s:=s+mr[i] else

for i:-l to n do s:=s+mi[ij;

sum: =s;

end;

End.

Тестирующая программа вызывает одну и ту же функцию для суммирования массивов с разным типом элементов.

Program ex;

Uses Summa4;

 

Var a: array [1..10] of integer;

b:array[1..15] of real;

i,n: integer;

Begin

for i:=l to 10 do Read(a[i]);

ReadLn;

WriteLn('Cyммa= ',sum (a, 10, tinteger): 8: l);

for i:=l to 15 do Read(b[i]);

ReadLn;

WriteLn('Cyммa= ',sum (b, 15, treal):8:l);

end.

Вместо описания массива максимально возможного размера в подпрограмме можно описать массив длиной 1 элемент, но при работе с таким шаблоном необходимо отключать контроль индексов {$R-}.

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

b1,1,1, b1,1,2, b1,2,1, b1,2,2, b1,3,1, b1,3,,2, b2,1,1, b2,1,2, b2,2,1, b2,2,2, b2,3,1, b2,3,2.

Пример 2. Разработать универсальную подпрограмму транспонирования матрицы.

В одномерном массиве элемент с индексами i и j имеет индекс (i-l)*P+j, т.е. индекс этого элемента зависит от размера строки зарезервированной матрицы. В подпрограмму это значение передается через параметр Р.

Чтобы транспонировать матрицу, меняем местами элементы, расположенные ниже и выше главной диагонали.

При разработке алгоритма процедуры учтено, что при транспонировании матрицы по аналогии с переворотом строки количество перестановок равно n*n div 2. Если выполнить n*n перестановок, то матрица примет исходный вид, так как будет транспонирована дважды.

Unit Matrica;

Interface

Procedure tran(Var x;n,P:integer);

Implementation

Procedure Iran;

Var a:array[1..2*maxint div sizeof(real)] of real absolute x;

i,j:integer;

t:real;

begin

for i: =2 to n do

for j:=l to i-1 do

begin

t:=a[(i-l)*P+j];

a [(i-l) *P+j]. =a [j-l) *P+i],

a[(J-l)*P+i] := t;

end;

end;

End.

Тестирующая программа выглядит следующим образом:

Program ex;

Uses Matrica;

Var a: array [1 ..10,1. .10] of real;

i,j: integer;

Begin

WriteLn(‘Введите матрицу a(5*5):');

for i:=l to 5 do

begin

forj:=l to 5 do Read(afiJJ);

ReadLn;

end;

tran(a,5,10);•

WriteLn('Результат:');

for i:=I to 5 do

begin

forj:=l to 5 do Write(a[ij]:6:2);

WriteLn;

end;

End.

 

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

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

Для объявления процедурного типа используют заголовок подпрограммы, в котором отсутствует имя, например:

Type proc=procedure (a,b,c:real;Var d:real);

func=function(x:real) :real;

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

Var f:func;

f:=funl;...

Процедуры или функции, идентификаторы которых будут передаваться в качестве параметров процедурного типа, по правилам языка необходимо компилировать в режиме дальнего вызова (с указанием директивы компилятора {$Р+}или служебного слова far). В этом режиме при вызове подпрограмм используются длинные 4-байтовые адреса в отличие от коротких 2-байтовых адресов, которые применяются для адресации подпрограмм, объявленных в основной программе или ее подпрограммах.

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

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

Пример 3. Разработать подпрограмму, которая возвращает массив значений произвольной функции при заданных интервале изменения аргумента [а,b] и количестве точек n.

Имя функции будем передавать в подпрограмму через параметр процедурного типа. Массив значений будем описывать как открытый:

Unit SFun;

Interface

Typefunc=function(x:real):real;

Procedure TabFun(f:func;a, b:real;n: integer;Var Masf:array of real);

Implementation

Procedure TabFun;

Var

h,x:real;

r.integer;

Begin

h:=(b-a)/(n-l);

for i:=0 to n-1 do Masf[i]:=f(a+h*i);

End;

End.

Основная программа должна описать конкретную функцию как функцию дальнего вызова. Для функции sin создается специальная функция дальнего вызова.

Program ex;

Uses SFun;

Var

masFl :array[1.. 10] of real;

masF2: array [1.. 20] of real;

i: integer;

function Fl(x:real): real; far;

Begin

Fl:=sin(x);

end;

function F2(x:real) :real; far;

Begin

F2:=exp(x)+cos(x);

end;

Begin

WriteLn(' Таблица значений функции sin x:');

TabFun(Fl, 0,2,10,masFl);

for i:=l to 10 do Write(masFl[i]:7:l);

Writeln;

WriteLn(' Таблица значений функции ехр x+cos x:');

TabFun(F2, 0,2, 20, masF2); for i:=l to 20 do Write(masF2[i]:7:l);

Writeln;

End.

 

Рекурсия

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

N! = 1, если N=0;

N*(N-l)!, если N>0.

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

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








Дата добавления: 2015-12-01; просмотров: 1178;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.018 сек.