Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

DiVM / OOP / 12_116608_1_51491

.pdf
Скачиваний:
18
Добавлен:
11.05.2015
Размер:
6.45 Mб
Скачать

Рисунок 2.4. Схема работы процедуры-оператора Continue

Процедура-оператор Break прерывает выполнение цикла и передает управление первому оператору, расположенному за блоком цикла (рисунок 2.5):

Рисунок 2.5. Схема работы процедуры-оператора Break

2.7.12. Оператор безусловного перехода

Среди операторов языка Delphi существует один редкий оператор, о котором авторы сперва хотели умолчать, но так и не решились. Это оператор безусловного перехода goto ("перейти к"). Он задумывался для того случая, когда после выполнения некоторого оператора надо выполнить не следующий по порядку, а какой-либо другой, отмеченный меткой, оператор.

Метка — это именованная точка в программе, в которую можно передать управление. Перед употреблением метка должна быть описана. Раздел описания меток начинается зарезервированным словом label, за которым следуют имена меток, разделенные запятыми. За последним именем ставится точка с запятой. Типичный пример описания меток:

label

Label1, Label2;

В разделе операторов метка записывается с двоеточием. Переход на метку выполняется с помощью зарезервированного слова goto, за которым следует имя метки:

61

Deleted: "нехороший"

program Console;

{$APPTYPE CONSOLE}

uses SysUtils;

label M1, M2;

begin M1:

Write('Желаем успеха '); goto M2;

Write('А этого сообщения вы никогда не увидите!'); M2:

goto M1;

Writeln('в освоении среды Delphi!'); Writeln('Press Enter to exit...'); Readln;

end.

Эта программа будет выполняться бесконечно, причем второй оператор Write не выполнится ни разу!

Внимание! В соответствии с правилами структурного программирования следует избегать применения оператора goto, поскольку оно усложняет понимание логики программы. Оператор goto использовался на заре программирования, когда выразительные возможности языков были скудными. В языке Delphi без него можно успешно обойтись, применяя условные операторы, операторы повтора, процедуры Break и Continue, операторы обработки исключений (последние описаны в главе 4).

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

2.8.1. Общие положения

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

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

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

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

Все процедуры и функции языка Delphi подразделяются на две группы: встроенные и определенные программистом.

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

62

Deleted: не следует использовать вообще

Deleted: его употребление

Deleted: резко

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

Процедуры и функции программиста пишутся программистом, т.е. вами, в соответствии с синтаксисом языка и представляют собой локальные блоки. Предварительное описание процедур и функций программиста обязательно.

2.8.2. Стандартные подпрограммы

Арифметические функции

Abs(X) Возвращает абсолютное значение аргумента X.

Exp(X) Возвращает значение ex.

Ln(X) Возвращает натуральный логарифм аргумента X.

Pi

Возвращает значение числа π.

Sqr(X) Возвращает квадрат аргумента X.

Sqrt(X) Возвращает квадратный корень аргумента X.

Примеры:

Выражение

Результат

Abs(–4)

4

Exp(1)

2.71828182845905

Ln(Exp(1))

1

Pi

3.14159265358979

Sqr(5)

25

Sqrt(25)

5

Тригонометрические функции

ArcTan(X Возвращает угол, тангенс которого равен X.

)

Cos(X) Возвращает косинус аргумента X (X задается в радианах).

Sin(X) Возвращает синус аргумента X (X задается в радианах).

Примеры:

 

Выражение

Результат

ArcTan(Sqrt(3))

1.04719755119660

Cos(Pi/3)

0.5

63

Sin(Pi/6)

0.5

Заметим, что в состав среды Delphi входит стандартный модуль Math, который содержит высокопроизводительные подпрограммы для тригонометрических, логорифмических, статистических и финансовых вычислений.

Функции выделения целой или дробной части

Frac(X) Возвращает дробную часть аргумента X.

Int(X) Возвращает целую часть вещественного числа X. Результат принадлежит вещественному типу.

Trunc(X) Возвращает целую часть вещественного числа X. Результат принадлежит целому типу.

Round(X) Округляет вещественное число X до ближайшего целого. Если число X находится строго посередине между целыми числами, то округление выполняется до ближайшего четного целого числа (см. примеры ниже). Такое округление называется "округлением банкира", оно применяется в банках и бухгалтериях при работе с деньгами. Для других расчетных задач это округление может не подойти.

Примеры:

Выражение

Результат

Frac(1.5)

0.5

Int(1.5)

1.0

Trunc(1.5)

1

Round(1.5)

2

Round(2.5)

2

Функции генерации случайных чисел

Random Возвращает случайное вещественное число в диапазоне 0 <= X < 1.

Random(I) Возвращает случайное целое число в диапазоне 0 <= X < I.

Randomiz Заново инициализирует встроенный генератор случайных

eчисел новым значением, полученным от системного таймера.

Подпрограммы для работы с порядковыми величинами

Chr(X) Возвращает символ, порядковый номер которого равен X.

Dec(X, Уменьшает целую переменную X на 1 или на заданное

64

[N])

число N.

 

 

 

Inc(X,

Увеличивает целую переменную X на 1 или на заданное

[N])

число N.

 

 

 

Odd(X)

Возвращает True, если аргумент X является нечетным

 

числом.

 

 

 

Ord(X)

Возвращает порядковый номер аргумента X в своем

 

диапазоне значений.

 

 

Pred(X)

Возвращает

значение,

предшествующее

значению

аргумента X в своем диапазоне.

Succ(X) Возвращает значение, следующее за значением аргумента X в своем диапазоне.

Примеры:

Выражение

Результат

Chr(65)

'A'

Odd(3)

True

Ord('A')

65

Pred('B')

'A'

Succ('A')

'B'

Подпрограммы для работы с датой и временем

Date

Возвращает текущую дату в формате TDateTime.

Time

Возвращает текущее время в формате TDateTime.

Now

Возвращает текущие дату и время в формате

 

TDateTime.

DayOfWeek(D

Возвращает день недели по дате в формате

)

TDateTime.

DecodeDate(...

Разбивает значение даты на год, месяц и день.

)

 

DecodeTime(..

Разбивает значение времени на час, минуты,

.)

секунды и милисекунды.

EncodeDate(...

Формирует значение даты по году, месяцу и дню.

)

 

EncodeTime(..

Формирует значение времени по часу, минутам,

.)

секундам и милисекундам.

65

Процедуры передачи управления

 

 

 

Break

Прерывает выполнение цикла.

 

 

Continue

Начинает новое повторение цикла.

 

 

Exit

Прерывает выполнение текущего блока.

 

Halt

Останавливает

выполнение

программы

и

 

возвращает управление операционной системе.

 

RunError

Останавливает выполнение программы, генерируя

 

ошибку времени выполнения.

 

 

Разные процедуры и функции

FillChar(...) Заполняет непрерывную область символьным или байтовым значением.

Hi(X)

Возвращает старший байт аргумента X.

 

 

High(X)

Возвращает самое старшее значение в диапазоне

 

аргумента X.

 

 

 

 

Lo(X)

Возвращает младший байт аргумента X.

 

 

Low(X)

Возвращает самое младшее значение в диапазоне

 

аргумента X.

 

 

 

 

Move(...)

Копирует заданное количество байт из одной

 

переменной в другую.

 

 

 

ParamCount

Возвращает количество параметров, переданных

 

программе в командной строке.

 

 

 

ParamStr(X)

Возвращает параметр командной строки по его

 

номеру.

 

 

 

 

 

SizeOf(X)

Возвращает

 

количество

байт,

занимаемое

 

аргументом X в памяти. Функция SizeOf особенно

 

нужна для определения размеров переменных

 

обощенных типов данных, поскольку представление

 

обощенных типов данных в памяти может

 

изменяться от одной версии среды Delphi к другой.

 

Рекомендуем всегда использовать эту функцию для

 

определения размера переменных любых типов

 

данных;

это

считается

хорошим

стилем

программирования.

Swap(X) Меняет местами значения старшего и младшего байтов аргумента.

UpCase(C) Возвращает символ C, преобразованный к верхнему регистру.

66

Примеры:

 

Выражение

Результат

Hi($F00F)

$F0

Lo($F00F)

$0F

High(Integer)

32767

Low(Integer)

–32768

SizeOf(Integer)

2

Swap($F00F)

$0FF0

UpCase('a')

'A'

2.8.3. Процедуры программиста

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

procedure <имя процедуры> ( <список формальных параметров> ) ; const ...;

type ...; var ...; begin

<операторы> end;

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

Вызов процедуры для выполнения осуществляется по ее имени, за которым в круглых скобках следует список фактических параметров, т.е. передаваемых в процедуру данных:

<имя процедуры> ( <список фактических параметров> );

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

Понятие процедуры является чрезвычайно важным, так как именно оно лежит в основе одной из самых популярных технологий решения задач на языке Delphi. Технология эта внешне проста: задача разбивается на несколько логически обособленных подзадач и решение каждой из них оформляется в виде отдельной процедуры. Любая процедура может содержать в себе другие процедуры, их количество ограничено только объемом памяти вашего компьютера.

67

Приведем пример небольшой программы, использующей процедуру Power для вычисления числа X в степени Y. Результат вычисления процедура Power заносит в глобальную переменную Z.

program Console;

{$APPTYPE CONSOLE}

uses SysUtils;

var

Z: Double;

procedure Power(X, Y: Double); // X и Y - формальные параметры begin

Z := Exp(Y * Ln(X)); end;

begin

Power(2, 3); // 2 и 3 - фактические параметры

Writeln('2 в степени 3 = ', Z); Writeln('Press Enter to exit...'); Readln;

end.

2.8.4. Функции программиста

Функции программиста применяются в тех случаях, когда надо создать подпрограмму, участвующую в выражении как операнд. Как и процедура, функция состоит из заголовка и блока. Заголовок функции состоит из зарезервированного слова function, имени функции, необязательного заключенного в круглые скобки списка формальных параметров и типа возвращаемого функцией значения. Функции возвращают значения любых типов данных кроме Text и file of (см. файлы). Тело функции представляет собой локальный блок, по структуре аналогичный программе.

function <имя функции> ( <список формальных параметров> ): <тип результата>; const ...;

type ...; var ...; begin

<операторы> end;

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

Вкачестве примера заменим явно неуклюжую процедуру Power (см. выше) на функцию с таким же именем:

68

program Console;

{$APPTYPE CONSOLE}

uses SysUtils;

function

Power(X, Y: Double): Double;

// X и Y - формальные параметры

begin

:= Exp(Y * Ln(X));

 

Result

 

end;

 

 

begin

Writeln('2 в степени 3 = ', Power(2, 3)); // 2 и 3 - фактические параметры Writeln('Press Enter to exit...');

Readln; end.

2.8.5. Параметры процедур и функций

Параметры служат для передачи исходных данных в подпрограммы и для приема результатов работы этих подпрограмм.

Исходные данные передаются в подпрограмму с помощью входных параметров, а результаты работы подпрограммы возвращаются через выходные параметры. Параметры могут быть входными и выходными одновременно.

Входные параметры объявляются с помощью ключевого слова const; их значения не могут быть изменены внутри подпрограммы:

function Min(const A, B: Integer): Integer; begin

if A < B then Result := A else Result := B;

end;

Для объявления выходных параметров служит ключевое слово out:

procedure GetScreenResolution(out Width, Height: Integer); begin

Width := GetScreenWidth; Height := GetScreenHeight;

end;

Установка значений выходных параметров внутри подпрограммы приводит к установке значений переменных, переданных в качестве аргументов:

var

W, H: Integer; begin

GetScreenResolution(W, H);

...

end;

После вызова процедуры GetScreenResolution переменные W и H будут содержать значения, которые были присвоены формальным параметрам Width и Height соответственно.

Если параметр является одновременно и входным, и выходным, то он описывается с ключевым словом var:

69

procedure Exchange(var A, B: Integer); var

C: Integer; begin

C := A;

A := B;

B := C; end;

Изменение значений var-параметров внутри подпрограммы приводит к изменению значений переменных, переданных в качестве аргументов:

var

X, Y: Integer; begin

X := 5;

Y := 10;

...

Exchange(X, Y);

// Теперь X = 10, Y = 5

...

end;

При вызове подпрограмм на место out- и var-параметров можно подставлять только переменные, но не константы и не выражения.

Если при описании параметра не указано ни одно из ключевых слов const, out, или var, то параметр считается входным, его можно изменять, но все изменения не влияют на фактический аргумент, поскольку они выполняются с копией аргумента, создаваемой на время работы подпрограммы. При вызове подпрограммы на месте такого параметра можно использовать константы и выражения. Пример подпрограммы:

function NumberOfSetBits(A: Cardinal): Byte; begin

Result := 0; while A <> 0 do begin

Result := Result + (A mod 2); A := A div 2;

end; end;

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

Разные способы передачи параметров (const, out, var и без них) можно совмещать в одной подпрограмме. В следующем законченном примере процедура Average принимает четыре параметра. Первые два (X и Y) являются входными и служат для передачи исходных данных. Вторые два параметра являются выходными и служат для приема в вызывающей программе результатов вычисления среднего арифметического (M) и среднего геометрического (P) от значений X и Y:

70