TURBO PASCAL

Новости       

Программы

Turbo Pascal

Игры

Документация

"Странности"

FAQ

Ссылки

Благодарности 

Гостевая книга

Спонсор

От автора

Глава 9. Процедуры и функции

·        Описания процедур

·        Описания функций

·        Параметры

·        Параметры-значения

·        Параметры-константы

·        Параметры-переменные

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

·        Открытые параметры

·        Открытые строковые параметры

·        Открытые параметры-массивы

 

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

Примечание: Определение блока вы можете найти в Главе 8 "Блоки, локальность и область действия".

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

 

Описания процедур

Описание процедуры позволяет связать идентификатор с проце­дурным блоком. Процедуру можно затем активизировать с помощью оператора процедуры.

Заголовки процедур именуют идентификаторы процедур и задают формальные параметры (если они имеются).

Примечание: Синтаксис списка формальных параметров по­казан далее в этой главе в разделе "Параметры".

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

Приведем пример описания процедуры:

procedure NumString(N: integer; var S: string);

var

V: integer; begin

V := Abs(N);

S := ''; repeat

S := Chr(N mod 10 + Ord('0')) + S; N := N div 10;

until N = 0;

if N < 0 then S := '-' + S;

end;

Возврат в начало

 

 

Описания функций

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

Примечание: Функция не может возвращать процедурный тип или структурный тип.

В заголовке функции определяется идентификатор функции, фор­мальные параметры (если они имеются) и тип результата функции.

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

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

Если идентификатор функции используется при вызове функции внутри модуля-функции, то функция выполняется рекурсивно.

Приведем далее примеры описаний функции:

function Max(a: Vector; n: integer): extended;

var

x: extended;

i: integer;

begin

x := a(1);

for i := 2 to n do if x < a[i] then x := a[i];

Max := x; end;

function Power(x: extended; y: integer): extended;

var

z: extended;

i: integer;

begin

z := 1.0; i := y;

while i > 0 do

begin

if Odd(i) then z := z*x;

x := Sqr(x);

end;

Power := z; end;

Аналогично процедурам функции могут описываться, как с ближ­ним типом вызова (near), с дальним типом вызова (far), опережаю­щие (forward), внешние (external), ассемблерные (assembler) или подставляемые (inline). Однако функции прерываний (interrupt) не допускаются.

Возврат в начало

 

 

Параметры

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

 

Существует три типа параметров: значение, переменная и нети­пизированная переменная. Они характеризуются следующим:

1.      Группа параметров без предшествующего ключевого слова является списком параметров-значений.

2.      Группа параметров, перед которыми следует ключевое слово const и за которыми следует тип, является списком пара­метров-констант.

3.      Группа параметров, перед которыми стоит ключевое слово var и за которыми следует тип, является списком типи­зированных параметров-переменных.

4.      Группа параметров, перед которыми стоит ключевое слово var или const за которыми не следует тип, является спис­ком нетипизированных параметров-переменных.

Параметры строкового типа и массивы могут быть открытыми па­раметрами. Параметры-переменные, описанные с помощью идентифика­тора OpenString или с использованием ключевого слова string в состоянии $P+, являются открытыми строковыми параметрами. Зна­чение, константа или параметр-переменная, описанные с помощью синтаксиса array of T, являются открытым параметром-массивом.

Примечание: Подробнее об открытых параметрах рассказы­вается ниже.

Возврат в начало

 

 

Параметры-значения

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

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

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

Возврат в начало

 

 

Параметры-константы

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

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

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

Возврат в начало

 

 

Параметры-переменные

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

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

Примечание: Файловый тип может передаваться только, как параметр-переменная.

Директива компилятора $P управляет смыслом параметра-пере­менной, описываемого с ключевым словом string. В состоянии по умолчанию ($P-) string соответствует строковому типу с атрибу­том размера 255. В состоянии $P+ string указывает, что параметр является открытым строковым параметром (см. ниже).

При ссылке на фактический параметр-переменную, связанную с индексированием массива или получением указателя на объект, эти действия выполняются перед активизацией процедуры или функции.

Правила совместимости по присваиванию для объектного типа применяются также к параметрам-переменным объектного типа. Для формального параметра типа T1 фактический параметр должен быть типа T2, если T2 находится в домене T1. Например, с учетом опи­саний Главы 4, методу TField.Copy может передаваться экземпляр TField, TStrField, TNumField, TZipField или любой другой экземп­ляр потомка TField.

Возврат в начало

 

 

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

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

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

Приведем пример нетипизированных параметров-переменных:

function Equal(var source,dest; size: word): boolean;

type

Bytes = array[0..MaxInt] of byte; var

N: integer; begin

N := 0;

while (N<size) and (Bytes(dest)[N] <> Bytes(source)[N]

do Inc(N);

Equal := N = size; end;

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

type

Vector = array[1..10] of integer;

Point = record

x,y: integer;

end;

var

Vec1, Vec2: Vector;

N: integer;

P: Point;

и вызовов функций:

Equal(Vec1,Vec2,SizeOf(Vector))

Equal(Vec1,Vec2,SizeOf(integer)*N)

Equal(Vec[1],Vec1[6],SizeOf(integer)*5)

Equal(Vec1[1],P,4)

сравнивается Vес1 с Vес2,  сравниваются первые N элементов Vес1 с

первыми N элементами Vес2, сравниваются первые 5 элементов Vес1 с

последними пятью элементами Vес2 и сравниваются Vес1[1] с  Р.х  и

Vес2[2] с P.Y.

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

Возврат в начало

 

 

Открытые параметры

Открытые параметры позволяют передавать одной и той же про­цедуре или функции строки и массивы различных размеров.

Возврат в начало

 

 

Открытые строковые параметры

Открытые строковые параметры могут описываться двумя спосо­бами:

·        с помощью идентификатора OpenString;

·        с помощью ключевого слова string в состоянии $P+.

Идентификатор OpenString описывается в модуле System. Он обозначает специальный строковый тип, который может использовать­ся только в описании строковых параметров. В целях обратной сов­местимости OpenString не является зарезервированным словом и мо­жет, таким образом, быть переопределен как идентификатор, задан­ный пользователем.

Когда обратная совместимость значения не имеет, для измене­ния смысла ключевого слова string можно использовать директиву компилятора $P+. В состоянии $P+ переменная, описанная с клю­чевым словом string, является открытым строковым параметром.

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

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

В следующем примере параметр S процедуры AssignStr - это открытый строковый параметр:

procedure AssignStr(var S: OpenString;

begin

S := '0123456789ABCDEF'; end;

Так как S - это открытый строковый параметр, AssignStr можно передавать переменные любого строкового типа:

var

S1: string[10];

S1: string[20]; begin

AssignStr(S1);                                S1 := '0123456789'

AssignStr(S2);                                S2 := '0123456789ABCDEF'

end;

В AssingStr максимальная длина параметра S та же самая, что у фактического параметра. Таким образом, в первом вызове AssingStr при присваивании параметра S строка усекается, так как максимальная длина S1 равна 10.

При применении к открытому строковому параметру стандартная функция Low возвращает 0, стандартная функция High возвращает описанную максимальную длину фактического параметра, а функция SizeOf возвращает размер фактического параметра.

В следующем примере процедура FillString заполняет строку заданным символом до ее максимальной длины. Обратите внимание на использование функции High для получения максимальной длины отк­рытого строкового параметра.

procedure FillStr(var S: OpenString; Ch: Char);

begin

S[0] := Chr(High(S));                               задает длину строки

FillChar(S[1], High(S), Ch);  устанавливает число символов

emd;

Значения и параметры-константы, описанные с использованием идентификатора OpenString или ключевого слова string в состоянии $P+, не являются открытыми строковыми параметрами. Они ведут себя также, как если бы были описаны с максимальной длиной стро­кового типа 255, а функция Hingh для таких параметров всегда возвращает 255.

Возврат в начало

 

 

Открытые параметры-массивы

Формальный параметр, описанный с помощью синтаксиса:

array of T

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

array[0..N - 1] of T

где N - число элементов в фактическом параметре. По существу, диапазон индекса фактического параметра отображается в диапазон целых чисел от 0 до N - 1. Если фактический параметр - это прос­тая переменная типа T, то он интерпретируется как массив с одним элементом типа T.

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

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

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

При применении к открытому параметру-массиву стандартная функция Low возвращает 0, стандартная функция High возвращает ин­декс последнего элемента в фактическом параметре-массиве, а функ­ция SizeOf возвращает размер фактического параметра-массива.

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

procedure Clear(var A: array of Real);

var

I: Word; begin

for I := 0 to High(A) do A[I] := 0; end;

function Sum(const A: array of Real): Real;

var

I: Word;

S: Real; begin

S := 0;

for I := 0 to High(A) do S := S + A[I];

Sum := S; end;

Когда типом элементов открытого параметра-массива является Char, фактический параметр может быть строковой константой. Нап­ример, с учетом предыдущего описания:

procedure PringStr(const S: array of Char);

var

I: Integer; begin

for I := 0 to High(S) do

if S[I] <> #0 then Write(S[I]) else Break;

end;

и допустимы следующие операторы процедур:

PrintStr('Hello word');

PrintStr('A');

При передаче в качестве открытого параметра-массива пустая строка преобразуется в строку с одним элементом, содержащим сим­вол NULL, поэтому оператор PrintStr('') идентичен оператору PrintStr('#0').

 

Возврат в начало

 

На первую страницу

Rambler's Top100 PROext: Top 1000
Rambler's Top100

(с) Все права защищены.

По всем интересующим вопросам прошу писать электронный адрес

Hosted by uCoz