Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
программирование на паскале2.doc
Скачиваний:
144
Добавлен:
31.03.2015
Размер:
935.94 Кб
Скачать

2.3. Функции Паскаля

2.3.1. Описание функций

Описание функций дается в разделе процедур и, также как описание процедур общего вида, состоит из заголовка и блока. Заголовок функции имеет вид:

functionИмяФункции[(СписокФормалПараметров)]:ТипФункции;

Если имя процедуры общего вида обозначает описываемый ей алгоритм, то имя функции, кроме того, служит для обозначения выходного параметра (единственного или основного). Под типом функции подразумевается тип выходного параметра. Этот тип обязательно простой. В разделе действий функции обязательно должен иметься оператор присваивания, в левой части которого стоит имя функции, так как выходное значение должно быть определено. B правой части оператора присваивания имя функции воспринимается только как обращение18к функции. Tак, например, в функции SUM, вычисляющей сумму элементов массива А, оператор

SUM:=SUM+A[i];

неприменим, а для накопления суммы в разделе действий вместо SUM надо использовать другое обозначение (см.также пример из §2.3.2):

S:=0; ...

S:=S+A[i]; ...

SUM:=S;

2.3.2. Обращение к функции

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

ИмяФункции[(Список фактических параметров)];

Указатель функции может стоять только в правой части оператора присваивания.

Пример.Вычислить значение У:

где a=(a1,…,a10),b=(b1,…,b5) - заданные последовательности.

Вычисление суммы и произведения и ввод элементов массива требуется производить 2 раза (для aиb), поэтому эти алгоритмы стоит оформить как подпрограммы. Каждая из подпрограмм вычисления суммы и произведения имеют одно выходное значение, поэтому это будут функции. Подпрограммы рассчитаны на массивы с размером, не превыщающим 10. Текст программы приведен ниже.

program primer_2_3;

type mas=array[1..10] of real;

var a,b:mas; y:real; pra:real;

function sum(var v:mas; n:integer):real;

{функция вычисляет сумму первых n (n<=10) элементов массива v}

var s:real; i:integer;

begin

s:=0;

for i:=1 to n do

s:=s+v[i];

sum:=s;

end;{конец функции sum}

function pr(var v:mas; n:integer):real;

{функция вычисляет произведение первых n(n<=10) массива v}

var p:real; i:integer;

begin

p:=1;

for i:=1 to n do

p:=p*v[i];

pr:=p;

end; {конец функции pr}

procedure masin(var v:mas; n:integer);

{процедура осуществляет ввод массива v размером n (n<=10),

приглашение к вводу не включено в процедуру, поэтому в списке

параметров нет символьной переменной –имени массива –

ср. с примером п.2.2}

var i:integer;

begin

for i:=1 to n do

read(v[i]);

readln;

end; {конец процедуры masin}

BEGIN

writeln(' BBEДИТЕ МАССИВ А ИЗ 10 ЭЛЕМЕНТОВ');

masin(a,10);

writeln(' ВВЕДИТЕ МАССИВ В ИЗ 5 ЭЛЕМЕНТОВ');

masin(b,5);

pra:=pr(a,10);

if pra =0 then

writeln(' ЗНАМЕНАТЕЛЬ РАВЕН НУЛЮ')

else

begin

y:=(sum(a,10)*(pr(b,5)+5)-sum(b,5))/pra;

writeln(' ЗНАЧЕНИЕ ВЫРАЖЕНИЯ; y=',y:9:3);

end;

readln;

END.

2.4. Глобальные и локальные имена

Каждая процедура (функция) может иметь свой раздел процедур, а описанные в нем процедуры также могут иметь внутренние процедуры. Таким образом, может иметь место последовательность вложенных блоков.

Понятие глобальных и локальных имен имеет смысл только относительно некоторого блока.

Глобальные имена - это имена, которые действуют на протяжении всей программы (или внешнего блока), они объявляются в соответствуюших разделах программы (или внешнего блока).

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

К локальным именам относятся формальные параметры и все имена, описанные в блоке подпрограммы. Вне блока подпрограммы локальные имена неопределены.

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

В Паскале данные, описанные в блоке программы, хранятся в так называемом статическом сегменте памяти; память под них распределяется при компиляции.

Локальные данные подпрограммы хранятся в специальной области оперативной памяти – стеке; память под эти данные распределяется каждый раз при вызове подпрограммы и освобождается при завершении работы подпрограммы. Если имеется цепочка вложенных обращений к подпрограммам, например, программа вызывает подпрограмму Р1, Р1 вызывает подпрограмму Р2, а Р2 – Р3, то схема заполнения стека будет соответствовать рис. 15; порядок освобождения стека: сначала уходит Р3, затем Р2, затем Р1.

Важными являются понятия области действияимени ивремени жизниданных.

Область действия имени - это часть программы, в которой имя может быть доступно. Таким образом, область действия локального имени - блок подпрограммы, в которой оно объявлено; глобального – весь текст программы от места объявления до последнего словаEnd(с точкой). Глобальное имя доступно в подпрограмме только в том случае, если в подпрограмме оно не объявлено еще раз.

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

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

Program Primer;

Var a,i:real;

Procedure p1;

Var i:real;

Begin . . . a:=...; i:=...;

End{p1};

Procedure p2;

Var i:real;

Begin . . . a:=...; i:=...;

End{p2};

Begin {раздел действий программы}

i:=...; a:=...;

р1; р2; р2

End.

a-глобальная переменная, под нее отведена одна ячейка в статическом сегменте памяти, которая доступна программе и процедурам р1 и р2. Под переменную с именем iпрограммы отводится ячейка памяти статического сегмента; под переменныеiпроцедур память в стеке распределяется столько раз, сколько раз осуществляется вход в блок процедур (в нашем примере три раза: при вызове р1 и при каждом вызове р2); при выходе из блока (т. е. при завершении работы процедуры) ячейка с именем i каждый раз освобождается. Так как в каждой процедуре имеется локальное имя i, глобальное i программы в процедурах недоступно.

В данной программе область действия переменной а – вся программа, включая процедуры, время ее жизни – все время работы программы. Область действия глобальной переменной i– текст программы, за исключением процедур; время ее жизни – все время работы программы. Область действия локальнойi– текст процедуры, в которой она объявлена, время ее жизни – время работы соотвествующей процедуры.

Рекомендации

  1. Не стоит делать глобальными промежуточные переменные (например, iв программе вычисления выражения примера §2.3.2), потому что:

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

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

  1. Однако допустимо использование глобальных переменных для передачи данных между подпрограммами(если не требуется подстановка параметров). Так, если бы в примере п.2.2.2 требовалось обработать одну матрицу, то можно было бы использовать процедуры без параметров, как сделано в приведенной ниже программе.

program primer2_4;

{вычисление минимальных значений элементов строк матрицы a[3*5]}

Type matr=array[1..3,1..5] of real;

mas= array[1..3] of real;

Var a:matr; min:mas; {далее-раздел процедур и функций}

Procedure minstr;

Var i,j:integer;

Begin

for i:=1 to 3 do

begin

min[i]:=a[i,1];

for j:=1 to 5 do

if min[i]>a[i,j] then

min[i]:=a[i,j];

end

End{minstr};

Procedure matrin;

Var i,j:integer;

Begin

Writeln('Введите матрицу размером 3*5');

for i:=1 to 3 do

for j:=1 to 5 do

read(a[i,j]);

readln;

End{matrin};

Procedure masout;

Var i:integer;

Begin

Writeln('Минимальные значения строк матрицы ');

for i:=1 to 3 do

writeln(' ',min[i]);

End{masout};

{далее - раздел действий программы}

Begin

matrin;

minstr;

masout;

readln

End.

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

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

  2. усложняет автономную отладку подпрограмм.

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