Литмир - Электронная Библиотека

procedure Calc(var arg: string; Ch: char; var Res: integer);

Этот вариант лучше, но не сработает, если в вызове процедуры указать строковую константу, например:

      Calc(’PASCAL’, ’L’, Result);

Здесь компилятор воспротивится не на шутку, требуя в первом параметре переменную. И будет прав, поскольку ключевое слово VAR в заголовке процедуры объявляет ссылку на переменную, а не на константу. Что делать? Вернуться к первому способу? Нет, есть лучшее средство: вместо ключевого слова VAR укажите в заголовке слово CONST, вот так:

procedure Calc(const arg: string; Ch: char; var Res: integer);

Такая ссылка будет годна как для переменной, так и для константы.

      Calc(’PASCAL’, ’L’, Result);       { вызов с константой }

      Calc(S, ’L’, Result);       { вызов с переменной }

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

Итоги

• Количество фактических параметров, их тип и порядок следования в вызове должны совпадать со списком формальных параметров процедуры.

• Для экономии памяти и повышения быстродействия строковые данные (и другие сложные типы данных) передают по ссылке с применением ключевых слов CONST и VAR.

• Если строку передают по ссылке только внутрь процедуры, используют ключевое слово CONST, а если обратно или в оба направления – слово VAR.

• Если строка передается только внутрь процедуры и далее применяется там как локальная переменная, то ключевые слова CONST и VAR в объявлении параметра не ставят (так происходит передача параметра по значению).

А слабо?

А) Введите в компьютер программу «P_22_1» и проверьте её работу.

Б) Измените программу «P_20_1» так, чтобы заменяемый и замещаемый символы передавались в процедуру Scan через параметры.

В) Напишите программу для проверки рассмотренной выше процедуры Calc, подсчитывающей символ в строке.

Глава 23

Функции

Песни о Паскале (СИ) - _80.jpg

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

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

      x:= 1+ Random(10);       { арифметическое выражение }

      Writeln(Length(S)); { печатается длина строки S };

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

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

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

function Имя_Функции : Тип;       { функция без параметров }

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

Отличий от процедуры всего два. Во-первых, вместо ключевого слова PROCEDURE указано слово FUNCTION. А во-вторых, завершает заголовок тип функции (тип возвращаемого ею результата), – его указывают после двоеточия.

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

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

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 (подсчет).

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; { – это ошибка! }

31
{"b":"596178","o":1}