ПРОЦЕДУРЫ И ФУНКЦИИ
Описание и вызов. В Паскале подпрограммы называются процедурами и функциями и описываются в разделе с тем же названием.
Процедура имеет такую же структуру, как и программа, но с двумя отличиями:
• заголовок процедуры имеет другой синтаксис и включает служебное слово procedure;
• описание процедуры заканчивается точкой с запятой (а не точкой). Все имена, описанные в программе до процедуры, действуют во всей программе и в любой ее подпрограмме (если они там не описаны заново). Они называются глобальными, в отличие от локальных имен, описанных в процедуре и действующих лишь в ней.
Данные для обработки могут передаваться процедуре через глобальные имена или через аргументы процедуры. В процедуре каждый аргумент имеет свое имя -формальный параметр, описываемый в заголовке процедуры по схеме
procedure <имя> (<список описаний формальных параметров>) Описание формальных параметров может иметь вид
<список имен>: <тип> или var <список имен>: <тип>
В первом случае говорят о параметрах-значениях, во втором - о параметрах-переменных. В простейшем случае заголовок процедуры может содержать только имя процедуры.
Оператор вызова процедуры имеет вид
<имя процедуры> (<список выражений>);
Указанные выражения называют фактическими параметрами. Их список должен точно соответствовать списку описаний формальных параметров процедуры. Во время вызова процедуры каждому параметру-значению присваивается значение соответствующего фактического параметра и поэтому их обычно используют для передачи входных данных.
Параметры-переменные следует использовать для представления результатов процедуры.
Пример: составим программу, которая с помощью строки символов разделит экран на части, где напечатает таблицу квадратных корней для чисел 1, 2,..., 10 и таблицу натуральных логарифмов для чисел 1, 2,..., 5.
Печать строки символов оформим как процедуру. Так как никакую информацию передавать из процедуры в программу не надо, то аргументы процедуры (вид и количество символов) будут описаны как параметры-значения.
Заметим, что процедура в программе выполняется пять раз.
Программа 18
program section;
var x:integer;
procedure line(a:integer;c:char) ;
var j:integer;
begin
for j:=l to a do write (c);
writeln
end;
begin
line(35,'-'); writeln('таблица квадратных корней');
line(35,'-');
for x:=l to 10 do writeln(x:8,sqrt(x):8,4);
line (35,'-'); writein('таблица натуральных логарифмов');
line(35,'-');
for x:=l to 5 do writein(x:8,In(x):8:4);
line(35,'*')
end.
Функция - это подпрограмма, определяющая единственное скалярное, вещественное или строковое значение. Отличия подпрограммы-функции от процедуры:
• заголовок функции начинается со служебного слова function и заканчивается указанием типа значения функции:
function <имя> (список описаний формальных параметров): <тип>;
•раздел операторов функции должен содержать хотя бы один оператор присваивания имени функции;
• обращение к функции - не оператор, а выражение вида
<имя функции> (<список фактических параметров>).
Функции (и процедуры) могут использовать свое имя в собственном описании, т.е. могут быть рекурсивными.
Пример: составим программу, которая для заданных четырех натуральных чисел а, b, с, d напечатает наибольшие общие делители первой и второй пар чисел и сравнит их по величине.
В программе определим рекурсивную функцию nod(x,y) по формулам
|
x, если у = 0
nod(x,y) = | nod(y.x). если х < у
| nod(x mod у,у), если х > у
Применяя эти формулы к числам 21 и 15, последовательно находим nod(21,15) = nod(6,15) = nod(15,6) = nod(3,6) = nod(6,3) = nod(0,3) = nod(3,0) = 3.
Программа 19
program four;
var a,b,c,d,m,n:integer;
function nod(x,у:integer):integer;
var h:integer;
begin
if y=0 then h:=x
else if x<y then h:=nod(y,x)
else h:=nod(x mod у, у);
nod: =h end;
begin
writeln('введите 4 натуральных числа');
read(а,Ь,с,d); writeln;
m:=nod(a,b); n:=nod(c,d);
writeln('нод(',а,',',b,')=',m);
writeln('нод(',c,',',d,')=',n);
if m>n then writeln('первый > второго')
else if m<n then writeln ('первый < второго')
else writeln('нод пар равны') end.
Внешние библиотеки.
Как известно, подпрограммы (процедуры и функции) используются в программах с целью их структурирования, а также при многократных повторениях некоторых частей программы. Процедуры и функции описываются в программных единицах в разделе описания подпрограмм. Они являются внутренними для этих программных единиц.
Бывают случаи, когда одни и те же подпрограммы могут использоваться в различных программах одного и даже нескольких пользователей. В подобных ситуациях целесообразно создавать внешние подпрограммы, которые можно в необходимый момент подключать в любые программы. Как правило, внешние подпрограммы объединяют в отдельные пакеты, так называемые, библиотеки внешних подпрограмм. Могут создаваться личные библиотеки, специализированные библиотеки коллективного пользования и др. С одной из таких библиотек - встроенной библиотекой стандартных подпрограмм - пользователи имеют дело практически всегда. В состав этой библиотеки входят процедуры и функции вычисления значений ряда элементарных функций: синуса, косинуса, экспоненты и т.д., процедуры и функции обработки символьных величин, процедуры ввода-вывода и др. (список их приведен в конце § 3). Встроенная библиотека подключается к любой программе автоматически при компиляции. Поэтому откомпилированный файл с расширением .corn (иногда называемый «комовским»), как правило, занимает в 8 -10 раз больше места в памяти, чем исходный текст.
Внешние подпрограммы создаются обычным образом в виде отдельного файла или файлов. Для подключения внешних подпрограмм в программе пользователя в разделе описания ставится директива $I имя файла. С этого момента все процедуры и функции внешнего файла становятся внутренними для программы, и на все входящие в него процедуры и функции распространяется правило локальных и глобальных переменных. В этой связи, директива подключения внешнего файла должна размещаться после описания всех ею используемых глобальных параметров, процедур и функций.
Пример. Создадим внешнюю библиотеку из двух процедур и одной функции. Первая процедура программы 20 очищает экран, выдает приветствие, затем после нажатия клавиши <Пробел> снова очищает экран. Вторая процедура возводит число а в степень b. Третья подпрограмма-функция вычисляет значение экспоненты с некоторым грубым приближением на основе ряда Тейлора.
Программа 20
procedure PRIVET;
var a: char;
begin
cirscr; gotoxy(20,10) ;
write('здравствуйте , желаю успехов !') ;
repeat (цикл позволяет)
gotoxy(35,50);write('пробел'); (сменить экран}
read(kbd,а); (по нажатию клавиши)
until а=' '; (* 'пробел' )
cirscr;
end;
procedure STEPEN(a,b:real;var y:real);
begin
y:=exp(b*ln(a)) ;
end;
function MEXP(x:real):real;
begin
mexp:=l+x+x*x/2+x*x*x/6+x*x*x*x/24;
end;
Пусть представленные три подпрограммы записаны в файл с именем lab.pas. А теперь составим программу, использующую созданную внешнюю библиотеку.
Программа 21
program primeri;
($i lab) (директива подключения библиотеки} var a,b : real;
begin
PRIVET;
STEPEN(2,4,a); writeln('2 в степени 4 =',a); b:=MEXP(l);
write('машинная exp(1)=',EXP(1):6:4,' моя
exp(1)=',b:6:4);
end.
В программе используется стандартная функция - экспонента ЕХР(1) и наша подпрограмма МЕХР(1).
Модули используют в более поздних версиях Паскаля для создания библиотек и разделения больших программ на логически связанные независимые друг от друга составные части. В состав модуля входят следующие разделы: заголовок, интерфейс, реализация, инициализация. Заголовок необходим для ссылок на модуль. Интерфейс содержит объявления, включая процедуры и функции, представленные списком заголовков и доступные пользователям в теле основной программы. Раздел «реализация» содержит тела процедур и функций, перечисленных в интерфейсной части модуля. Раздел «инициализация» содержит операторы, необходимые для инициализации модуля. Таким образом модуль - это набор констант, типов данных, переменных, процедур и функций.
Каждый модуль компилируется отдельно; результат компилляции - файл с расширением .tpu (Turbo Pascal Unit). Каждый элемент модуля можно использовать в программе пользователя без дополнительного объявления, для чего достаточно записать имя используемого модуля в директиве Uses в начале программы после его заголовка.
В Турбо-Паскале версии 5.0 и выше применяют стандартные модули CRT, GRAPH и др. В этих модулях содержатся сервисные процедуры и функции по работе с экраном дисплея, с клавиатурой, графическими примитивами и т.п. Модули подключаются к программе путем специальной команды, размещаемой сразу после заголовка:
uses <имя модуля>
Программист может сам создать модуль. Ниже приведен пример с соответствующими комментариями.
Пример. Создать модуль, дополняющий математические возможности Паскаля арифметическими действиями над комплексными числами.
Будем представлять комплексные числа парами действительных: (а, b). Как известно, действия над ними выполняются по правилам
(a,b) + (c.d) = (a+c,b+d),
(a,b)-(c,d)=(a-^,b-d),
(a,b) * (c,d) = (a*c-b*d , a*d+b*c),
(a,b) / (c,d) = ( (a*c+b*d)/(c*c+d*d), (b*c-a*d)/(c*c+d*d)).
Создаваемый модуль будет включать четыре процедуры: Sum - сумма, Raz -разность, Proiz - произведение, Chastn - частное.
Этот модуль может быть отдельно откомпилирован. После этого любая программа, написанная на Паскале, может получить доступ к интерфейсным объектам (в данном случае - процедурам) этого модуля с помощью директивы Uses CompChisla.
Обратим внимание, что в интерфейсной части модуля от процедур присутствуют лишь заголовки, а в части «реализация» от заголовков процедур остаются лишь их имена.
Программа 22
unit CompChisla;
interface
procedure Sum(a,b,c,d: real; var x,y: real);
procedure Raz(a,b,c,d: real; var x,y: real);
procedure Proiz (a,b,c,d: real; var x,y:
real);
procedure Chstn(a,b,c,d: real; var x,y:
real);
implementation
procedure Sum;
begin x:=a+c;
y:=b+d end;
procedure Raz;
begin x:=a-c; y:=b-d end;
procedure Proiz;
begin x:=a*c-b*d; y:=a*d+b*c
end;
procedure Razn;
var z:real;
begin z:= c*c+d*d; x:=(a*c+b*d)/z; y:=(b*c-a*d)/z end;
end.
Контрольные вопросы
1. Какова структура процедуры? функции?
2. Какие параметры называют формальными и какие - фактическими?
3. В чем различие между локальными и глобальными переменными?
4. В чем сходство и различие между процедурой и модулем?