Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебник Емельянов.doc
Скачиваний:
12
Добавлен:
03.11.2018
Размер:
3.25 Mб
Скачать

Процедура exit

Эта процедура используется, если необходимо досрочно выйти из под­программы. Например, задан массив вещественных чисел, найти первый отрицательный элемент в этом массиве:

Function Minus(const M : Array of Real): Real;

Var I: Byte; Begin

Minus := 0.0; For I:=0 to High(M) do If M[i]<0 then begin Minus := M[i]; Exit; End; End;.

■ .

Директивы подпрограммы

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

СОГЛАШЕНИЯ ПО ПЕРЕДАЧЕ ДАННЫХ

Существуют четыре варианта передачи данных в подпрограммах:

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

  • Pascal, отличающийся от предыдущего режима в основном тем, что ре­ гистры процессора для передачи параметров не используются;

  • Cdecl - режим, позволяющий использовать DLL, написанные на C++ или на других языках;

  • Stdcall - режим, позволяющий обращаться к подпрограммам Windows.

ДИРЕКТИВА FORWARD

При объявлении подпрограмм существует правило, запрещающее ис­пользовать подпрограмму, если она не объявлена и не определена. Если подпрограмма Б вызывает А, а А вызывает Б (циклический вызов), то в этом случае, чтобы не нарушать правило, указанное выше, первую из подпро-

грамм объявляют с директивой Forward и после этого определяют сначала вторую, а потом первую подпрограммы. Например,

Integer); Forward; у : Single);

procedure First(var x procedure Second(var x,

Integer)

...First(x) ;... end; procedure First(Var x :

...Second(zl,z2) ;... end;.

ДИРЕКТИВА EXTERNAL

Эта директива используется в двух случаях: для вызова подпрограмм из DLL или для вызова подпрограмм, написанных на ассемблере и существую­щих в виде отдельного объектного файла. В первом случае записывается ключевое слово с дополнительной информацией, например, Procedure First; external 'MyDll.dll' ;. Во втором случае имя DLL опускается.

ДИРЕКТИВА ASSEMBLER

С помощью этой директивы можно подключать к программам подпро­граммы, полностью написанные на языке Assembler, например,

Function Max(x,y:

integer):Integer; Assembler;

ASM

{Вместо begin}

Mov

еах, х

Сшр

еах, у

{сравнить}

Jge

81

{перейти}

Mov еах, у 91: end;.

Эта подпрограмма ищет максимальное из двух чисел.

ПЕРЕГРУЖЕННЫЕ ПОДПРОГРАММЫ

Часто возникает потребность выполнять одни и те же действия над раз­ными типами данных. Например, рассмотрим встроенную функцию Abs(X) -вычисление модуля числа. Если аргумент Х- число целое, то результат воз­вращается, как целое число, если аргумент — число вещественное, то и ре­зультат будет числом вещественным. При создании подпрограмм, которые в зависимости от типа аргумента возвращают разный тип результата, исполь­зуется механизм перегрузки подпрограмм. Синтаксически перегруженные подпрограммы объявляются с директивой overload и, кроме того, подпро­грамма определяется отдельно для каждого типа аргумента. Например,

106

107

Форма с вариантом решения представлена на рис. 33.

Procedure ShowResult(I:integer); overload; Begin

ShowMessage(IntToStr(I)); End;

Procedure ShowResult(R:real); overload; Begin

ShowMessage(FloatToStr(R)) ; End;

Procedure ShowResult{S:string); overload; Begin

ShowMessage (S) ; End;.

При вызове данной подпрограммы - ShowResult (2) ;, ShowResult (5. 7) ;, ShowResult ('Перегруженная процедура') -скла­дывается впечатление, что работает одна и та же процедура.

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

ПРИМЕР ПРИЛОЖЕНИЯ 13

Пусть заданы два числа kl и к2. С помощью генератора случайных чи­сел, распределенных равномерно, создаются два множества такие, что пер­вое содержит число kl, а второе - к2. Если к2 намного больше kl, то можно предположить, что в большинстве случаев сумма элементов второго множе­ства больше суммы элементов первого множества. Проверить сформулиро­ванное утверждение на трех парах множеств. Количество элементов во мно­жестве равно к. Диапазон чисел от 0 до £=100.

В данном случае требуется сгенерировать 6 множеств. Обозначим их £Оь S(a, S\u S]2, S21, ^22- Для записи элементов этих множеств воспользуемся ком­понентом TPageControl, который находится на странице Win32 палитры компонентов. Компонент TpageControl используется для реализации много­страничных диалоговых панелей. Каждая страница представляет собой объ­ект типа TTabSheet (лист с этикеткой). Название страницы задается свойст­вом Caption. Текущая страница доступна через свойство ActivePage. Стра­ницы нумеруются начиная с нуля. При переключении страниц возникает событие OnChange. На каждой странице могут быть расположены любые компоненты: TEdit, TMemo, TImage и т.д. Заголовки страниц могут отобра­жаться или в одну строку со скроллингом, или в несколько строк. В послед­нем случае свойству MultiLine необходимо присвоить значение true.

Для нашего примера были выбраны три страницы (с помощью правой клавиши мыши выбирается NewPage). На каждой странице расположено по два компонента типа ТМето: соответственно от Memol до Метоб.

Рис. 33

Для ввода чисел к, kl, к2 использовался компонент TSpinEdit (страница Samples). Ввод с помощью этого элемента ограничивается только целыми числами. Их можно вводить или непосредственно, или с помощью встроен­ных стрелок, последовательно уменьшая или увеличивая число. Само число содержится в свойстве Value.

В данном случае для решения примера понадобятся дополнительные подпрограммы. Создадим одну подпрограмму для генерации (пример 12) множеств (назовем ее CreateMn), другую (SumMn) - для нахождения сум­мы элементов множества. Расположим эти подпрограммы в секции Imple­mentation модуля как необходимые для решения внутренних задач.

Выберем тип Procedure для первой подпрограммы: она должна возвра­щать элементы множества. Вторая подпрограмма должна возвращать значе­ние суммы (одно число), поэтому ее оформим в виде Function. Программа приведена ниже.

unit priml3; interface

uses Windows, Messages, SysUtils, Classes, Graphics,Controls, Forms, Dialogs, StdCtrls, Buttons, ComCtrls, Spin, ExtCtrls; type

TForm1 = class(TForm) Panel1: TPanel; Panel2: TPanel;

108

109

SpinEdit1:TSpinEdit; SpinEdit2:TSpinEdit; Label2: TLabel;

Label3: TLabel;

SpinEdit3:TSpinEdit; Label4: TLabel; BitBtn2:TBitBtn; Button2:TButton; PageControll: TPageControl; TabSheetl: TTabSheet; TabSheet2: TTabSheet; TabSheet3: TTabSheet;

Memo 1: TMemo ;

Memo2: TMemo;

МеmоЗ: TMemo;

Memo4: TMemo;

Memo5: TMemo;

Memo 6: TMemo;

procedure PageControllChange(Sender: TObject) procedure Button2Click(Sender: TObject);

end;

const L=100; type mn=set of 0..L;

var Form1: TForm1;

s:array [0..2,1..2] of nm;

ss:mn = [] ;

k,kl,k2:byte;

implementation

{$R *.DFM}

procedure CreateMn(n:byte);

var i,j,z:byte; begin

if n=l then ss:=[kl] else ss:=[k2]; for j :-0 to 2 do repeat

s[j,n] : = [];

for i:=l to к do

while true do begin z:=randora(L+l); if z in s[j,n] then continue; include(s[j,n],z);

break; end;

until 5[j,n]>=ss;

end;

function SumMn{const np,n:byte):word;

var i:byte; begin

result:=0;

for i:=l to L do

if i in s[np,n] then result:=result+i,

end;

procedure TForm1.Button2Click(Sender: TQbject); var kl2:integer;

const str='He выполняется условие '; begin

randomize;

kl2:=SpinEdit1.Value; if (kl2>L) or (kl2<0) then begin ShowMessage{str+'0<=kl<L'); SpinEdit1.SetFocus; exit; end;

kl:-kl2;

kl2:=SpinEdit2.Value; if (kl2>L) or (kl2<0) then begin ShowMessage(str+'0<=k2<L'); SpinEdit2,SetFocus;

exit;

end;

k2:=kl2;

kl2:=SpinEdit3.Value;

if kl2<=0 then begin

ShowMessage fstr+'k>0'); SpinEdit3,SetFocus;

exit;

end; k:~kl2; CreateMn(1); CreateMn(2); end;

procedure TForm1.PageControllChange(Sender: TObj ect); var i:byte;

strl,str2:string; CurrentTab:TTabSheet; CurrentMemol:TMemo; CurrentMemo2:TMemo; begin

strl:=''; str2:='';

CurrentTab:=PageControll.ActivePage; CurrentMeraol:=nil; CurrentMemo2:=nil; case CurrentTab.Pagelndex of 0 :begin

CurrentMemol:=Memol;

110

111

CurrentMemo2:=Memo2; end; 1:begin

CurrentMemol:=Memo3; CurrentMemo2:=Memo4; end; 2:begin

CurrentMemol:=Memo5; CurrentMemo2:=Memo6; end; end;

if (CurrentMeraolonil) and (CurrentMemo2<>nil) then begin CurrentMemol.Lines.clear; CurrentMemo2.Lines.Clear; for i:=0 to L do begin

if i in s[CurrentTab.Pagelndex,1] then

strl:=strl+inttostr(i)+' ';

if i in s CurrentTab.Pagelndex,2] then str2:=str2+inttostr(i)+' ';

if i mod 20-0 then begin

if length(trim(strl))>0 then begin CurrentMemol.Lines.Add(strl); strl:=''; end;

if length(trim(str2))>0 then begin CurrentMemo2.Lines.Add(str2); str2:="';

end;

end;

end;

end;

CurrentMemol.Lines.Add('Суммам'+

inttostr(summn(CurrentTab.Pagelndex,1))); CurrentMemo2.Lines.Add(' Сумма='+

inttostr(summn(CurrentTab.Pagelndex,2) ) ) ; end; end.

В данной программе введены три особые переменные currentTab: TTabSheet; CurrentMemol:TMemo; CurrentMemo2 : TMemo;. Эти пере­менные являются объектами, т.е. порождены от типа класс. В программе показано, что с такими переменными можно работать, как с обычными пе­ременными. Следует рассмотреть вопрос необходимости применения пере­менной ki2.

КЛАССЫ

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

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

ИНКАПСУЛЯЦИЯ.

Класс - основной элемент программирования в Delphi. Как тип, класс имеет ряд особенностей. Первая особенность типа класс заключается в том, что в одном типе объединены данные и код для обработки этих данных. Это свойство класса называется инкапсуляцией. Синтаксически класс подобен типу record, в котором можно выделить следующие элементы:

  • поля служат для записи данных;

  • методы - процедуры и функции для обработки полей;

  • свойства - специальные методы, к которым можно обращаться как к полям.

Рассмотрим синтаксис объявления простейшего класса.

Type TMyClass =class (TObject) Public

AField: AType;

Procedure AMethod(Param: AType};

Function AFunc(Param: AType);AType;

Property AProperty: Atype read AField write AMetnod; End;.

Объявленный выше класс включает одно поле AField какого-либо типа,

два метода AMethod, AFunc И ОДНО СВОЙСТВО AProperty.

Объявление элементов класса делится на секции. В данном случае пока­зана одна секция Public. Кроме Public могут присутствовать секции Рго-

112

113

tected, Published, Private. Эти секции задают разную степень видимости при обращениях из других модулей. Внутри модуля, являющегося владельцем класса, доступны все элементы из различных секций.