Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
7. Delphi динамические массивы, процедуры, функ....doc
Скачиваний:
10
Добавлен:
17.12.2018
Размер:
223.23 Кб
Скачать

Внутри функции обязательно должно присваиваться значение переменной Result

  1. Процедуры

Если уж вы открыли банку с червями, то единственный способ

снова их запечатать - это воспользоваться банкой большего размера.

Из законов Мэрфи.

Процедура похожа на функцию, но обычно не возвращает значения (хотя и это возможно). Процедуру можно представить себе как полноценную маленькую программу со своими константами, переменными, типами данных и пр. Описание процедуры очень похоже на описание функции:

PROCEDURE имя_процедуры (арг1:тип; … аргn : тип);

раздел локальных описаний

BEGIN

операторы

END;

Глобальные процедуры тоже описываются после оператора IMPLEMENTATION. Как и в случае функции, в процедуру могут передаваться данные. Вызов процедуры состоит просто из написания ее названия. Например, создадим процедуру, завершающую работу всей программы и назовем ее Stop:

PROCEDURE Stop;

BEGIN

Form1.Close

END;

Вот как выглядит ее вызов:

BEGIN

. . .

Stop;

. . .

END;

Фактически в язык Delphi мы добавили новый оператор и назвали его Stop.

  1. Передача данных в процедуры

Две интересные передачи всегда идут в одно и то же время.

Из законов Мэрфи.

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

PROCEDURE ShowMax(a, b : REAL);

VAR r:REAL;

BEGIN

r:=a-b;

IF r>0 THEN

Form1.Label1.Caption:= FloatToStr(r)

END;

Поскольку процедура ShowMax ничего не знает про форму Form1 и компонент Label1, придется указывать полный путь к нему: Form1.Label1. Обработчики событий компонентов относятся к форме (являются ее методами) и внутри них Form1 можно не писать.

Здесь r – локальная переменная процедуры, она существует только внутри нее. При вызове такой процедуры ей на вход надо подать два числа, например:

ShowMax(10, 2*a-45);

Обратите внимание, что здесь a – совсем другая переменная, не имеющая отношения к переменной a в заголовке процедуры. Значение 10 будет занесено в локальную переменную a, а вычисленное значение 2*a-45 – в локальную переменную b.

Такой способ передачи данных называется "по значению" (by value). У него есть два недостатка. Во-первых, он позволяет передавать информацию только в одну сторону – из вызывающей программы в процедуру. Во-вторых, при передаче больших объемов данных, скажем, больших массивов, они каждый раз полностью копируются из одной области памяти в другую, на что уходит много ресурсов компьютера.

Для решения вопроса с возвратом значения из процедуры в Delphi предусмотрен второй механизм передачи данных, называемый "по ссылке" (by reference). Его смысл состоит в том, что в процедуру передается адрес переменной, которая описана в вызывающей программе. Зная адрес, процедура может напрямую занести в эту переменную требуемое значение.

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

PROCEDURE Hypot (a,b:REAL; VAR c:REAL);

VAR h:REAL;

BEGIN

h:= SQR(a)+SQR(b);

c:=SQRT(h)

END;

Весь фокус заключается в слове VAR, стоящем в заголовке перед именем переменной-аргумента c. Слово VAR в заголовке процедуры не имеет никакого отношения к выделению памяти1. Оно указывает на то, что указанную после него переменную можно изменять внутри процедуры и измененное значение вернется в вызывающую программу.

При обращении к процедуре Hypot третьим ее параметром обязательно должно идти имя переменной. Следующая запись правильна:

VAR h:REAL;

. . .

BEGIN

. . .

Hypot(a+b, 45, h)

Величина гипотенузы будет записана в переменную h.

А так делать нельзя:

Hypot(a+b, 45, h*4)

Выражение h*4 не является именем переменной и в него нельзя записать значение.

В качестве параметров процедур и функций могут быть и массивы. Рассмотрим пример программы, в которой нахождение минимального элемента массива оформлено в виде процедуры.

CONST Nmax=20;

TYPE TA=ARRAY[1..Nmax] OF REAL;

VAR a:TA; i:BYTE; min:REAL;

PROCEDURE FindMin(ar:TA; n:BYTE; VAR min:REAL);

VAR i:BYTE;

BEGIN

min:=ar[1];

FOR i:=2 TO n DO

IF ar[i]<min THEN

min := ar[i]

END;

BEGIN

FOR i:=1 TO Nmax DO

a[i]:=RANDOM;

FindMin(a,Nmax,min);

Label1.Caption:=FloatToStrF(min,ffFixed,10,4)

END.

В процедуру или функцию нужно передать и динамический массив. Напишем универсальную функцию поиска максимального элемента в массиве вещественных чисел любого размера:

FUNCTION FindMax(a:ARRAY OF REAL):REAL;

VAR i:WORD;

BEGIN

Result:=a[Low(a)];

FOR i:=Low(a)+1 TO High(a) DO

IF a[i]>Result THEN

Result:=a[i]

END;

На блок-схемах вызов процедуры или функции обозначается в виде . На каждую процедуру изображается отдельная блок-схема.