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

Ситкин. Информатика. Программирование в DELPHI

.pdf
Скачиваний:
142
Добавлен:
18.07.2019
Размер:
1.49 Mб
Скачать

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

Параметры подпрограмм можно разделить на входные, которые передают значения в подпрограмму и выходные, которые передают результаты её работы обратно в вызывающий блок. Входные пара-

метры это параметры-значения. По умолчанию все параметры па-

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

даются. Выходные параметры это параметры-переменные. Они мо-

гут передавать значения в подпрограмму, могут там изменяться и мо-

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

ветствующим формальным параметром в заголовке подпрограммы нужно поставить слово var, например,

procedure My_Procedure(x, y: real; var z: real);

здесь x и y параметры-значения, а z параметр-переменная, или procedure My_Procedure(var x, y: real; z: real);

здесь уже x и y параметры-переменные, а z параметр-значение.

Поскольку параметр-переменная способен передавать значения в обе стороны, возникает соблазн во избежание путаницы «что куда передаёт» все формальные параметры сделать таковыми

procedure My_Procedure(var x, y, z: real);

но параметр-переменная (в отличие от параметра-значения) не может передать в подпрограмму выражение или константу, а только отдель-

ную переменную. Кроме того, передавая значение в подпрограмму через параметр-переменную, и возвращая значение обратно через не-

го же, следует помнить, что старое значение будет потеряно.

41

Функция возвращает значение в вызывающий блок через своё имя, поэтому в описании функции параметры-переменные не вводят

(исключения составляют случаи, когда функция должна вернуть бо-

лее одного значения, т.к. к её имени можно привязать только одно).

Имя процедуры не является носителем значения, поэтому, если про-

цедура должны вернуть в вызывающий блок значение, то вводят па-

раметр-переменную, если должна вернуть два значения, то вводят два параметра-переменных и т.д. Также значение в вызывающий блок можно вернуть из подпрограммы через глобальную переменную.

Пример 3.1

Разработаем проекты для вычисления значения выражения

z a

x2

5

a2

y2 5

 

( y 2)

2 5

,

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

x

 

5

 

 

y

 

5

 

 

y 2

 

5

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

где x и y переменные, a константа с использованием подпрограмм.

В выражении видны повторяющиеся действия, выполняемые в дробях: в первой дроби над переменной x, во второй над перемен-

ной y и в третьей над выражением y 2. Чтобы многократно не про-

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

полнять типовое для данного выражения действие, а именно вычис-

лять значение дроби вида (t2+5)/( t +5), где t некоторый формаль-

ный (абстрактный) параметр, который показывает, что должно быть выполнено над подставленным в подпрограмму реальным, т.е. факти-

ческим параметром. Трижды вызвав подпрограмму с фактическими параметрами x, затем y, затем y 2, вычислим значения трёх дробей.

42

На рис. 3.1 и 3.2 представлены блок-схемы алгоритмов выпол-

нения типового действия и основного вычисления соответственно.

начало

начало

1

 

 

 

 

 

 

 

a=3

 

 

c = 5

 

z=az1+a2z2 +z3

 

 

 

 

 

 

 

ввод x, y

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

t1 = t2+c

 

вычисление

 

вывод z

 

значения z1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

конец

 

 

 

 

 

 

 

 

 

 

 

 

 

 

c

 

вычисление

 

t2 =

 

t

 

 

 

 

 

 

 

 

 

 

значения z2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

d=t1/t2

 

вычисление

 

 

 

значения z3

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

конец

1

 

 

Рис. 3.1

 

Рис. 3.2

Реализуем разработанные алгоритмы в проекте. Форму с компо-

нентами и событие, связанное с расчётом, оставим теми же, как и в предыдущей работе. Оформим нашу пользовательскую подпрограмму сначала как функцию, прописав её в модуле проекта после слова implementation, но до процедуры обработки события. А в этой про-

цедуре процессы вычисления трёх дробей опишем не как в предыду-

щей работе, а трижды вызвав функцию. Назовем её, например, «drob». Значение дроби, которое будет вычислять функция, относится к вещественному типу, как и формальный параметр t, поэтому в заго-

ловке функции укажем вещественный тип для t и для значения, выра-

батываемого функцией (в конце заголовка), например, «real».

43

implementation

{$R *.dfm}

function drob(t:real):real; //заголовок пользовательской функции const c=5; //объявление локальной константы

var t1, t2:real; //объявление локальных переменных

begin //начало раздела операторов пользовательской функции t1:=sqr(t)+c; //промежуточные расчёты внутри функции t2:=sqrt(abs(t))+c; //промежуточные расчёты внутри функции drob:=t1/t2; //присвоение имени функции значения (результата)

end; //конец пользовательской функции

procedure TForm1.Button1Click(Sender: TObject);

const a=3;

var x, y, z, z1, z2, z3:real;

begin

x:=StrToFloat(Edit1.Text); // считывание значения x из Edit1

y:=StrToFloat(Edit2.Text); //считывание значения y из Edit2

z1:=drob(x); //вызовы функции и

z2:=drob(y);

//присвоение её значений

z3:=drob(y-2); //промежуточным переменным

z:=a*z1+sqr(a)*z2+z3; //итоговые вычисления

Label3.Caption:='z='+ FloatToStr(z); //вывод значения z в Label3

end; //конец процедуры обработки события

end. //конец модуля проекта

Имя функции носитель значения, в данном случае это число. Умно-

жить одно число на другое или сложить их допустимо, поэтому мож-

но было сразу записать z:=a*drob(x)+sqr(a)*drob(y)+drob(y-2);.

Оформим теперь нашу подпрограмму как процедуру.

44

implementation

{$R *.dfm}

procedure drob(t:real; var d:real); //добавлен параметр-переменная d

const c=5;

var t1, t2:real;

begin

t1:=sqr(t)+c;

t2:=sqrt(abs(t))+c;

d:=t1/t2; //результат присваивается теперь параметру-переменной d

end;

procedure TForm1.Button1Click(Sender: TObject); const a=3;

var x, y, z, z1, z2, z3:real;

begin

x:=StrToFloat(Edit1.Text);

y:=StrToFloat(Edit2.Text);

drob(x, z1); //вызовы процедуры отдельными операторами drob(y, z2); //без операторов присвоения, т.к. имя процедуры drob(y-2, z3); //не несёт в себе значения (в данном случае числа)

z:=a*z1+sqr(a)*z2+z3; Label3.Caption:='z='+ FloatToStr(z);

end;

end.

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

ловке нашей подпрограммы не указан тип значения, вырабатываемого

45

процедурой. Введён второй формальный параметр d как параметр-

переменная (перед ним стоит var) для передачи результатов работы процедуры в вызывающий блок, т.к. через имя процедуры его не пе-

редать (результат присвоен параметру d, а не drob). Во-вторых, вызов drob осуществляется отдельным оператором без присвоений значений промежуточным переменным. Фактических параметров стало два, как стало и формальных. Теперь результат работы подпрограммы (число)

содержится не в имени drob (как было с функцией), а в параметре zi.

Запись вида «z:=a*drob(x, z1) + sqr(a)*drob(y, z2) + drob(y-2, z3);» или

«z1:=drob(x);» теперь будут ошибками.

Задание

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

пользованием процедуры.

Содержание отчёта

цель работы и задание (с исходным выражением);

блок-схемы алгоритмов вычисления значения типового выра-

жения и основного вычисления;

тексты модулей проектов

пример работы приложений с указанием компонентов формы;

выводы по работе.

Контрольные вопросы

1.С какой целью в программировании используют подпрограммы?

2.Что такое подпрограмма, какова их классификация?

3.В чём отличие процедуры от функции, в т.ч. в их структуре?

46

4.В чём отличие параметра-значения от параметра-переменной?

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

а вызов процедуры нельзя, только отдельным оператором. Почему?

6.В каких случаях пользовательскую подпрограмму целесообразнее оформить как функцию, в каких как процедуру?

7.В представленных описаниях подпрограмм и фрагментах вызыва-

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

Пользовательская подпрограмма

Блок, вызывающий подпрограмму

 

 

Procedure pr(m,n:byte; var k:byte);

var x, y, s, t:byte; z:real;

begin

begin

 

k:=m+n;

x:=2; y:=3; z:=2.5;

end;

pr(x, y);

pr(x, y+1, 2*s);

 

pr(x, z, s);

pr(x, sqr(y), s);

 

pr(2*x, y, s);

t:= 5+pr(x, y, s);

 

какие вызовы неверны и почему?

 

 

Procedure pr2(m, n, k:byte);

var x, y, s1, s2:byte;

begin

begin

 

k:=m+n;

x:=2; y:=3; s1:=0; s2:=0;

end;

pr(x, y, s1); pr2(x, y, s2);

 

каковы значения s1 и s2 теперь?

 

 

 

Function fun(u,v:byte):integer;

var x, y:byte;

w1, w2:integer;

begin

begin

 

fun:=u v;

x:=2; y:=3;

 

end;

w1:=fun(x, y);

можно ли изменить тип integer

w2:=fun(y, x);

на тип byte в описании функции?

каковы значения w1 и w2?

 

 

 

47

Лабораторная работа № 4

МОДУЛИ

Цель работы приобретение умений разработки модулей. Разработанные пользовательские подпрограммы предыдущей

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

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

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

48

Структура модуля

В общем случае модуль имеет следующую структуру

UNIT имя_модуля //заголовок

INTERFACE //раздел описаний («видимая часть») uses //список модулей, подключаемых к данному const //объявление глобальных констант

type //объявление глобальных типов

var //объявление глобальных переменных procedure //заголовки глобальных процедур function //заголовки глобальных функций

IMPLEMENTATION // раздел реализации (невидимая часть)

uses //список модулей, используемых только внутри данного модуля const //объявление локальных для данного модуля констант

type //объявление локальных для данного модуля типов

var //объявление локальных для данного модуля переменных procedure //полное описание локальных процедур

function //полное описание локальных функций procedure //полное описание глобальных процедур function //полное описание глобальных функций

INITIALIZATION //раздел инициализации

FINALIZATION //заключительный раздел

END. //конец модуля

Первая строка модуля его заголовок. Он начинается со слу-

жебного слова unit, за которым указывается имя модуля. Далее сле-

дует раздел описаний, начинающийся со служебного слова interface.

Всё, что описано в разделе описаний, будет доступно подключившим к себе этот модуль программным единицам (проект, другой модуль,

49

подпрограмма). Константы, типы, переменные здесь описываются обычным образом, а для подпрограмм выносятся только заголовки.

Со служебного слова implementation начинается раздел реали-

зации. Здесь приводят описание констант, типов, переменных и под-

программ, которые являются локальными для данного модуля. Т.е.

могут использоваться только внутри модуля, они «не видны» извне. И

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

свою очередь, могут использовать локальные подпрограммы, кон-

станты, переменные, типы.

В разделе инициализации помещаются команды, выполняемые до начала работы программной единицы, подключившей к себе дан-

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

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

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

констант. Заканчивается модуль end.

Отметим, что модуль описания формы (модуль проекта) подчи-

нён такой же структуре, просто он имеет значительный по объёму ко-

да раздел описаний, т.к. там описываются сложные объектные типы.

Создание и подключение модуля

Для создания собственного модуля можно запустить Delphi, за-

крыть форму и окно модуля, не сохраняя его. Затем выбрать команду

50