Подпрограммы
Функции
Функции являются такими же подпрограммами, как и процедуры, с одной разницей: они возвращают значение указанного типа. Функция начинается с ключевого слова function и имеет следующий синтаксис:
function <имя функции>(<список параметров>): <тип возвращаемого значения>; const <объявление констант>; type <объявление новых типов>; var <объявление переменных>; <описание вложенных процедур и функций>; begin <тело процедуры>; end;
В теле функции должен быть оператор, который присваивает возвращаемое значение стандартной переменной Result, что и приводит к возвращению функцией значения. Result объявлять не нужно, он уже есть в каждой функции. Разумеется, в Result нужно присваивать значение только указанного в заголовке типа. Пример:
function MyFunc(i: integer): integer; begin Result:= i * 2; end;
Здесь функция MyFunc принимает в качестве параметра какое-то целое число, удваивает его и присваивает результат переменной Result. Это приводит к тому, что функция возвращает этот результат. Теперь мы можем удвоить целое значение, вызвав эту функцию, например:
myperem:= 5; myperem:= MyFunc(myperem);
Что будет в результате в переменной myperem? Если вы ответили 10, то вы правы. Здесь мы в первом шаге присваиваем переменной целого типа myperem значение 5. Во втором шаге мы вызываем функцию MyFunc, передавая ей в качестве параметра значение myperem. В третьем шаге мы присваиваем полученный от функции результат удвоения снова в переменную myperem.
Кстати, вместо системной переменной Result можно использовать имя функции:
function MyFunc(i: integer): integer; begin MyFunc:= i * 2; end;
Данный пример даст точно такой же результат. Какой способ использовать - дело выбора. Лично я предпочитаю использовать Result, это выглядит как-то более стандартно. В любом случае, вы должны знать про оба способа.
В отличие от многих других языков, в Lazarus переменной Result (или имени функции) значение можно присваивать неоднократно, если этого требует логика подпрограммы. Например, функция получает два вещественных числа. Первое нужно разделить на второе, и результат вернуть. Но на ноль делить нельзя, поэтому во избежание зависания программы, если второе число - ноль, то и вернуть нужно ноль. Такую функцию можно реализовать следующим образом:
function Delenie(r1, r2: real): real; begin if r2 = 0 then Result:= 0 else Result:= r1 / r2; end;
Хорошо, опробуем функции на практике. Ниже Button1 добавьте Button2 с текстом в Caption:
Пример удвоения №2
Сгенерируйте для второй кнопки событие OnClick, чуть выше этого события опишите функцию удвоения FuncUdvoenie. В результате у вас получится следующее:
function FuncUdvoenie(st: string): string; var r: real; begin //полученную строку сначала преобразуем в число: r:= StrToFloat(st); //теперь удвоим его: r:= r * 2; //теперь вернем результат в виде строки: Result:= FloatToStr(r); end; procedure TfMain.Button2Click(Sender: TObject); begin ShowMessage(FuncUdvoenie(Edit1.Text)); end;
Обратите внимание, здесь мы пошли немного другим путем. Мы создали функцию, которая лишь возвращает результирующее число в виде строки, а вывод этой строки на экран организовали при вызове функции, в строке
ShowMessage(FuncUdvoenie(Edit1.Text));
Тут в первом шаге мы вызываем функцию FuncUdvoenie, передавая ей в качестве параметра текст из Edit1. Во втором шаге отрабатывает функция - преобразует этот текст в число, удваивает его, снова преобразует в строку, и результат возвращает компилятору. А в третьем шаге с помощью функции ShowMessage() мы выводим этот результат на экран. Реализовано иначе, но работать будет точно также. Попробуйте. И пока не закрывайте проект.
Параметры по ссылке
Параметры по ссылке позволяют изменять сами аргументы, поскольку в процедуру или функцию передается не копия аргумента, а ссылка на сам аргумент. Чтобы в функцию или процедуру передать параметр по ссылке, нужно перед параметром указать ключевое слово var, например:
procedure MyProc(var myparam: integer);
Если вы передаете в подпрограмму параметры как по значению, так и по ссылке, то параметры по ссылке должны идти в описании последними. Вот пример объявления процедуры с множеством параметров:
procedure MyProc2(a,b: integer; c: real; var s1, s2: string);
Здесь мы объявили три параметра по значению: a и b - целые числа, c - вещественное; и два параметра по ссылке - s1 и s2, оба строкового типа. Если внутри процедуры мы изменим все эти параметры, то исходные целые числа и вещественное число не изменятся, но изменения в обеих строках будут сохранены и после выхода из процедуры. Давайте попробуем поработать с параметрами по ссылке на практике. Сделайте в проекте третью кнопку, аналогично первым двум, и расположенную ниже. В свойстве Caption этой кнопки напишем:
Пример удвоения №3
Сгенерируйте событие OnClick для нее, и чуть выше опишите процедуру, которая будет принимать и изменять параметр по ссылке, следующим образом:
procedure UdvoeniePoSsilke(var r: real); begin r:= r * 2; end; procedure TfMain.Button3Click(Sender: TObject); var myReal: real; begin myReal:= StrToFloat(Edit1.Text); UdvoeniePoSsilke(myReal); ShowMessage(FloatToStr(myReal)); end;
Этот пример отличается от предыдущих, но выполняет ту же работу, и с тем же результатом. В процедуре UdvoeniePoSsilke всего одна строка
r:= r * 2;
Эта строка удваивает не просто параметр-копию, она удваивает сам аргумент! Поскольку перед параметром r указано ключевое слово var, то этот параметр - не копия аргумента, а ссылка на него. И удваивая r, мы удваиваем аргумент. Что и было продемонстрировано следующим событием нажатия на третью кнопку. Здесь, в первом шаге мы преобразуем строковое представление числа из Edit1 в число, и результат присваиваем вещественной переменной myReal. Затем, во втором шаге, мы передаем эту переменную в процедуру UdvoeniePoSsilke, которая изменяет значение myReal. Ну и, наконец, в третьем шаге, мы выводим результат на экран, предварительно преобразовав его в строковое представление. Надеюсь, вы не запутались в параметрах и аргументах?