Лекция 2.3. Процедуры и функции
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

Лекция 2.3. Процедуры и функции

Основные понятия структурного программирования

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

С массовым внедрением ВТ процесс программирования постепенно превращается в промышленное изготовление программ. Для этой цели создаются различные технологии программирования. Примером таких технологий может служить технология нисходящего программирования.

Технология нисходящего программирования базируется на методе программирования "сверху вниз". Основой такого метода является идея постепенной декомпозиции исходной задачи на ряд подзадач. Сначала формулируется самая грубая модель решения, отдельные детали которой на начальном этапе могут быть довольно расплывчатыми. По мере разработки программы, разбивая наиболее неясные части алгоритма и добиваясь, все более четких и детализированных формулировок, получаем более подробное решение. Решение отдельного фрагмента сложной задачи может представлять собой самостоятельный программный блок, называемый
подпрограммой. Такой процесс детализации продолжается до тех пор, пока, не станут ясны все детали решения задачи. В этом случае программу решения сложной задачи можно представить как иерархическую совокупность относительно самостоятельных фрагментов программ.

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


Процедуры

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

Procedure <имя>(<Формальные параметры>);

const...;

type...;

var...;

begin

< операторы >

end;

 

Пример. Необходимо ввести значения элементов целочисленных массивов A[1..10] и B[1..10], найти в массиве количество положительных и отрицательных элементов и результат вывести на экран.

Program Prim6_1;

Const Kol=10;

Type Vector = array[1..Kol] of integer;

Var

A,B : vector;

KolOtrA,KolPolA,KolOtrB,KolPolB,i : integer;

Procedure Summa(V:vector; Var Kp,Ko:integer);

var
k:integer;

begin

Kp:=0; Ko:=0;

For k:=1 to Kol do

if V[k]>0 then Kp:=Kp+1

else if V[k]<0 then Ko:=Ko+1;

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

begin

Write('Введите значения массива А:');

For i:=1 to Kol do Read(A[i]);

Write('Введите значения массива B:');

For i:=1 to Kol do Read(B[i]);

Summa(A,KolPolA,KolOtrA);

Summa(B,KolPolB,KolOtrB);


Writeln(KolOtrA,KolPolA,KolOtrB,KolPolB);

end.

 

Для вызова процедуры из основной программы следует написать оператор, состоящий из имени процедуры и списка фактических параметров, которые должны совпадать по количеству и типам с формальными параметрами процедуры. Например, Summ (A,KolPolA,KolOtrA) означает, что вызывается процедура Summa для вычисления количества положительных и отрицательных элементов в массиве А.

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

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



Функции

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

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

function <имя>(<формальные параметры>):<тип результата>

const...;

type...;

var...;

begin

< операторы >

end;

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

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

Пример. Составить программу вычисления выражения Z=(X**5+X**-3)/2*X**M, в которой возведение в степень выполняется функцией Step.

Program Prim6_2;

var

M:integer;

X,Z,R : real;

Function Step(A:real;
D:integer):real;

var

i:integer;

Y:real;

begin

Y:=1;

For i:=1 to B do Y:=Y*A; { Цикл вычисления степени }

Step:;=Y; {Присвоение функции результата вычисления степени}

end;

begin

Write('Введите значения Х и М');

ReadLn(X,M);

Z=Step(X,5);

Z:=Z+Step(1/X,3);

if M=0 then R:=1

else if M>0 then R:=Step(X,M)

else
R:=Step(1/X,M);

Z:=Z/(2*R);

Writeln('Для Х=',X,'M=',M,'выражение = ',Z);

end.



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

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

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

Пример 7.1. Вычисление квадратов двух чисел и вывода на экран их суммы.

Program Prim7_1;

var A,B : real;


Procedure SumSqr(X,Y:real);{X,Y - формальные параметры }

begin

X:=X*X;

Y:=Y*Y;

Writeln(' Сумма квадратов =',X+Y);

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

begin {Начало главной программы}

A:=1.5; B:=3.5;

SumSqr(A,B); {Вызов процедуры с передачей ей значений фактических параметров}

end.

При вызове процедуры SumSqr с фактическими параметрами А и В значения этих параметров копируются в соответствующие формальные параметры X и Y, и дальнейшее преобразование этих формальных параметров ни как не влияют на значения переменных А и В.


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

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

Procedure Prim(var M,N : integer; var Y : real);

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

Program Prim7_2;

var

A,B : real;

SumAB, SubAB : real;


Procedure SumSub(X,Y : real; var Sum, Sub : real);

begin

Sum:=X*X+Y*Y;

Sub:=X*X-Y*Y;

end;


begin {Начало главной программы}

A:=1.5;

B:=3.4;

SumSub(A,B,SumAB,SubAB); {Вызов процедуры с передачей ей фактических параметров-значений А и В и параметров-переменных SumAB и SubAB}

Writeln('Сумма квадратов чисел А и В = ',SumAB);

Writeln('Разность квадратов чисел А и В = ',SubAB);

end.



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

Часто в качестве параметра в подпрограмму следует передать ту или иную переменную, но изменять ее подпрограмма не должна. В этом случае нежелательно передавать этот параметр как параметр-переменную. Можно его передать как параметр-значение, однако, если эта переменная имеет большой размер (массив, запись и т. д.), то копия такого параметра займет большую часть стека и даже может его переполнить. Это же приводит и к уменьшению быстродействия программы. В этой ситуации параметр лучше передать как параметр-константу. Такой параметр, если он структурированного типа, передается своим адресом, не предусматривается защита от его изменения. Использовать параметр-константу можно только в версии 7.0.

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

Пример .

function NewString(const S: string): string;

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

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

Параметр-константу нельзя передавать в другую подпрограмму в качестве фактического параметра.

Пример. Функция вычисления максимального элемента в массиве.

function Max(const Mas: tArr; N: Byte): Integer;

var Ma: Integer;

i: Byte;

begin

Ma := Mas[l];

for i := 2 to N do

if Ma < Mas[i] then

Ma := Mas [ i ] ;

Max := Ma

end;

Параметры без типа

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

Пример .

function Equal(var Paraml, Param2; Len: Word): Boolean;

Здесь Param1, Param2 - параметры-переменные без типа (вместо них можно использовать, например, любые переменные простого типа, типа-массив, типа-запись и т. д.); Len - параметр-значение.

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

Пример. Функция вычисления максимального элемента в массиве.

function Max(var Mas; N: Byte): Integer;

type

tArray = array[1..Maxint] of Integer;

{тип массива максимального размера}

var Ma: Integer;

i: Byte;

begin

Ma := tArray(Mas)[1];

for i := 2 to N do

if Ma < tArray(Mas)[i] then

Ma := tArray(Mas)[i];

Max := Ma

end;

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

ОБЛАСТЬ ДЕЙСТВИЯ ПАРАМЕТРОВ

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

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

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

Можно схематически изобразить структуру блоков некоторой программы, как показано на рис.1.

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

1. Имена объектов, описанных в некотором блоке, считаются известными в пределах данного блока, включая и все вложенные блоки.

2. Имена объектов описанных в блоке, должны быть уникальны в пределах данного блока и могут совпадать с именами объектов из других блоков.

3. Если в некотором блоке описан объект, имя которого совпадает с именем объекта, описанного в объемлющем блоке, то это последнее имя становится недоступным в данном блоке (оно как бы экранируется одноименным объектом данного блока).

Если применить эти правила к предыдущей схеме то можно сказать, что объекты, описанные в блоке В, известны кроме самого блока В еще и в блоках С и D, но невидимы в блоке А. Объекты, описанные в блоке F, известны в пределах только этого блока.

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

В качестве примера с вложенными подпрограммами рассмотрим пример программы, определяющей количество сверхпростых чисел в натуральном ряду чисел, не превышающих 1000. Сверхпростым называется число, если оно простое и число, полученное из исходного числа, при записи цифр исходного числа в обратном порядке (перевертыш) тоже будет простым. Например, 13 и 31 —сверхпростые числа.

Program Prim7_3;

var X, К : integer; {Описание глобальных переменных X, К}

{Функция проверки числа Х на простое число}

function Prost(Y : integer):boolean;

var

D, I : integer;

Flag : boolean;

begin

D:=0; Flag:=False;

for I:=2 to Y-l do if Y mod 1=0 then D:=D+1;

if D=0 then Flag:=True;

Prost:=Flag;

end;

{Перевертыш простого числа}

function Povorot(Y:integer):integer ;

var

S:integer; {Описание локальной переменной 3}

begin

if Y<10 then S:=Y;

if (Y>10) and (Y<100) then S:=Y mod 10*10+Y div 10;

if (Y>=100) and (Y<1000)

then
S:=Y mod 10*100+Y mod 100 div 10*10+Y div 100;

Povorot:=S;

end;

begin {Начало главной программы}

Writeln(‘ ’:20,’Сверхпростые числа’);

К:=2; {2 и 3 — простые числа}

for X:=4 to 999 do

begin

if Prost(X) then {Вызов функции определения простого чис­ла х}

if Prost(Povorot(X)) then

{Вызов функции определения простого числа для числа-перевертыша полученного вычислением функции Povorot(х) от простого числа}

begin

Writeln(X); {Печать сверхпростого числа}

К:=К+1;

end;

end;

Writein(‘Всего найдено‘,К,’сверхпростых чисел < 1000 ‘);

end.


РЕКУРСИЯ

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

Примером программы с использованием рекурсии может быть программа вычисления факториала числа.

Program Prim7_4;

var N:integer;

F:longint;

function Fact(N:integer):longint;

begin

if N=1 then Fact:=1 else Fact:=N*Fact(N-1);

end;

begin {Начало главной программы}

Write('Введите число N ');

Readln(N);

F:=Fact(N);

Writeln('Для числа ',N,' значение факториала = ',F);

Readln

end.

После считывания числа N, в выражении N:=Fact(N); вызывается функция Fact с параметром-значением N. В подпрограмме функции Fact вычисления факториала проверяется условие N=1. Если оно выполняется, то функции Fact присваивается значение 1, на этом выполнение функции завершается. Если условие N=1 не соблюдается, то выполняется вычисление произведения N*Fact(N-1).Вычисление
произведения носит рекурсивный характер, так как при этом осуществляется вызов функции Fact(N-1), значение которой вычисляется, в свою очередь, через вызов функции Fact и так до тех пор, пока значение параметра N=1.

Таким образом, при выполнении рекурсивной подпрограммы осуществляется многократный переход от некоторого текущего уровня организации алгоритма к нижнему уровню последовательно до тех пор, пока, наконец, не будет получено тривиальное решение поставленной задачи. В нашем примере решение при N=1 тривиально, т.к. Fact=1. Затем осуществляется возврат на верхний уровень с последовательным вычислением функции Fact.

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


Лекция 2.3. Процедуры и функции

Основные понятия структурного программирования

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

С массовым внедрением ВТ процесс программирования постепенно превращается в промышленное изготовление программ. Для этой цели создаются различные технологии программирования. Примером таких технологий может служить технология нисходящего программирования.

Технология нисходящего программирования базируется на методе программирования "сверху вниз". Основой такого метода является идея постепенной декомпозиции исходной задачи на ряд подзадач. Сначала формулируется самая грубая модель решения, отдельные детали которой на начальном этапе могут быть довольно расплывчатыми. По мере разработки программы, разбивая наиболее неясные части алгоритма и добиваясь, все более четких и детализированных формулировок, получаем более подробное решение. Решение отдельного фрагмента сложной задачи может представлять собой самостоятельный программный блок, называемый
подпрограммой. Такой процесс детализации продолжается до тех пор, пока, не станут ясны все детали решения задачи. В этом случае программу решения сложной задачи можно представить как иерархическую совокупность относительно самостоятельных фрагментов программ.

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


Дата: 2019-05-28, просмотров: 169.