При решении сложных объемных задач
часто целесообразно разбивать их на
более простые. Метод последовательной
детализации позволяет составить
алгоритм из действий, которые, не
являясь простыми, сами представляют
собой достаточно самостоятельные
алгоритмы. В этом случае говорят о
вспомогательных алгоритмах или
подпрограммах. Использование
подпрограмм позволяет сделать основную
программу более наглядной, понятной, а в
случае, когда одна и та же
последовательность команд встречается
в программе несколько раз, даже более
короткой и эффективной.
В языке Паскаль существует два вида
подпрограмм: процедуры и функции,
определяемые программистом. Процедурой
в Паскале называется именованная
последовательность инструкций,
реализующая некоторое действие. Функция
отличается от процедуры тем, что она
должна обязательно выработать значение
определенного типа.
Процедуры и функции, используемые в
программе, должны быть соответствующим
образом описаны до первого их
упоминания. Вызов процедуры или функции
производится по их имени.
Подпрограммы в языке Паскаль могут
иметь параметры (значения, передаваемые
в процедуру или функцию в качестве
аргументов). При описании указываются
так называемые формальные параметры (имена,
под которыми будут фигурировать
передаваемые данные внутри
подпрограммы) и их типы. При вызове
подпрограммы вместе с ее именем должны
быть заданы все необходимые параметры в
том порядке, в котором они находятся в
описании. Значения, указываемые при
вызове подпрограммы, называются
фактическими параметрами.
Формат описания процедуры:
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, описанным в
основной программе.
Существует два способа передачи
фактических параметров в подпрограмму:
по значению и по ссылке. В первом случае
значение переменной-фактического
параметра при вызове подпрограммы
присваивается локальной переменной,
являющейся формальным параметром
подпрограммы. Что бы потом ни
происходило с локальной переменной, это
никак не отразится на соответствующей
глобальной. Для одних задач это благо, но
иногда требуется произвести в
подпрограмме действия над самими
переменными, указанными в качестве
фактических параметров. На помощь
приходит второй способ. Происходит
следующее: при обращении к подпрограмме
не происходит формирования локальной
переменной-формального параметра.
Просто на время выполнения подпрограммы
имя этой локальной переменной будет
указывать на ту же область памяти, что и
имя соответствующей глобальной
переменной. Если в этом случае изменить
локальную переменную, изменятся данные
и в глобальной.
Передача параметров по ссылке
отличается тем, что при описании
подпрограммы перед именем переменной-формального
параметра ставится служебное слово Var.
Теперь использование в качестве
фактических параметров выражений или
непосредственных значений уже не
допускается - они должны быть именами
переменных.
Еще один классический пример. Задача:
"Расположить в порядке неубывания три
целых числа".
Program Pr;
Var
S1,S2,S3 :Integer;
Procedure Swap(Var A,B: Integer);{Процедура Swap с
параметрами-переменными}
Var C : Integer; {C - независимая локальная
переменная}
Begin
C:=A; A:=B; B:=C {Меняем
местами содержимое A и B}
End;
Begin
Writeln('Введите три числа');
Readln(S1,S2,S3);
If S1>S2 Then Swap(S1,S2);
If S2>S3 Then Swap(S2,S3);
If S1>S2 Then Swap(S1,S2);
Writeln('Числа в порядке неубывания:V',S1,S2,S3)
End.