Общие сведения о подпрограммах 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Общие сведения о подпрограммах



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

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

Главным вопросом, который следует решить при проектировании подпрограмм, является вопрос о способе передачи данных между подпрограммой и программой. В любом алгоритмическом языке существует два основных способа передачи данных: через список параметров подпрограммы и через глобальные переменные (общие области, внешние имена). Первый способ дает возможность подстановки, т. е. передачи в подпрограмму при каждом обращении к ней новых данных программы. В список параметров подпрограммы включаются переменные, значения которых должны быть переданы из программы в подпрограмму и из подпрограммы в программу (т.е. "вход" и "выход"[15] подпрограммы).

Во всех алгоритмических языках при использовании подпрограмм выделяются два момента: описание подпрограмм и обращение к ним (вызов). Под описанием подпрограммы понимается оформление её алгоритма особым образом, так чтобы любая программа (или подпрограмма) могла его активизировать и выполнить над своими данными. Под обращением к подпрограмме понимается активизация подпрограммы; программа передает управление подпрограмме и пересылает ей данные, подпрограмма выполняет свой алгоритм и возвращает управление программе. При описании подпрограммы в списке параметров записываются формальные параметры, которые используются только в подпрограмме и при обращении к ней заменяются фактическими параметрами, т. е. соответствующими данными программы[16]. Фактические параметры должны соответствовать формальным по количеству, порядку перечисления и типу.

Существует два способа замены формальных параметров на фактические:" по ссылке"[17] (call-by-reference) и "по значению" (call-by-value). Передача параметра "по ссылке" означает передачу в подпрограмму адреса фактического параметра. При этом любое изменение формального параметра внутри подпрограммы есть изменение соответствующего фактического параметра. Поэтому константы и выражения нельзя передавать "по ссылке" - они могут измениться, «испортиться». Передача параметров "по значению" означает пересылку значения фактического параметра в ячейку, соответствующую формальному параметру, при обращении к подпрограмме. Это обеспечивает сохранность величины фактического параметра. Изменение формального параметра внутри подпрограммы никак не отражается на значении фактического.

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

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

В большинстве алгоритмических языков имеется два вида подпрограмм: подпрограммы общего назначения (в паскале они называются процедурами) и функции. Функции следует использовать, если подпрограмма имеет одно выходное значение (или одно основное выходное значение); классическими примерами функций во всех алгоритмических языках являются стандартные математические функции: синус, косинус, абсолютная величина и т. д. Имя функции является не только именем ее алгоритма, но и именем результата; это имя можно использовать в выражениях (как sin, cos, abs, и т. д.) Говорят, что функция через свое имя возвращает единственный (или основной) результат.

Процедуры в Паскале

Как всегда при изучении подпрограмм, рассмотрим два вопроса: описание процедур и обращение к ним.

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

Описание процедуры состоит из заголовка и блока (тела) процедуры:

Заголовок;

Блок

Заголовок процедуры имеет вид:

procedure ИмяПроцедуры [ (CписокФормальныхПараметров) ]

Здесь и далее в выделенные квадратные скобки заключены необязательные элементы операторов.

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

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

Изучим структуру списка формальных параметров. Список формальных параметров - это секции формальных параметров, перечисленные через символы ";":

Секция1; Секция2;...;СекцияN

Секция формальных параметров имеет вид:

[ VAR ] CписокПеременных: Тип;

Указывается стандартный тип или имя нестандартного типа (можно использовать только имя типа, но не его описание!). Имя типа должно быть объявлено во внешнем блоке. В дальнейшем мы увидим, что запрет использования описания типа формального параметра влечет за собой весьма существенные ограничения (см. §2.2.2).

Если перед списком параметров стоит ключевое слово VAR, то эти параметры заменяются на фактические "по ссылке" (в терминах Паскаля такие параметры называются параметрами-переменными).

Если перед списком не стоит VAR, то замена на фактические происходит "по значению" (это параметры-значения).

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

Обращение к процедуре

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

ИмяПроцедуры [ (CписокФактическихПараметров) ]

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

Пример. Даны две матрицы: а из 3-х строк и 5 столбцов и b из 7 строк и 3 столбцов. Вычислить минимальные значения элементов для каждой строки каждой из этих матриц.

Естественно, вычисление минимальных значений строк произ­вольной матрицы следует оформить как подпрограмму (назовем ее minstr), а затем применить ее два раза к конкретным (фактическим) матрицам а и b. Алгоритм ввода одинаков для матриц а и b, поэтому ввод также оформим как подпрограмму (назовем ее matrin). Вывод массива результатов будет осуществлять подпрограмма masout.

Таблица 9. Состав данных программы

Имя Смысл Тип Структура
Исходные данные
а заданные матрицы вещественный двумерный массив размером 7*5
b
Выходные данные
mina минимальные значения элементов строк матрицы a(b) вещественный одномерный массив из 7 элементов
minb

 

Обратите внимание на размеры массивов в таблице 9. Типы фактических и формальных параметров подпрограмм должны совпадать, поэтому размеры формальных массивов должны подходить и для матрицы а, и для матрицы b. Чтобы удовлетворить этому требованию, используем максимальные размеры, подходящие и для а, и для b, т. е. память под массивы отводится с избытком. Тип массивов-параметров процедур (и функций) должен быть объявлен в разделе Type программы (в нашем примере это matr для матрици mas для одномерных массивов – см. текст программы).

Заметим, что в программе не будет промежуточных переменных. Программа будет состоять из вызовов подпрограмм (крупных операторов), а промежуточные переменные (с точки зрения пользователя детали, мелочи) будут «спрятаны» в подпрограммы.

Поясним, как составлен заголовок подпрограммы minstr. Подпрограмма имеет столько результатов, сколько строк у матрицы, все они равноправны, поэтому нет причины передавать один из них через имя функции, и, следовательно, minstr должна быть процедурой (не функцией). В список формальных параметров включаются "входные" данные для процедуры: матрица а и ее размеры (n - число строк, m - число столбцов), и "выходные" данные: min - массив минимальных значений строк. Заметим, что обозначения, принятые в одной подпрограмме (a, n, m, min ) никоим образом не связаны с обозначениями в других подпрограммах и программе, т. е. подпрограммы разрабатываются автономно друг от друга. Переменная min - результат работы функции, поэтому ее надо объявить как параметр-переменную (перед описанием поставить ключевое слово Var). Так как фактическими значениями n и m будут константы (для фактической матрицы a, например, 3 и 5), n и m должны быть параметрами-значениями (перед их описанием Var не следует ставить). a лучше объявить как параметр-переменную (так как это массив) с целью экономии памяти.

Получаем заголовок:

procedure minstr(Var a:matr; n,m:integer; Var min:mas).

Промежуточные переменные процедуры (счетчики строк и столбцов i и j) должны быть описаны в разделе переменных блока процедуры.

Рассмотрим заголовок процедуры ввода матрицы matrin (предлагается читателю пояснить самостоятельно, почему это процедура, а не функция). На входе matrin – размеры матрицы n и m и имя матрицы, которое будет выводиться в приглашении к вводу символьная переменная с; эти данные должны быть параметрами-значениями (объясните, почему). На выходе процедуры – введенная матрица, для разнообразия обозначим ее р; это обязательно параметр-переменная. Получили заголовок:

procedure matrin(n,m:integer; c: char;Var p:matr).

Обратите внимание, что отсутствие ключевого слова Var перед описанием a в этом заголовке приведет к неработоспособности программы, в то время как в заголовке процедуры minstr отсутствие Var, вообще говоря, допустимо (объясните, почему).

Дальнейшие комментарии к программе приведены в ее тексте.

 
 

Блок-схема программы приведена на рис. 13, блоки вызова подпрограмм имеют двойные линии по боковым сторонам. Блок-схема процедуры minmatr приведена на рис. 14.

 

 
 

program primer2_2;

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

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

Procedure minstr(Var a:matr; n,m:integer; Var min:mas);

Var i,j:integer;

Begin

for i:=1 to n do

begin

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

for j:=2 to m do

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

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

end

End{minstr};

Procedure matrin(n,m:integer; c:char; Var p:matr);

Var i,j:integer;

Begin

Writeln('Введите матрицу ',c,' размером ',n,'*',m);

for i:=1 to n do

for j:=1 to m do

read(p[i,j]);

readln;

End{matrin};

Procedure masout(n:integer;c:char;Var min:mas);

Var i:integer;

Begin

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

for i:=1 to n do

writeln(' ',min[i]);

End{masout};

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

matrin(3,5,'a',a);

matrin(7,3,'b',b);

minstr(a,3,5,mina);

minstr(b,7,3,minb);

masout(3,'a', mina);

masout(7,'b', minb);

readln

End.

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

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

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

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

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

SUM:=SUM+A[i];

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

S:=0;...

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

SUM:=S;

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

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

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

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


 
 

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

где 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.

 



Поделиться:


Последнее изменение этой страницы: 2017-02-07; просмотров: 1025; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.119.131.72 (0.081 с.)