Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi / песни о паскале.pdf
Скачиваний:
63
Добавлен:
26.03.2016
Размер:
5.16 Mб
Скачать

Глава 23 Функции

Процедуры и функции — сестры-близнецы, потому и носят общее имя — подпрограммы. Всё, что сказано о передаче параметров, относится и к тем, и к другим. И всё же функции чем-то отличаются от процедур, иначе, зачем их придумали? А затем, чтобы упростить возвращение результата.

Нередко таким результатом бывает число, строка, символ или булево значение. Конечно, вернуть результат можно и через ссылку на переменную, но функция сделает это удобней — через своё имя. Результат, возвращаемый функцией, можно вставлять внутрь выражений наряду с переменными и константами. Взять хотя бы знакомые нам функции Random и Length, вызовы которых можно применить, например, так.

x:= 1+ Random(10);

{

арифметическое выражение }

Writeln(Length(S));

{

печатается длина строки S };

 

 

 

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

Объявление функции

Подобно объявлению процедуры, объявление функции состоит из заголовка и тела. Тело строят по тем же правилам, что и для процедур, а вот заголовок выглядит немного иначе.

function Имя_Функции : Тип;

{ функция без параметров }

function Имя_Функции (Параметры) : Тип;

{ функция с параметрами }

 

Отличий от процедуры всего два. Во-первых, вместо ключевого слова

PROCEDURE указано слово FUNCTION.

А во-вторых, завершает заголовок тип

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

Пример функции

Разберем всё это на примере. Создадим функцию, выбирающую большее из двух чисел. Разумеется, что функция будет принимать два параметра — сравниваемые числа, и возвращать будет тоже число. Стало быть, её заголовок может быть таким:

148

Глава 23

Функции

function Max(arg1, arg2 : integer) : integer;

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

function Max(arg1, arg2 : integer) : integer; begin

if arg1 > arg2

then Max:= arg1 else Max:= arg2

end;

Но откуда взялась переменная Max, которой присваиваем значение? Ведь мы её не объявляли! А её и не надо объявлять, — это имя нашей функции, оно и принимает в себя результат. Мало того, если результату не присвоить значение, он останется неопределенным, и это будет ошибкой!

Созданная нами функция может вызываться так.

A:= Max(

20, 10 );

{

A = 20 }

Writeln(

Max( A, B ) );

{

печатается большее из A и B }

 

 

 

 

Вызов функции можно использовать даже как фактический параметр в её собственном вызове, то есть организовать вложенные вызовы, например:

A:=

Max

(

Max(

20,

10

),

40 );

{

A

=

40 }

A:=

Max

(

Max(

20,

10

),

Max( 200, 100 ) );

{

A

=

200 }

 

 

 

 

 

 

 

 

 

 

 

 

В первом случае сначала вызывается функция Max(20,10), вставленная как первый фактический параметр, а затем Max(20,40), — то есть результат первого вызова подставляется параметром во второй. Похоже работает и другой пример, только функция вызывается трижды. Полезно понаблюдать за такими вызовами через отладчик. Напишите главную программу для исследования функции Max и прогоните её в отладчике.

Подсчет символов в строке

В прошлой главе я предложил вам написать процедуру для подсчета заданного символа в строке. Если вы справились с той задачей, то для возврата результата наверняка воспользовались ссылкой на переменную. Теперь рассмотрим решение с применением функции.

Начнем, разумеется, с заголовка функции, дадим ей имя Count (подсчет).

149

Глава 23

Функции

function Count(const Str : string; Ch : char): integer;

Функция принимает два параметра: ссылку на строку и символ, который надо подсчитать. Напомню, что ключевое слово CONST в объявлении параметра позволяет ссылаться и на константу, и на переменную. Тело функции строим на базе цикла со счетчиком.

function Count(const str : string; ch: char): integer; var N, i: integer;

begin

N:=0; { обнуляем счетчик } for i:=1 to Length(str) do

if str[i]=ch then N:= N+1;

Count:= N; { определяем результат функции }

end;

Подсчет символов в массиве ведется в локальной переменной N, и лишь по завершении цикла результат копируется в имя функции. Грубой ошибкой было бы накапливать счетчик прямо в имени функции:

if str[i]=ch then Count:= Count+1; { - это ошибка! }

Запомните: в теле функции её имя применяется только слева от оператора присваивания! Есть исключения из этого правила, но мы пока не будем их касаться.

И, наконец, напишем программу P_22_1 для проверки функции Count. В главной программе функция вызывается сначала для переменной S, а затем для константы «BANAN». Причем во втором случае она вызывается дважды, а результат суммируется. Испытайте эту программу.

{ P_23_1 – подсчет заданных символов в строке }

function Count(const str : string; ch: char): integer; var N, i: integer;

begin

N:=0; { обнуляем счетчик } for i:=1 to Length(str) do

if str[i]=ch then N:= N+1;

Count:= N; { передаем результат через имя функции }

end;

150

Глава 23

Функции

var S: string;

begin {--- главная программа ---} S:='PASCAL';

Writeln( Count(S, 'A'));

Writeln( Count('BANAN', 'N') + Count('BANAN', 'B'));

Readln;

end.

Возврат строк

Вернемся к программе P_20_1, заменяющей символы «A» на символы «B». Помните сколько крови она попортила прежде чем заработать? Заменив процедуру Scan на функцию с тем же именем, мы решим проблему возврата результата. Результат, разумеется, должен иметь строковый тип. Обратите внимание на то, что ключевые слова VAR или CONST в заголовке не указаны, а потому параметр arg можно употребить в теле функции в качестве локальной переменной.

{ P_23_2 – замена символов в строке с применением функции }

function Scan(arg : string): string; var k: integer;

begin

for k:=1 to Length(arg) do

if arg[k]=’A’ then arg[k]:=’B’; { замена в параметре arg } Scan:= arg;

end;

 

var S: string;

k: integer;

begin {--- главная программа ---}

for k:=1 to 3 do begin

Write(’Введите строку: ’); Readln(S);

Writeln(Scan(S));

end;

Readln;

end.

Когда результат не важен

Хорошая функция возвращает правильный результат, а отличная делает ещё что-нибудь полезное. Программисты нередко поручают одной функции несколько дел, вот пример: напишем функцию Swap (обмен) булевого типа, принимающую ссылки на две переменные. Функция должна сравнить эти переменные и вернуть TRUE, если первая из них окажется больше второй. Мало того, в этом случае она

151

Соседние файлы в папке delphi