Главная » Free Pascal » Параметры подпрограмм — одномерные массивы Free Pascal

0

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

   Листинг 9 .4 .  Программа  arg_array1                                           

program arg_array1;

type

ar5=array [1..5] of integer; var

a:ar5 = (2,1,3,0,5);

//———————————–

function max1(b:ar5):integer;

// Массив передается по значению и загромождает стек var i,j:integer;

begin

j:=Low(b);      // минимальная граница индекса Result:=b[j];   // пробный максимум – первый элемент for i:=j+1 to High(b) do

if Result < b[i] then Result:=b[i]; end;

//——————————————–

function max2(var b:ar5):integer;

// Массив передается по адресу, и его элементы можно изменить var i,j:integer;

begin

j:=Low(b);      // минимальная граница индекса Result:=b[j];

for i:=j+1 to High(b) do

if Result < b[i] then Result:=b[i]; end;

//———————————————-

function max3(const b:ar5):integer;

// Массив передается по адресу, но его элементы изменить нельзя var i,j:integer;

begin

j:=Low(b);      // минимальная граница индекса Result:=b[j];

for i:=j+1 to High(b) do

if Result < b[i] then Result:=b[i]; end;

//———————————————-

function max4(var b; n:integer):integer;

// Массив передается как указатель без типа.

// Использовано приведение типа.

// n – число элементов в массиве.

type

int=array [0..(MaxInt div 4)-1] of integer;

var i:integer; begin

Result:=int(b)[1]; for i:=1 to n-1 do

if Result<int(b)[i] then Result:=int(b)[i]; end;

//————————————————

function max5(var b;n:integer):integer;

// Массив передается как указатель без типа.

// Использовано приведение к абсолютному адресу. var

a:array [0..0] of integer absolute b;

i:integer; begin

{$R-}           // отключение контроля за индексами Result:=a[0];

for i:=1 to n-1 do

if Result<a[i] then Result:=a[i];

{$R+}           // включение контроля за индексами end;

//————————————————-

function max6(b : array of integer):integer;

// Использование открытого массива var i:integer;

begin

Result:=b[0];

for i:=1 to High(b) do

if Result < b[i] then Result:=b[i]; end;

//————————————————–

begin

writeln(‘Max1 = ‘,max1(a));

writeln(‘Max2 = ‘,max2(a));

writeln(‘Max3 = ‘,max3(a));

writeln(‘Max4 = ‘,max4(a,5));

writeln(‘Max5 = ‘,max5(a,5));

writeln(‘Max6 = ‘,max6(a)); end.

Результаты работы программы arg_array1 приведены на рис. 9.2.

Рис. 9.2. Максимальный элемент в одномерном массиве

Функции max1, max2, …, max5 реализованы в традициях ранних версий языка Паскаль.

Формальный аргумент функции max1 описан с применением глобального типа ar5. Это означает, что функция max1 может обрабатывать массивы только указан- ного типа. И если в рамках вашей программы приходится обрабатывать массивы других размерностей, то нужно подключать другие функции. За такой подход Пас- каль справедливо подвергался нападкам. Дополнительный недостаток функции max1 заключается в том, что в стек записываются все элементы обрабатываемого массива. А это расточительно как с точки зрения использования памяти, так и до- полнительных потерь времени на передачу исходных данных.

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

фиксированной размерности. И хотя в ее теле задействованы универсальные функ- ции Low и High, компилятор забракует все обращения, в которых тип фактического аргумента отличается от ar5.

Функция max3 отличается от функции max2 только тем, что ее аргумент может

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

В функции max4 реализован более прогрессивный подход, позволяющий обра- батывать массивы любой длины. Первый ее аргумент определяет начальный адрес обрабатываемого массива, а второй — задает количество элементов в массиве. Чтобы не нарушить правила использования нетипизированного параметра b, его приводят к типу с именем int, представляющему целочисленный массив с огром- ным диапазоном по индексу. Память для массива такого размера никто выделять не собирается, т. к. фактический массив, передаваемый в качестве значения аргумента b, уже находится в памяти среди набора данных вызывающей программы. А мак- симально допустимый индекс в типе int не позволит нарушить границы индексов в цикле обработки элементов приведенного массива. Дополнительным преимущест- вом функции max4 является возможность определения максимального элемента в любом фрагменте массива. Для этого в качестве первого фактического аргумента достаточно задать имя первого элемента фрагмента, а в качестве второго фактиче- ского аргумента — длину фрагмента.

В функции max5, по существу, реализован аналогичный поход. Здесь объявлен локальный массив а минимального размера — он содержит единственный элемент a[0] и его адрес совпадает с начальным адресом параметра b (указание …absolute b). Чтобы отключить контроль за индексами элементов массива a, который неизбеж- но будет нарушен при n>0, на время работы цикла контроль блокируется.

Самый современный подход, связанный с использованием открытых масси- вов, реализован в функции max6. Формальный параметр, называемый открытым массивом, описывается в заголовке подпрограммы без указания границ индексов. Принято, что минимальный индекс элементов открытого массива равен 0, а макси- мальный определяется функцией High. Поэтому в функции max6 не приходится за- ниматься приведением типов, изменением режима контроля за индексами и прочи- ми ухищрениями, которые были использованы в функциях max4 и max5. На практике придерживаются следующего правила — для создания универсальных подпрограмм, которые могут обрабатывать массивы любой длины, всегда старай- тесь использовать открытые массивы.

Если параметром подпрограммы является открытый массив, то в качестве фак- тического аргумента может быть задан так называемый конструктор массива: y:=max6([5,7,x,x+z]);

Такое обращение эквивалентно следующим традиционным действиям:

var

x,y,z:integer; a:array[0..3];

…………….

x:=…;

z:=…;

a[0]:=5;

a[1]:=7;

a[2]:=x;

a[3]:=x+z;

y:=max6(a);

Однако есть и принципиальное внутреннее отличие: если фактическим аргу- ментом является настоящий массив, то функция max6 получает его адрес. Если же использован конструктор массива, то в стеке создается его копия, и подпрограмма получает адрес копии.

Применение открытого массива в функции max6 предоставляет еще одну воз- можность, которой не может похвастаться большинство других алгоритмических языков. Пусть у нас имеется целочисленный массив b, объявленный с интервалом индексов от 1 до 100. Тогда допустимы следующие обращения к функции max6: y1:=max6(b[1..50]);  // поиск максимума в первой половине массива

y2:=max6(b[51..100]); // поиск максимума во второй половине массива

Источник: Кетков, Ю. Л., Свободное программное обеспечение. FREE PASCAL для студентов и школьников, Ю. Л. Кетков, А. Ю. Кетков. — СПб.: БХВ-Петербург, 2011. — 384 с.: ил. + CD-ROM — (ИиИКТ)

По теме:

  • Комментарии