- •Windows -приложение
- •Среда программирования
- •Встроенный отладчик
- •Использование графики
- •Графические данные и палитра
- •Сохранение проекта
- •Структура приложения
- •Структура модуля
- •Простые типы
- •Символьные типы
- •Логические типы
- •Тип перечень
- •Составной оператор
- •Оператор if
- •Оператор цикла for
- •Оператор цикла while
- •Оператор цикла repeat
- •Пример приложения 6
- •Пример приложения 7
- •Статические массивы
- •Динамические массивы
- •Оператор with
- •Идентичность типов
- •Совместимость типов
- •Преобразование типов
- •Операторы обработки исключительных ситуаций
- •Рекурсия
- •Процедура exit
- •Директивы подпрограммы
- •Класс как объектный тип
- •Наследование
- •Операции is и as
- •Типы ссылки на класс
- •Типизированные файлы
- •Файлы без типа
- •Пример приложения 17
- •Компонент tmainmenii
- •Двунаправленные списки
- •Потоки данных
- •Пример приложения 22
- •Интерфейс drag and drop
- •Пример приложения 24
- •С файлами
- •Пример приложения 26
- •Программные потоки
- •Приоритеты потоков
- •Класс tthread
- •Проблемы синхронизации потоков
Процедура 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)
...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.
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) - для нахождения суммы элементов множества. Расположим эти подпрограммы в секции Implementation модуля как необходимые для решения внутренних задач.
Выберем тип 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. Эти секции задают разную степень видимости при обращениях из других модулей. Внутри модуля, являющегося владельцем класса, доступны все элементы из различных секций.