Опубликован: 25.06.2014 | Уровень: для всех | Доступ: платный | ВУЗ: Учебный центр "ANIT Texno Inform"
Лекция 9:

Подпрограммы

< Лекция 8 || Лекция 9: 123 || Лекция 10 >

Функции

Функции являются такими же подпрограммами, как и процедуры, с одной разницей: они возвращают значение указанного типа. Функция начинается с ключевого слова 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. Ну и, наконец, в третьем шаге, мы выводим результат на экран, предварительно преобразовав его в строковое представление. Надеюсь, вы не запутались в параметрах и аргументах?

< Лекция 8 || Лекция 9: 123 || Лекция 10 >
Инга Готфрид
Инга Готфрид
Александр Скрябнев
Александр Скрябнев

Через WMI, или используя утилиту wmic? А может есть еще какие более простые пути...