Посмотрите начальные сведения о функциях
В этой лекции мы рассмотрим создание и применение пользовательских подпрограмм: функций и процедур. Подпрограммы разрабатываются, чтобы не писать многократно один и тот же текст, когда в программе встречаются повторяющиеся действия. Кроме того, использование подпрограмм повышает наглядность текста программ (если имена подпрограмм легко понять).
procedure <имя процедуры> (<параметры>); label <метки>; const <объявление констант>; type <определения типов данных>; var <объявления переменных>; < Объявления подпрограмм > begin <тело процедуры - операторы> end;
Функции имеют такой же формат, как и процедуры, только они начинаются с заголовка function и заканчиваются типом данных возвращаемого значения:
function имя функции (параметры): тип данных;
Мы видим, что структура подпрограмм практически повторяет структуру главной программы. Имеются только два различия между главной программой и подпрограммами:
- процедуры и функции имеют заголовок procedure или function, соответственно, а не program;
- процедуры и функции заканчиваются точкой с запятой (;), а не точкой (.).
Процедуры и функции могут иметь описания своих констант, типов данных, переменных и свои процедуры и функции. Но все эти элементы могут быть использованы только в тех процедурах и функциях, где они объявлены. То есть нужно различать ЛОКАЛЬНЫЕ идентификаторы и ГЛОБАЛЬНЫЕ. Локальные идентификаторы описаны в подпрограмме и их можно использовать только в теле этой подпрограммы. Глобальные идентификаторы - это идентификатороы, описанные в главной программе. Они действительны и в теле главной программы и в телах подпрограмм (конечно, только если описание подпрограммы расположено ПОСЛЕ описания этого глобального идентификатора). Глобальные метки нельзя ставить в подпрограммах.
В теле подпрограммы НЕ рекомендуется использовать глобальные идентификаторы, а пользоваться только локальными и параметрами. Тогда подпрограмму несложно использовать и в других программах, так как обмен данными с главной программой происходит только через параметры, а они "все на виду".
Чтобы вычислить гипотенузу конкретного треугольника в главной программе функцию Hyp нужно ВЫЗВАТЬ, записав ее имя в каком-либо выражении. Например:
writeln('Гипотенуза треуг. с катетами 3 и 4 равна ', Hyp(3,4):0:2);
Видим, что место параметров a,b занимают 3 и 4 - называемые ФАКТИЧЕСКИМИ параметрами. То есть: при вызове подпрограмм места ФОРМАЛЬНЫХ параметров занимают фактические параметры (соответствие определяется по порядку). А формальные параметры используются при записи тела подпрограммы. Закончим описание функции Hyp:
function Hyp(a,b: real):real; begin Hyp := sqrt(sqr(a)+sqr(b)); end;Видим, что формальные параметры используются в теле функции. Заодно отметим особенность функции: необходимо, чтобы в ее теле присутствовало присваивание имени функции какого-то значения.
Параметры в этом примере - ПАРАМЕТРЫ-ЗНАЧЕНИЯ. Это означает, что:
В отличие от параметров-значений ПАРАМЕТРЫ-ПЕРЕМЕННЫЕ описываются начиная с var.
Например, заголовок процедуры, вычисляющей гипотенузу, может выглядеть так:
procedure hypot(a,b: real; var c: real);
Здесь 3-й параметр - "c" является параметром-переменной. Только такие параметры можно применять для передачи результатов из подпрограммы в главную программу (второй вариант - через имя функции, но это пример процедуры). При этом тип фактического параметра должен совпадать с типом формального параметра.
Завершим описание этой процедуры:
procedure hypot(a,b: real; var c: real); begin c := sqrt(sqr(a)+sqr(b)); end;Как видим, различие с функцией в том, что результат - вычисленная длина гипотенузы присваивается параметру-переменной. Посмотрим, как использовать этот результат в главной программе:
. . . var dli: real; begin . . . hypot(4-1,2+3,dli); writeln('Гипотенуза треуг. с катетами 3 и 4 равна ', dli(3,4):0:2); . . .В завершение отметим, что существуют параметры-константы, параметры процедурного типа, нетипизированные параметры, параметры-динамические массивы и строки. Тип фактического параметра должен соответствовать типу формального параметра.
Простой пример программы можно увидеть здесь.
Подробнее о подпрограммах можно прочесть в Руководстве программиста, гл.8 "Процедуры и функции" (справочник-задачник).
В ТПас7 и Делфи можно использовать рекурсивные подпрограммы. Использование рекурсии (там, где это возможно по условиям задачи) облегчает программирование и сокращает текст проргаммы. Однако при каждом рекурсивном вызове расходуется память (подпрограммы размещаются в стеке). Поэтому нужно не допускать переполнения стека. Объем памяти стека регулируется в настройках компилятора.
Пример программы: вычисление факториала ( рекурсия ).