При решении сложных объемных задач часто целесообразно разбивать их на более простые. Метод последовательной детализации позволяет составить алгоритм из действий, которые, не являясь простыми, сами представляют собой достаточно самостоятельные алгоритмы. В этом случае говорят о вспомогательных алгоритмах или подпрограммах. Использование подпрограмм позволяет сделать основную программу более наглядной, понятной, а в случае, когда одна и та же последовательность команд встречается в программе несколько раз, даже более короткой и эффективной.
Подпрограммы значительно облегчают программирование, за счет (а) избавления от необходимости многократно повторять в тексте программы аналогичные фрагменты; (б) улучшения структуры программы, облегчая ее понимание при разборе; (в) повышения устойчивости программы к ошибкам программирования и непредвиденным последствиям при модификациях.
Различают два вида подпрограмм - процедуры и функции.
Процедура – это независимая именованная часть программы, которую можно вызвать по имени для выполнения определенных действий. Процедура не может выступать как операнд в выражении. Упоминание в тексте имени процедуры приводит к её активизации и называется вызовом.
|
|
Функция – аналогично процедуре, с двумя отличиями: (1) функция передает в точку вызова скалярное значение, (2) имя функции может использоваться в выражении как операнд.
Подпрограммы в Pascal могут обращаться сами к себе. Такое обращение называется рекурсией.
Формат описания процедуры:
Procedure <Имя процедуры> (<Имя форм. параметра 1>:<Тип>;
< Имя форм. параметра 2>:<Тип>?);
<Раздел описаний>
Begin
<Тело процедуры>
End;
Раздел описаний может иметь такие же подразделы, как и раздел описаний основной программы (описание процедур и функций - в том числе). Однако все описанные здесь объекты "видимы" лишь в этой процедуре. Они здесь локальны также, как и имена формальных параметров. Объекты, описанные ранее в разделе описаний основной программы и не переопределенные в процедуре, называются глобальными для этой подпрограммы и доступны для использования.
Легко заметить схожесть структуры программы целиком и любой из ее процедур. Действительно, ведь и процедура и основная программа реализуют некий алгоритм, просто процедура не дает решения всей задачи. Отличие в заголовке и в знаке после End.
Формат описания функции:
Function <Имя функции> (<Имя форм. параметра 1>:<Тип>;
< Имя форм. параметра 2>:<Тип>?): <Тип результата>;
<Раздел описаний>
Begin
<Тело функции>
End;
В теле функции обязательно должна быть хотя бы команда присвоения такого вида: <Имя функции>:=<Выражение>;
|
|
Указанное выражение должно приводить к значению того же типа, что и тип результата функции, описанный выше.
Вызов процедуры представляет в программе самостоятельную инструкцию:
<Имя процедуры>(<Фактический параметр 1>, < Фактический параметр 2>?);
Типы фактических параметров должны быть такими же, что и у соответствующих им формальных.
Вызов функции должен входить в выражение. При вычислении значения такого выражения функция будет вызвана, действия, находящиеся в ее теле, будут выполнены, в выражение будет подставлено значение результата функции.
Приведем простейший пример использования подпрограммы.
Задача: "Найти максимальное из трех введенных чисел". Для решения воспользуемся описанием функции, принимающей значение максимального из двух чисел, которые передаются в нее в виде параметров.
Program Fn;
Var
A,B,C:Real;
Function Max(A,B:Real):Real; {Описываем функцию Max с формальными}
Begin {параметрами A и B, которая принимает }
If A>B Then Max:=A {значение максимального из них }
Else Max:=B {Здесь A и B - локальные переменные }
End;
Begin
Writeln('Введите три числа');
Readln(A,B,C);
Writeln('Максимальным из всех является ', Max(Max(A,B),C))
End.
Обратите внимание на краткость тела основной программы и на прозрачность действий внутри функции. Формальные параметры A и B, используемые в подпрограмме, не имеют никакого отношения переменным A и B, описанным в основной программе.
Существует два способа передачи фактических параметров в подпрограмму: по значению и по ссылке. В первом случае значение переменной-фактического параметра при вызове подпрограммы присваивается локальной переменной, являющейся формальным параметром подпрограммы. Что бы потом ни происходило с локальной переменной, это никак не отразится на соответствующей глобальной. Для одних задач это благо, но иногда требуется произвести в подпрограмме действия над самими переменными, указанными в качестве фактических параметров. На помощь приходит второй способ. Происходит следующее: при обращении к подпрограмме не происходит формирования локальной переменной-формального параметра. Просто на время выполнения подпрограммы имя этой локальной переменной будет указывать на ту же область памяти, что и имя соответствующей глобальной переменной. Если в этом случае изменить локальную переменную, изменятся данные и в глобальной.
Задача: Организация ввода координат вектора. Вычислить длину вектора. Для начала определим список формальных параметров: входные и выходные данные. Нам потребуется Размерность векторного пространства (k: byte) и переменная х пользовательского типа vector=array[1..100] of real.
Для ввода координат будем использовать procedure, так как выходных данных будет много (его координаты), а так как длина вектора это число, поэтому используем function.
program pro;
type vector=array [1..100] of real;
var k: byte;
dl:real;
x: vector;
procedure vvod (var y:vector); {Процедура ввода вектора}
var i:byte;
begin
writeln('Введите координаты вектора');
for i:=1 to k do
readln(y[i]);
end;
function dlvec(y:vector):real; {Функция вычисления длины вектора}
var i:byte;
s:real;
begin
for i:=1 to k do
s:= s+ sqr(y[i]);
dlvec:= sqrt(s); {Обязательно в конце нужно имени функции присвоить вычисленное значение}
end;
begin
write(' Введите размерность векторного пространства k=');
readln(k);
vvod(x); {вызов процедуры}
dl:=dlvec(x); {вызов функции}
writeln('Длина вектора Х равна', dl: 8: 2);
end.