Песни о Паскале
Шрифт:
Writeln(Scan(S));
end;
Readln;
end.
Когда результат не важен
Хорошая функция возвращает правильный результат, а отличная делает ещё что-нибудь полезное. Программисты нередко поручают одной функции несколько дел, вот пример: напишем функцию Swap (обмен) булевого типа, принимающую ссылки на две переменные. Функция должна сравнить эти переменные и вернуть TRUE, если первая из них окажется больше второй. Мало того, в этом случае она должна обменять значения этих переменных (как в процедуре Swap, рассмотренной ранее).
function Swap( var a1, a2 : integer) : Boolean;
var t: integer;
begin
if a1 > a2
then begin
{ обмен значений переменных }
t:=a1; a1:=a2; a2:=t;
Swap:= true
end
else Swap:= false
end;
Где применить такую функцию? Пусть переменные N1, N2, N3 содержат три разных числа. Переложим эти числа так, чтобы в N1 оказалось наименьшее, а в N3 – наибольшее число, то есть, чтобы соблюдалось условие: N1 < N2 < N3. Такая сортировка выполняется тремя вызовами функции Swap (в комментариях показаны результаты обмена).
Swap(N1, N2); { N1 < N2 }
if Swap(N2, N3) { N2 < N3 }
then Swap(N1, N2); { N1 < N2 < N3 }
Здесь в первой и третьей строках функция вызывается как процедура, поскольку возвращаемый ею булев результат не используется. Во второй строке она вызывается как функция, поскольку результат использован оператором IF.
Возможность вызывать функцию как процедуру называют расширенным синтаксисом (Extended syntax), – он должен быть разрешен в настройках компилятора, иначе вызов функции как процедуры компилятор сочтет ошибкой.
Неявная переменная Result
Современные версии компиляторов дают новую возможность в части построения функций. Так, компилятор Delphi позволяет, наряду с именем функции, для возврата результата использовать автоматически объявляемую переменную Result. Тип переменной Result совпадает с типом функции. Тогда функцию подсчета символов можно упростить так:
function Count(const str : string; ch: char): integer;
var i: integer;
begin
Result:=0; { обнуляем счетчик }
for i:=1 to Length(str) do
if str[i]=ch then Result:= Result + 1;
end;
Как видите, переменную Result можно использовать как в левой, так и в правой части оператора присваивания. Последнее значение переменной станет результатом функции.
Итак, потратив три главы на изучение процедур и функций, мы готовы, наконец, к настоящему делу. Сколько можно в цацки играть? В следующей главе приступим к шифрованию файлов!
Итоги
• Функции – это подпрограммы, возвращающие результат через свое имя. Тип возвращаемого результата указывают в заголовке функции.
• В теле функции обязательно присваивают значение функции (через её имя), иначе результат останется неопределенным, случайным.
• Вызовы функций можно использовать в выражениях наряду с константами и переменными.
• Когда результат функции не используется, её вызывают как процедуру. При этом через настройки компилятора должен
А слабо?
А) Напишите функцию для поиска буквы в заданной строке. Она должна возвращать TRUE, если в строке есть хоть одна эта буква, и FALSE в противном случае. Напишите программу для проверки функции. Или слабо?
Б) Напишите функцию для определения позиции буквы в заданной строке. Функция должна вернуть позицию первой такой буквы или ноль, если буквы в строке нет. Напишите программу для проверки функции.
В) Напишите функцию и программу для её проверки, принимающую число и возвращающую строку: слово «четное» или «нечетное» в зависимости от четности или нечетности параметра. Подсказка: для проверки четности числа N надо проверить остаток от его деления на два: if (N mod 2) = 0 then …
Глава 24
Криптография
Говорят, что хороший разведчик стоит целой дивизии. Ещё бы! Ведь лишенный секретов противник почти безоружен. Но вот умолкли пушки, а разведка не спит, – у мирного времени свои тайны: коммерческие и технические секреты. Впрочем, если секретов нет, их можно придумать, – почему бы нам не поиграть в шпионов? Приятно сознавать, что «отмыленное» приятелю письмо никто, кроме вас двоих, не прочтет, – надо лишь зашифровать его. Придумана уйма способов шифрования, есть даже наука об этом – криптография; сейчас и мы коснемся краешка этой премудрости.
Секреты Юлия Цезаря
Римскому полководцу Юлию Цезарю выпали лихие времена. Отправляя гонца с письмом в отдаленный уголок империи, Цезарь рисковал «подарить» свои тайны недругам, – ведь на дорогах было неспокойно. Это надоумило его шифровать свои письма. В чем заключался метод Цезаря?
Прием Юлия состоял в замене одних букв другими путем кругового сдвига алфавита на несколько позиций. На рис. 54 показано превращение букв при сдвиге алфавита на две позиции. Буква «А» становится буквой «В», буква «Б» – буквой «Г» и так далее. Двум последним уготовано превратиться соответственно в буквы «А» и «Б». Такое шифрование превращает письмо в дикую абракадабру!
Рис.54 – Принцип шифрования Юлия Цезаря
Как расшифровать её? Очень просто – сдвинуть буквы в обратную сторону. Но надо знать количество сдвигов – это число называют ключом шифра (в примере на рисунке ключ шифра равен двум). Разумеется, что ключ шифра и метод шифрования знали лишь двое: получатель письма и сам Юлий Цезарь.
Пойдем и мы вслед римскому полководцу, – создадим программу для шифрования текстового файла и его расшифровки. Скажу прямо: задача непростая, а потому решать её будем в два этапа. Вначале освоим шифрование отдельной строки, а уж потом «замахнемся» на файл. Но начнем с шифрования отдельного символа.