Вопрос 19.
Функции пользователя.
Подпрограмма – процедура предназначена для выполнения какой–то законченной последовательности действий. Любая процедура оформляется аналогично основной программе (содержит заголовок, разделы описаний и операторов). В отличие от основной программы заголовок в процедуре обязателен.
Формат описания процедуры:
procedure <имя процедуры> (<список формальных параметров>);
|
begin
|
end;
Раздел описаний процедуры может содержать подразделы: метки, константы, типы, переменные, процедуры и функции. Раздел описаний в процедуре может отсутствовать.
Для вызова процедуры из основной программы или другой подпрограммы следует записать оператор, состоящий из имени процедуры и списка фактических параметров, которые должны совпадать по количеству и типам с формальными параметрами процедуры.
Формат вызова процедуры:
<имя процедуры> (<список фактических параметров>);
6.3. Функция
Подпрограмма – функция предназначена для нахождения значения какого – либо параметра. У этой подпрограммы два основных отличия от процедуры.
Первое отличие функции в ее заголовке.
Формат описания функции:
function <имя функции> (<список форм. параметров>):<тип функции>;
|
begin
|
end;
Раздел описаний функции может содержать подразделы: метки, константы, типы, переменные, процедуры и функции. Раздел описаний может отсутствовать.
Второе отличие заключается в том, что в теле функции (раздел операторов) хотя бы один раз имени функции должно быть присвоено значение.
Для вызова функции из основной программы или другой подпрограммы следует в выражении, где необходимо использовать значение функции, указать ее имя со списком фактических параметров, которые должны совпадать по количеству и типам с формальными параметрами функции.
6.4. Глобальные и локальные данные
Процедуры и функции обладают определенной независимостью в смысле использования переменных, а также типов и констант. При описании в программе переменных (типов, констант) происходит их разделение на глобальные и локальные.
Глобальные переменные (типы, константы) – это те, которые объявлены в программе вне процедур или функций. Они действуют в основной программе и в любой подпрограмме. Процедуры и функции используют и модифицируют глобальные данные, если эти данные описаны в тексте основной программы выше описаний соответствующих процедур и функций.
Локальные данные – это константы, типы и переменные, существующие только внутри процедур и функций, и объявленные либо в списке параметров (только переменные), либо в разделах const, type, var этих процедур и функций. Такие данные недоступны для операторов основной программы.
При совпадении имен глобальных и локальных данных сильнее оказываются локальные имена, и именно они используются внутри подпрограммы.
6.5. Формальные и фактические параметры
Формальные параметры подпрограммы указывают, с какими параметрами следует обращаться к этой подпрограмме (количество параметров, их последовательность, типы). Они задаются в заголовке подпрограммы в виде списка формальных параметров, разбитого на группы, разделенные ";". В группу формальных параметров включаются однотипные параметры одной категории.
Все формальные параметры можно разбить на четыре категории:
– параметры – значения (значения этих параметров в основной про–
грамме подпрограммой не меняются);
– параметры – переменные (значения этих параметров подпрограм–
ма может изменять в основной программе);
– параметры – константы (используются только в версии 7.0);
– параметры – процедуры и параметры – функции.
Для каждого формального параметра следует указать имя, тип, а в случае параметра – переменной или параметра – константы – его категорию (слово – идентификатор). Имена параметров могут быть любыми, в том числе и совпадать с именами объектов программы. Необходимо помнить, что в этом случае параметр основной программы с таким именем становится недоступным для непосредственного использования подпрограммой. Тип формального параметра может быть любым, однако в заголовке подпрограммы нельзя вводить новый тип, то есть типом параметра в списке формальных параметров может быть только стандартный или ранее объявленный тип.
Например, нельзя писать
function day (dn : (Pn, Vt, Sr, Ch, Pt, Sb, Vs)):integer;
Чтобы правильно написать этот заголовок, следует в основной программе ввести перечисляемый тип, а затем использовать его в заголовке:
type
days=(Pn, Vt, Sr, Ch, Pt, Sb, Vs);
function day (dn : days) : integer;
При обращении к подпрограмме формальные параметры заменяются на соответствующие фактические вызывающей программы или подпрограммы.
6.5.1. Параметры – значения
Параметры – значения передаются основной программой в подпрограмму через стек в виде их копий и, следовательно, собственный параметр программы подпрограммой изменяться не может. Суть механизма передачи параметра по значению состоит в следующем. При обращении к подпрограмме:
1) выделяется место в памяти машины для каждого формального параметра;
2) вычисляется значение фактического параметра;
3) это значение засылается в ячейку, соответствующую формальному пара–
метру.
После получения начального значения связь между формальными и фактическими параметрами утрачивается. Значение формального параметра в теле процедуры может изменяться. После окончания работы процедуры формальный параметр утрачивает свое значение. Фактические параметры сохраняют те значения, которые имели до обращения к подпрограмме. Если даже фактические и формальные параметры одинаково обозначены в программе, в памяти ЭВМ они занимают разные ячейки.
Выводы:
а) формальные параметры – значения используют для передачи ис–
ходных данных в подпрограмму;
б) параметры – значения нельзя использовать для передачи результа–
тов из подпрограммы в основную программу;
в) в качестве фактического параметра, соответствующего формаль–
ному параметру – значению может быть использовано любое вы–
ражение, переменная, константа того же типа, что и формальный
параметр – значение.
Параметр – значение указывается в заголовке подпрограммы своим именем и через ":" – типом. Тип параметра – значения может быть любым за исключением файлового.
Если параметров – значений одного типа несколько, их можно объединить в одну группу, перечислив их имена через ",", а затем уже указать общий тип.
Пример 1. procedure Inp (Max, Min : real; N : Word);
function Mult (X,Y : integer) : real;
В качестве фактического параметра на месте параметра - значения при вызове подпрограммы может выступать любое выражение совместимого для присваивания типа, не содержащее файловую компоненту.
Inp (abs(Z), –abs(T), 2*k);
M := Mult (X+Y, X–Y);
Пример 2. Пусть в программе необходимо многократно вычислять площадь квадрата S1 = a*a и площадь прямоугольника S2 = a*b при различных значениях a и b. Оформить вычисление этих площадей, используя подпрограмму – функцию.
program PL_FIGUR;
var A, B : real; S1, S2 : real;
function PL(X, Y : real): real;
begin
PL:= X*Y
end;
{основная программа}
begin
Write('Введите значения A, B:');
Readln(A, B);
S1:= PL(A, A); {вызов подпрограммы: S квадрата}
S2:= PL(A, B); {вызов подпрограммы: S прямоугольника}
Writeln('S1=', S1:5:2, ', S2=', S2:5:2)
end.
Пример 3. Даны отрезки a, b, c и d. Для каждой тройки этих отрезков, из которых можно построить треугольник, напечатать площадь данного треугольника. При решении задачи использовать подпрограмму – процедуру PR_SQ (X, Y, Z), печатающую площадь треугольника со сторонами x, y и z, если такой треугольник существует.
program S_TREUG;
var A, B, C, D : real;
procedure PR_SQ(X, Y, Z : real);
var P : real;
begin if (X+Y>Z) and (Y+Z>X) and (Z+X>Y) then
begin P:= (X+Y+Z)/2;
Writeln(sqrt(P*(P–X)*(P–Y)*(P–Z)):6:2) end
end;
{основная программа}
begin
Write('Введите длины отрезков A, B, C, D:'); { A, B, C, D > 0}
Readln(A, B, C, D);
{вызов процедуры PR_SQ выполняется 4 раза для вычисления площадей
треугольников со сторонами : A, B, C; A, B, D; A, C, D; B, C, D при вы–
полнении условия существования этих треугольников}
PR_SQ(A, B, C); PR_SQ(A, B, D);
PR_SQ(A, C, D); PR_SQ(B, C, D)
end.
6.5.2 Параметры – переменные.
При передаче параметров – переменных в подпрограмму фактически через стек передаются их адреса в порядке, объявленном в заголовке подпрограммы. Следовательно, подпрограмма имеет доступ к этим параметрам и может изменять их значения. Механизм передачи параметра по ссылке состоит в следующем:
1. Параметр – переменная указывается в заголовке подпрограммы аналогично параметру – значению, но только перед именем параметра записывается зарезервированное слово var. Действие слова var распространяется до ближайшей точки с запятой, т.е. в пределах одной группы переменных. Например,
procedure T1(var X, Y : real; I, J : integer);
где X, Y – параметры – переменные, а I, J – параметры – значения.
2. При обращении к подпрограмме происходит передача формальному параметру – переменой адреса фактического параметра, а не его значения. При всяком упоминании в подпрограмме параметра, переданного по ссылке, компилятор будет использовать область памяти, отведенную для аргумента из главной программы. Таким образом, всякое изменение в значении формального параметра фактически будет и изменением в значении соответствующего аргумента.
3. Фактический параметр основной программы, соответствующий формальному параметру – переменной, может быть только переменой, но не константой или выражением. Тип параметров – переменных может быть любым, включая и файловый. При вызове подпрограммы на месте параметра – пере–менной в качестве фактического параметра должна использоваться переменная идентичного типа.
Вывод: с помощью параметров – переменных данные можно передавать как из программы в процедуру, так и обратно; таким образом параметры – значения могут быть только входными, а параметры – переменные – входными и выходными.
Пример оформления процедуры.
procedure SUMMA (A, B : real; var Y, Z : real);
const N=5;
var i : integer;
begin for i:= 1 to N do
begin Y:= A+B*i;
Z:= 4*Y–i
end
end;
В описанной процедуре A и B – входные параметры (параметры – значения); они получают свои значения из основной программы. Результаты работы процедуры – выходные параметры Y и Z (параметры – переменные) передаются в основную программу и могут быть там использованы.
Из основной программы описанную процедуру можно вызвать следующим образом:
SUMMA(3.5, 7.6, Y1, Z1);
Это означает, что формальным параметрам A и B будут присвоены значения 3.5 и 7.6 соответственно, а в переменные Y1 и Z1 (фактические параметры) будут переданы результаты работы процедуры (Y, Z соответственно).
Пример 1. Описать процедуру МХ_MN, которая присваивает параметру X большее из вещественных чисел x и y, а параметру Y – меньшее.
procedure MX_MN (var X,Y : real);
var r : real; {промежуточная переменная для обмена данными между
ячейками X и Y}
begin
if X<Y then begin r := X;
X := Y;
Y := r
end
end;
В описанной процедуре формальные параметры X, Y, переданные по ссылке, являются и входными и выходными параметрами одновременно.
Пример 2. Определить, что будет напечатано в результате выполнения программы:
program PRIM;
var k: integer;
procedure PLUS1(N : integer);
begin N:= N+10 end;
procedure PLUS2(var N : integer);
begin N:= N+10 end;
{основная программа}
begin
k:= 0; PLUS1(k); Writeln(k);
k:= 0; PLUS2(k); Writeln(k)
end.
Процедура PLUS1 имеет один формальный параметр N (входной параметр, параметр – значение). При вызове процедуры PLUS1 фактический параметр k сопоставляется с формальным параметром N. Таким образом, значением N становится число 0. Внутри процедуры значение N увеличивается на 10 и становится равным 10. Выполнение процедуры закончено. Так как в данном случае используется механизм передачи параметра по значению, то изменение формального параметра не приводит к изменению фактического, т.е. в основной программе печатается значение переменной k, равное 0.
Процедура PLUS2 имеет один формальный параметр N (параметр – переменная), который является входным и выходным одновременно. При вызове процедуры PLUS2 выполняются действия, аналогичные действиям в процедуре PLUS1. Но так как в этом случае используется механизм передачи параметра по ссылке, то в ячейку N засылается адрес ячейки k. Выполнение оператора N:= N+10 в процедуре PLUS2 имеет следующий смысл: взять число из ячейки k, адрес которой хранится в переменной N, прибавить 10 и заслать в ту же ячейку k. Таким образом, все изменения, происходящие с формальным параметром N, одновременно приводят к изменению фактического параметра k. В результате выполнения процедуры PLUS2 формальный параметр N получит значение 10 и в основной программе будет напечатано значение переменной k, равное 10.
Пример 3. Определить, что будет напечатано в результате выполнения программы:
program PRIM1;
var A, B, C, D : integer;
procedure P(var B : integer; C : integer);
var D : integer;
begin A:= 5; B:= 6; C:= 7; D:=8;
Writeln(A, B, C, D)
end;
begin A:= 1; B:= 2; C:= 3; D:= 4;
P(A, B); Writeln(A, B, C, D)
end.
Описанным в основной программе глобальным переменным A, B, C, D присваиваются соответствующие значения 1, 2, 3, 4. При обращении к процедуре P значение фактического параметра A основной программы передается по ссылке формальному параметру B подпрограммы, а значение фактического параметра B основной программы – формальному параметру C процедуры по значению. Таким образом, все изменения, происходящие в процедуре с формальным параметром B, одновременно изменят и значение глобальной переменной A. Все же изменения, происходящие с формальным параметром C процедуры, никак не отразятся на глобальной переменной B, с которой она связана.
В теле процедуры глобальной переменной A присваивается значение 5. Формальному параметру B присваивается 6, а так он связан по ссылке с глобальной переменной A, то в ячейку A так же засылается значение 6. Формальному параметру C присваивается значение 7. Локальной переменной D присваивается значение 8. В теле процедуры печатается значение A, B, C, D соответственно 6, 6, 7, 8. Выполнение процедуры закончено. В основной программе печатаются значения глобальных переменных A, B, C, D соответственно 6, 2, 3, 4.
6.5.3. Процедурные типы. Параметры – функции и
параметры – процедуры.
В Турбо Паскале процедуры и функции можно рассматривать как некоторые параметры и можно использовать переменные, принимающие значение процедуры или функции. С этой целью вводятся процедурные типы (в стандартном Паскале таких типов нет), которые дают программисту возможность использования процедур и функций в качестве фактических параметров при обращении к другим процедурам и функциям.
Объявление процедурного типа в разделе type похоже на заголовок подпрограммы: после имени типа пишется слово procedure или function, за которым в круглых скобках записывается список формальных параметров с указанием типа; для функции после списка формальных параметров указывается через двоеточие тип функции. В отличие от заголовка подпрограммы после слов procedure и function не указывается имя подпрограммы. В разделе переменных var объявляются переменные процедурного типа.
Формат записи:
1. type
<имя типа> = procedure(<список форм. параметров>);
<имя типа> = function(<список форм. парам.>):<тип функции>;
var
<имя переменной> : <имя типа>;
2. var
<имя переменной> : procedure (<список форм. парам>);
<имя перем.> : function (<список форм.парам.>):<тип функции>;
Пример 1.
type
Proc = procedure(var A, B : real; d : integer);
Func = function(X, Y : real) : real;
var
P1, P2 : Proc;
F : Func;
После этого процедурным переменным можно присваивать значения конкретных процедур и функций.
Следующий пример иллюстрирует использование переменных процедурного типа.
program DELEN;
type
Proc = procedure(var X, Y : integer);
Func = function(X, Y : integer) : real;
Var P : Proc; F : Func; A, B : integer;
{$F+}
procedure Swap(var X1, Y1 :integer);
var Z:integer;
begin
if X1 < Y1 then begin Z := X1; X1 := Y1; Y1 := Z end
end;
function Del(X2, Y2 :integer) : real;
begin Del := X2/Y2 end;
function Minus(X3, Y3 : integer) : real;
begin Minus := X3–Y3 end;
{$F–}
{основная программа}
begin
Write('Введите два целых числа'); Readln(A, B);
P:= Swap; P(A, B); F:= Del;
Writeln('Частное от деления большего числа на меньшее ');
Writeln(F (A, B):5:2);
F:= Minus;
Writeln('Разность между большим и меньшим числами');
Writeln(F(A, B):5:2)
end.
Замечание 1. Процедурная переменная и подпрограмма должны быть совместимы для присваивания т.е. должны иметь одинаковое число формальных параметров, совпадающих по типам; функции, кроме того, должны иметь идентичный тип. Например, процедурная переменная P совместима с подпрограммой Swap, так как количество и тип формальных параметров в процедурной переменной P типа Proc совпадает с количеством и типом формальных параметров описанных в заголовке подпрограммы.
Замечание 2. Существует ряд правил использования подпрограмм в качестве процедурной переменной:
– подпрограммы должны компилироваться с ключом {$F+} или иметь директиву far для получения полного адреса подпрограмм, эта директива записывается в конце заголовка указанных подпрограмм после точки с запятой и после нее ставится точка с запятой;
(procedure Swap(var X1, Y1: integer); far;)
Подпрограммы не должны быть стандартными процедурами и функ циями; они не должны объявляться внутри других процедур и функций.
Замечание 3. После присвоения процедурной переменной имени подпрограммы имеется возможность вызывать эти подпрограммы как непосредственно, так и с помощью указания процедурной переменной. Так, следующие два вызова считаются эквивалентными P(A, B) и Swap(A, B).
При описании процедур и функций параметрами могут быть процедурные переменные, т.е. передаваемыми параметрами могут быть параметр – процедура или параметр – функция. Фактически этот параметр является параметром – значением, т.к. записывается без зарезервированного слова var. В качестве фактического параметра в этом случае используется соответствующая процедура или функция, имеющая необходимое количество параметров требуемых типов.
Для параметров – процедур и параметров – функций существуют те же правила, что и для других переменных процедурного типа: подпрограммы должны компилироваться с директивой far или с ключом {$F+}, не должны быть стандартными подпрограммами, не должны объявляться внутри подпрограмм.
Пример 2. Написать программу, которая печатает таблицу значений функции f(x)=tg(x)+1 в интервале изменения аргумента x от a до b с шагом h.
program TAB_FUNC;
type Func = Function(X: real):real;
Var a, b, h: real;
Function F1(X:real) : real; far;
begin F1:= sin(X)/cos(X)+1 end;
procedure Printfunc(X,b,h:real; F: Func);
begin While X<=b do
begin
Writeln( X:5:3, F(X):8:3);
X:=X+h end
end;
begin
Write('Введите интервал и шаг функции: '); Readln(a,b,h);
Printfunc(a,b,h,F1)
end.
Материалы на данной страницы взяты из открытых источников либо размещены пользователем в соответствии с договором-офертой сайта. Вы можете сообщить о нарушении.