Основы языка Delphi

Основы языка Delphi

Форма

Форма

Работа над новым проектом, так в Delphi называется разрабатываемое приложение, начинается с создания стартовой формы. Так на этапе разработки программы называют диалоговые окна.

Стартовая форма создается путем изменения значений свойств формы Form1 и добавления к форме необходимых компонентов (полей ввода и вывода текста, командных кнопок).

Свойства формы (табл. В1) определяют ее внешний вид: размер, положение на экране, текст заголовка, вид рамки.

Для просмотра и изменения значений свойств формы и ее компонентов используется окно Object Inspector. В верхней части окна Object Inspector указано имя объекта, значения свойств которого отображается в данный момент. В левой колонке вкладки Properties (Свойства) перечислены свойства объекта, а в правой — указаны их значения.



В последнее время резко возрос

Предисловие

Delphi — что это?

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

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

Несколько лет назад рядовому программисту оставалось только мечтать о создании собственных программ, работающих в среде Windows, т. к. единственным средством разработки был Borland C++ for Windows, явно ориентированный на профессионалов, обладающих серьезными знаниями и опытом.

Бурное развитие вычислительной техники, потребность в эффективных средствах разработки программного обеспечения привели к появлению систем программирования, ориентированных на так называемую "быструю разработку", среди которых можно выделить Borland Delphi и Microsoft Visual Basic. В основе систем быстрой разработки (RAD-систем, Rapid Application Development — среда быстрой разработки приложений) лежит технология визуального проектирования и событийного программирования, суть которой заключается в том, что среда разработки берет на себя большую часть рутинной работы, оставляя программисту работу по конструированию диалоговых окон и функций обработки событий. Производительность программиста при использовании RAD-систем -фантастическая!

Delphi — это среда быстрой разработки, в которой в качестве языка программирования используется язык Delphi. Язык Delphi — строго типизированный объектно-ориентированный язык, в основе которого лежит хорошо знакомый программистам Object Pascal.

В настоящее время программистам стала доступна очередная версия пакета Delphi - Borland Delphi 7 Studio. Как и предыдущие версии, Borland Delphi 7 Studio позволяет создавать самые различные программы: от простейших однооконных приложений до программ управления распределенными базами. В состав пакета включены разнообразные утилиты, обеспечивающие работу с базами данных, XML-документами, создание справочной системы, решение других задач. Отличительной особенностью седьмой версии является поддержка технологии .NET.

Borland Delphi 7 Studio может работать в среде операционных систем от Windows 98 до Windows XP. Особых требований, по современным меркам, к ресурсам компьютера пакет не предъявляет: процессор должен быть типа Pentium или Celeron с тактовой частотой не ниже 166 МГц (рекомендуется Pentium II 400 МГц), оперативной памяти - 128 Мбайт (рекомендуется 256 Мбайт), достаточное количество свободного дискового пространства (для полной установки версии Enterprise необходимо приблизительно 475 Мбайт).

Об этом диске

В книге, которая посвящена программированию в конкретной среде разработки, необходим баланс между тремя линиями — языком программирования, техникой и технологией программирования (программированием как таковым) и средой разработки. Уже при первом знакомстве со средой разработки, представлении ее возможностей у автора возникает проблема: чтобы описать процесс разработки программы, объяснить, как работает программа, нужно оперировать такими терминами, как объект, событие, свойство, понимание которых на начальном этапе изучения программирования весьма проблематично. Как поступить? Сначала дать описание языка, а затем приступить к описанию среды разработки и процесса программирования в Delphi? Очевидно, что это не лучший вариант. Поэтому при изложении материала принят подход, в основу которого положен принцип соблюдения баланса между языком программирования, методами программирования и средой разработки. В начале книги некоторые понятия, без которых просто невозможно изложение материала, даются на уровне определений.

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

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

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



Во введении кратко описывается процесс

Введение

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



Компиляция

Компиляция

Компиляция — это процесс преобразования исходной программы в исполняемую. Процесс компиляции состоит из двух этапов. На первом этапе выполняется проверка текста программы на отсутствие ошибок, на втором — генерируется исполняемая программа (ехе-файл).

После ввода текста функции обработки события и сохранения проекта можно из меню Project выбрать команду Compile и выполнить компиляцию. Процесс и результат компиляции отражаются в диалоговом окне Compiling (Рисунок В38). В это окно компилятор выводит ошибки (Errors), предупреждений (warnings) и подсказок (Hints). Сами сообщения об ошибках, предупреждения и подсказки отображаются в нижней части окна редактора кода (Рисунок В39).



Компоненты

Компоненты

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

Наиболее часто используемые компоненты находятся на вкладке Standard (Рисунок В16).

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



В1 Процедура обработки

Листинг В1. Процедура обработки события OnClick на кнопке Button1 (Вычислить)

// нажатие кнопки Вычислить

procedure TForm1.ButtonlClick(Sender: TObject);


var

dist : integer; // дистанция, метров

t: real; // время как дробное число

min : integer; // время, минуты
sek : integer; // время, секунды

v: real; // скорость

begin

// получить исходные данные из полей ввода
dist := StrToint(Edit1.Text);
t := StrToFloat(Edit2.Text);


// предварительные преобразования

min := Trunc(t);
// кол-во минут — это целая часть числа t

sek := Trunc(t*100) mod 100;
// кол-во секунд — это дробная часть

// числа t

// вычисление

v := (dist/1000) / ((min*60 + sek)/3600);


// вывод результата

label4.Caption := 'Дистанция: '+ Edit1.Text
+ ' м' + #13 + 'Время: ' + IntToStr(min)
+ ' мин ' + IntToStr(sek) + ' сек ' + #13 +

'Скорость: ' + FloatToStrF(v,ffFixed,4,2) + ' км/час';

end;

Функция Button1click выполняет расчет скорости и выводит результат расчета в поле Label4. Исходные данные вводятся из полей редактирования Editl и Edit2 путем обращения к свойству Text. Свойство Text содержит строку символов, которую во время работы программы введет пользователь. Для правильной работы программы строка должна содержать только цифры. Для преобразования строки в числа в программе используются функции StrToInt и strToFloat. Функция strToInt проверяет символы строки, переданной ей в качестве параметра (Edit1.Text - это содержимое поля Editl), на допустимость и, если все символы верные, возвращает соответствующее число. Это число записывается в переменную dist. Аналогичным образом работает функция strToFioat, которая возвращает дробное число, соответствующее содержимому поля Edit2. Это число записывается в переменную t.

После того как исходные данные будут помещены в переменные dist и t, выполняются подготовительные действия и расчет. Первоначально с использованием функции Trunc, которая "отбрасывает" дробную часть числа, выделяется целая часть переменной t — это количество минут. Значением выражения Trunc(t*100) mod 100 является количество секунд. Вычисляется это выражение так. Сначала число t умножается на 100. Полученное значение передается функции Trunc, которая возвращает целую часть результата умножения t на 100. Полученное таким образом число делится по модулю на 100. Результат деления по модулю — это остаток от деления.

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

Вычисленное значение скорости выводится в поле Label4 путем присваивания значения свойству Caption. Для преобразования чисел в строки используются функции IntToStr И FloatToStr.

В результате нажатия кнопки Завершить программа должна завершить работу. Чтобы это произошло, надо закрыть, убрать с экрана, главное окно программы. Делается это при помощи метода close. Процедура обработки события Onclick для кнопки Завершить приведена в листинге В2.



В2 Процедура обработки

Листинг В2. Процедура обработки события Onclick на кнопке Button2 (Завершить)

// нажатие кнопки Завершить

procedure TForm1.Button2Click(Sender: TObject);


begin

Form1.Close; // закрыть главное окно программы

end;

В4 Модуль программы Скорость бега

Листинг В4. Модуль программы Скорость бега

unit vrun1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls;

type

TForm1 = class(TForm) Edit1: TEdit;
Edit2: TEdit; Label1: TLabel;
Label2: TLabel; Label3: TLabel;
Label4: TLabel;
Button1: TButton;
Button2: TButton;

procedure ButtonlClick(Sender: TObject);

procedure Button2Click(Sender: TObject);


private

{ Private declarations } public

{ Public declarations } end;

var

Form1: TForm1;

implementation

{$R *.dfm}

// нажатие кнопки Вычислить

procedure TForm1.ButtonlClick'(Sender: TObject);


var

dist : integer; // дистанция, метров

t: real; // время как дробное число

min : integer; // время, минуты
sek : integer; // время, секунды

v: real;

// скорость

begin

// получить исходные данные из полей ввода
dist := StrToInt(Edit1.Text);
t := StrToFloat(Edit2.Text);


// предварительные преобразования

min := Trunc(t);
// кол-во минут — это целая часть числа t

sek := Trunc(t*100) mod 100; // кол-во секунд — это дробная часть

// числа t

// вычисление

v := (dist/1000) / ((min*60 + sek)/3600);


// вывод результата

label4.Caption := 'Дистанция: '+ Edit1.Text + ' м' + #13
+ 'Время: ' + IntToStr(min) + ' мин '
+ IntToStr(sek) + ' сек ' + #13 +

'Скорость: ' + FloatToStrF(v,ffFixed,4,2) + км/час';

end;

// нажатие кнопки Завершить

procedure TForm1.Button2Click(Sender: TObject)

begin

Form1.Close;

end;

end.

Начинается модуль словом unit, за которым следует имя модуля. Именно это имя упоминается в списке используемых модулей в инструкции uses главного модуля приложения, текст которого приведен в листинге ВЗ.
Модуль состоит из следующих разделов:
  • интерфейса;
  • реализации;
  • инициализации.

  • Раздел интерфейса (начинается словом interface) сообщает компилятору, какая часть модуля является доступной для других модулей программы. В этом разделе перечислены (после слова uses) библиотечные модули, используемые данным модулем. Также здесь находится сформированное Delphi описание формы, которое следует за словом type.
    Раздел реализации открывается словом implementation и содержит объявления локальных переменных, процедур и функций, поддерживающих работу формы.
    Начинается раздел реализации директивой {$R *.DFM}, указывающей компилятору, что в процессе генерации выполняемого файла надо использовать описание формы. Описание формы находится в файле с расширением dfm, имя которого совпадает с именем модуля. Файл описания формы генерируется средой Delphi на основе внешнего вида формы.
    За директивой ($R *.DFM} следуют процедуры обработки событий для формы и ее компонентов. Сюда же программист может поместить другие процедуры и функции.
    Раздел инициализации позволяет выполнить инициализацию переменных модуля. Инструкции раздела инициализации располагаются после раздела реализации (описания всех процедур и функций) между begin и end. Если раздел инициализации не содержит инструкций (как в приведенном примере), то слово begin не указывается.
    Следует отметить, что значительное количество инструкций модуля формирует Delphi. Например, Delphi, анализируя действия программиста по созданию формы, генерирует описание класса формы (после слова type). В приведенном примере инструкции, набранные программистом, выделены фоном. Очевидно, что Delphi выполнила значительную часть работы по составлению текста программы.

    В5 Модуль программы Скорость

    Листинг В5. Модуль программы Скорость бега после внесения изменений unit vrun1;

    interface

    uses

    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

    Dialogs, StdCtrls;

    type

    TForml = class(TForm) Editl: TEdit;
    Edit2: TEdit; Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Buttonl: TButton;
    Button2: TButton;

    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

    procedure EditlKeyPress(Sender: TObject; var Key: Char);


    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    {$R *.dfm)

    // нажатие кнопки Вычислить

    procedure TForm1.ButtonlClick(Sender: TObject);


    var

    dist : integer; // дистанция, метров

    t: real; // время как дробное число

    min : integer; // время, минуты
    sek : integer; // время, секунды

    v: real; // скорость
    begin

    // получить исходные данные из полей ввода
    dist := StrToInt(Editl.Text);
    t := StrToFloat(Edit2.Text);


    // предварительные преобразования

    min := Trunc(t);
    // кол-во минут — это целая часть числа t

    sek := Trunc(t*100) mod 100; // кол-во секунд — это дробная часть

    // числа t

    // вычисление

    v := (dist/1000) / ( (min*60 + sek)/3600);


    // вывод результата

    label4.Caption := 'Дистанция: '+ Editl.Text +
    ' м' + #13 + 'Время: ' + IntToStr(min) +
    ' мин ' + IntToStr(sek) + ' сек ' + #13 +

    'Скорость: ' + FloatToStrF(v,ffFixed,4,2) + ' км/час';

    end;

    // нажатие кнопки Завершить

    procedure TForml.Button2Click(Sender: TObject);


    begin

    Form1.Close; end;

    // нажатие клавиши в поле Дистанция

    procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);


    begin

    // Key — символ, соответствующий нажатой клавише.

    // Если символ недопустимый, то процедура заменяет его

    // на символ с кодом 0. В результате этого символ в поле

    // редактирования не появляется, и у пользователя создается

    // впечатление, что программа не реагирует на нажатие некоторых

    // клавиш.

    case Key of

    '0'..'9': ; // цифра

    #8 : ; // клавиша


    #13 : Edit2.SetFocus ; // клавиша

    // остальные символы — запрещены
    else Key :=Chr(0);
    // символ не отображать
    end;
    end;

    end.

    После внесения изменений проект следует сохранить. Для этого нужно из меню File выбрать команду Save all.

    ВЗ Главный модуль приложения

    Листинг ВЗ. Главный модуль приложения Скорость бега program vrun;

    uses

    Forms,vrun1 in 'vrunl.pas' {Form1};

    {$R *.res}

    begin

    Application.Initialize;
    Application.CreateForm(TForm1, Form1);

    Application.Run;
    end.

    Начинается главный модуль словом program, за которым следует имя программы, совпадающее с именем проекта. Имя проекта задается в момент сохранения проекта, и оно определяет имя создаваемого компилятором исполняемого файла программы. Далее за словом uses следуют имена используемых модулей: библиотечного модуля Forms и модуля формы vrunl.pas.

    Строка {$R *.RES}, которая похожа на комментарий, — это директива компилятору подключить файл ресурсов. Файл ресурсов содержит ресурсы приложения: пиктограммы, курсоры, битовые образы и др. Звездочка показывает, что имя файла ресурсов такое же, как и у файла проекта, но с расширением res.

    Файл ресурсов не "является текстовым файлом, поэтому просмотреть его с помощью редактора текста нельзя. Для работы с файлами ресурсов используют специальные программы, например, Resource Workshop. Можно также применять входящую в состав Delphi утилиту Image Editor, доступ к которой можно получить выбором из меню Tools команды Image Editor.

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

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

    В листинге В4 приведен текст модуля программы вычисления скорости бега.



    Начало работы

    Начало работы

    Запускается Delphi обычным образом, т. е. выбором из меню Borland Delphi 7 команды Delphi 7 (Рисунок В6).



    Навигатор кода

    Навигатор кода

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

    Окно навигатора кода можно закрыть обычным образом. Если окно навигатора кода не доступно, то для того, чтобы оно появилось на экране, нужно из меню View выбрать команду Code Explorer.

    Окончательная настройка приложения

    Окончательная настройка приложения

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

    Настройка приложения выполняется на вкладке Application диалогового окна Project Options (Рисунок В44), которое появляется в результате выбора из меню Project команды Options.

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



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

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

    Во время работы приложения могут возникать ошибки, которые называются ошибками времени выполнения (run-time errors) или исключениями (exceptions). В большинстве случаев причинами исключений являются неверные исходные данные. Например, если во время работы программы вычисления скорости бега в поле Время ввести 3.20, т.е. для отделения дробной части числа от целой использовать точку, то в результате нажатия кнопки Вычислить на экране появится окно с сообщением об ошибке (Рисунок В42).



    Ошибки

    Ошибки

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

    Чтобы перейти к фрагменту кода, который содержит ошибку, надо установить курсор в строку с сообщением об ошибке и из контекстного меню (Рисунок В40) выбрать команду Edit source.

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



    Первый проект

    Первый проект

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



    is declared but never used

    Предупреждение

    Вероятная причина

    Variable... is declared but never used in ...

    Variable . . . might not have been initialized. (Вероятно, используется не инициализированная переменная)

    Переменная не используется

    В программе нет инструкции, которая присваивает переменной начальное значение



    Предупреждения и подсказки

    Предупреждения и подсказки

    При обнаружении в программе неточностей, которые не являются ошибками, компилятор выводит подсказки (Hints) и предупреждения (warnings).

    Например, наиболее часто выводимой подсказкой является сообщение об объявленной, но не используемой переменной:

    Variable ... is declared but never used in ... Действительно, зачем объявлять переменную и не использовать ее?

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



    Редактор кода

    Редактор кода

    Редактор кода выделяет ключевые слова языка программирования (procedure, var, begin, end, if и др.) полужирным шрифтом, что делает текст программы более выразительным и облегчает восприятие структуры программы.

    Помимо ключевых слов редактор кода выделяет курсивом комментарии.

    В процессе разработки программы часто возникает необходимость переключения между окном редактора кода и окном формы. Сделать это можно при помощи командной кнопки Toglle Form/Unit, находящейся на панели инструментов View (Рисунок В28), или нажав клавишу . На этой же панели инструментов находятся командные кнопки View Unit и View Form, используя которые можно выбрать нужный модуль или форму в случае, если проект состоит из нескольких модулей или форм.



    Рисунок В1. Начало установки Delphi

    Рисунок В1. Начало установки Delphi 7

    Рисунок В1. Начало установки Delphi

    Для того чтобы активизировать процесс установки Delphi, следует щелкнуть на строке Delphi 7. Процесс установки Delphi обычный. После ввода серийного номера (Serial Number) и ключа (Authorization Key) на экране сначала появляется окно с лицензионным соглашением, затем — окно Setup Type (Рисунок В2), в котором можно выбрать один из возможных вариантов установки: Typical (Обычный), Compact (Компактный) или Custom (Выборочный, определяемый пользователем).

    Обычный вариант предполагает, что с установочного CD-ROM на жесткий диск компьютера будут скопированы все компоненты Delphi. Обычный вариант установки требует наибольшего свободного места на жестком диске компьютера, порядка 475 Мбайт (для комплекта Enterprise). И если на жестком диске компьютера достаточно свободного места, лучше выбрать этот вариант.

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

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



    В10 Окно редактора кода

    Рисунок В10. Окно редактора кода

    В10 Окно редактора кода

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

    В11 Окно программы вычисления скорости бега

    Рисунок В11. Окно программы вычисления скорости бега

    В11 Окно программы вычисления скорости бега

    Для начала работы над новой программой запустите Delphi. Если вы уже работаете в среде разработки и у вас загружен другой проект, выберите в меню File (Файл) команду New | Application (Создать | Приложение).


    В12 Установка значения свойства путем ввода значения

    Рисунок В12. Установка значения свойства путем ввода значения

    В12 Установка значения свойства путем ввода значения

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

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

    Некоторые свойства являются сложными, т. е. их значение определяется совокупностью значений других (уточняющих) свойств. Перед именами сложных свойств стоит значок "+", при щелчке на котором раскрывается список уточняющих свойств (Рисунок В14). Например, свойство BorderIcons определяет, какие кнопки управления окном будут доступны во время работы программы. Так, если свойству biMaximize присвоить значение False, то во время работы программы кнопки Развернуть в заголовке окна не будет.



    В13 Установка значения

    Рисунок В13. Установка значения свойства путем выбора из списка


    В13 Установка значения





    В14 Раскрытый список вложенных

    Рисунок В14. Раскрытый список вложенных свойств сложного свойства BorderIcons

    В14 Раскрытый список вложенных

    Рядом со значениями некоторых свойств отображается командная кнопка с тремя точками. Это значит, что для задания значения свойства можно воспользоваться дополнительным диалоговым окном. Например, значение сложного свойства Font можно задать путем непосредственного ввода значений уточняющих свойств, а можно воспользоваться стандартным диалоговым окном выбора шрифта.

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



    В15 Так выглядит форма

    Рисунок В15. Так выглядит форма после установки значений свойств


    В15 Так выглядит форма




    В16 Вкладка Standard содержит

    Рисунок В16. Вкладка Standard содержит наиболее часто используемые компоненты

    В16 Вкладка Standard содержит

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

    Каждому компоненту Delphi присваивает имя, которое состоит из названия компонента и его порядкового номера. Например, если к форме добавить два компонента Edit, то их имена будут Edit1 и Edit2. Программист путем изменения значения свойства Name может изменить имя компонента. В простых программах имена компонентов, как правило, не изменяют.

    На Рисунок В17 приведен вид формы после добавления двух компонентов Edit полей редактирования, предназначенных для ввода исходных данных. Один из компонентов выделен. Свойства выделенного компонента отображаются в окне Object Inspector. Чтобы увидеть свойства другого компонента, надо щелкнуть левой кнопкой мыши на изображении нужного компонента. Можно также выбрать имя компонента в окне Object TreeView или из находящегося в верхней части окна Object Inspector раскрывающегося списка объектов.



    В17 Форма после добавления компонентов Edit

    Рисунок В17. Форма после добавления компонентов Edit

    В17 Форма после добавления компонентов Edit

    В табл. В3 перечислены основные свойства компонента Edit — поля ввода-редактирования.



    В18 Отображение текущих

    Рисунок В18. Отображение текущих значений свойств Left и Тор при изменении положения компонента


    В18 Отображение текущих





    В19 Отображение текущих

    Рисунок В19. Отображение текущих значений свойств Height и Width при изменении размера компонента


    В19 Отображение текущих





    В2 В диалоговом окне Setup

    Рисунок В2. В диалоговом окне Setup Type нужно выбрать вариант установки

    В2 В диалоговом окне Setup

    Выбрав вариант установки, нажмите кнопку Next. Если была выбрана частичная (Custom) установка, то открывается диалоговое окно Custom Setup (Рисунок ВЗ), в котором можно выбрать устанавливаемые компоненты, точнее -указать компоненты, которые устанавливать не надо. Чтобы запретить установку компонента, нужно щелкнуть на изображении диска слева от названия компонента и из появившегося меню выбрать команду Do Not Install.



    В20 Выбор компонента

    Рисунок В20. Выбор компонента


    В20 Выбор компонента





    В21 Выбор компонента из

    Рисунок В21. Выбор компонента из списка в окне Object Inspector в окне Object TreeView

    В21 Выбор компонента из

    В табл. В4 приведены значения свойств полей редактирования Editi и Edit2. Компонент Editi предназначен для ввода длины дистанции, Edit2 — для ввода времени.

    Обратите внимание на то, что значением свойства Text обоих компонентов является пустая строка.



    В22 Компонент Label — поле вывода текста

    Рисунок В22. Компонент Label — поле вывода текста

    В22 Компонент Label — поле вывода текста

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

    Свойства компонента Label перечислены в табл. В5.



    В23 Вид формы после добавления полей вывода текста

    Рисунок В23. Вид формы после добавления полей вывода текста


    В23 Вид формы после добавления полей вывода текста





    В24 Командная кнопка — компонент Button

    Рисунок В24. Командная кнопка — компонент Button


    В24 Командная кнопка — компонент Button





    В25 Форма программы Скорость бега

    Рисунок В25. Форма программы Скорость бега

    В25 Форма программы Скорость бега

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

  • событие;
  • процедура обработки события.


  • В26 На вкладке Events

    Рисунок В26. На вкладке Events перечислены события, которые может воспринимать компонент (в данном случае — командная кнопка)

    В26 На вкладке Events

    В левой колонке вкладки Events (Рисунок В26) перечислены имена событий, которые может воспринимать выбранный компонент (объект). Если для события определена (написана) процедура обработки события, то в правой колонке рядом с именем события выводится имя этой процедуры.

    Для того чтобы создать функцию обработки события, нужно сделать двойной щелчок мышью в поле имени процедуры обработки соответствующего события. В результате этого откроется окно редактора кода, в которое будет добавлен шаблон процедуры обработки события, а в окне Object Inspector рядом с именем события появится имя функции его обработки (Рисунок В27).

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



    В27 Шаблон процедуры обработки

    Рисунок В27. Шаблон процедуры обработки события, сгенерированный Delphi

    В27 Шаблон процедуры обработки

    В окне редактора кода между словами begin и end можно печатать инструкции, реализующие функцию обработки события.

    В листинге В1 приведен текст функции обработки события onclick для командной кнопки Вычислить. Обратите внимание на то, как представлена программа. Ее общий вид соответствует тому, как она выглядит в окне редактора кода: ключевые слова выделены полужирным, комментарии — курсивом (выделение выполняет редактор кода). Кроме того, инструкции программы набраны с отступами в соответствии с принятыми в среде программистов правилами хорошего стиля.



    В28 Панель инструментов View

    Рисунок В28. Панель инструментов View


    В28 Панель инструментов View




    В29 Пример подсказки

    Рисунок В29. Пример подсказки


    В29 Пример подсказки





    В30 Редактор кода автоматически

    Рисунок В30. Редактор кода автоматически выводит список свойств и методов объекта (компонента)


    В30 Редактор кода автоматически





    В31 Окно Code Explorer

    Рисунок В31. Окно Code Explorer облегчает навигацию по тексту программы


    В31 Окно Code Explorer




    В32 Список шаблонов кода

    Рисунок В32. Список шаблонов кода отображается в результате нажатия клавиш +


    В32 Список шаблонов кода





    В33 В поля диалогового

    Рисунок В33. В поля диалогового окна надо ввести имя шаблона и его краткое описание


    В33 В поля диалогового





    В34 Пример шаблона кода программиста

    Рисунок В34. Пример шаблона кода программиста


    В34 Пример шаблона кода программиста




    В35 Поиск справочной информации по ключевому слову

    Рисунок В35. Поиск справочной информации по ключевому слову


    В35 Поиск справочной информации по ключевому слову




    В36 Сохранение модуля формы

    Рисунок В36. Сохранение модуля формы


    В36 Сохранение модуля формы





    В37 Сохранение проекта

    Рисунок В37. Сохранение проекта

    В37 Сохранение проекта

    Обратите внимание на то, имена файлов модуля (pas-файл) и проекта (dpr-файл) должны быть разными. Имя генерируемого компилятором исполняемого файла совпадает с именем проекта. Поэтому файлу проекта следует присвоить такое имя, которое, по вашему мнению, должен иметь исполняемый файл программы, а файлу модуля — какое-либо другое имя, например, полученное путем добавления к имени файла проекта порядкового номера модуля.

    Примечание

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

    В38 Результат компиляции

    Рисунок В38. Результат компиляции

    В38 Результат компиляции

    Примечание

    Если во время компиляции окна Compiling на экране нет, то выберите из меню Tools команду Environment options и на вкладке Preferences установите во включенное состояние переключатель Show compiler progress.



    В39 Сообщения компилятора об обнаруженных ошибках

    Рисунок В39. Сообщения компилятора об обнаруженных ошибках


    В39 Сообщения компилятора об обнаруженных ошибках




    В4 Процесс установки завершен

    Рисунок В4. Процесс установки завершен

    В4 Процесс установки завершен

    Теперь можно приступить к работе, запустить Delphi. Однако перед тем, как это сделать, рекомендуется задать рабочий каталог, каталог проектов. Для этого нужно установить указатель мыши на команду запуска Delphi (Пуск | Программы | Borland Delphi 7 | Delphi 7), щелкнуть правой кнопкой мыши, и из появившегося контекстного меню выбрать команду Свойства. Затем в появившемся окне Свойства: Delphi 7 в поле Рабочая папка ввести имя папки, предназначенной для проектов Delphi (Рисунок В5).



    В40 Переход к фрагменту программы содержащему ошибку

    Рисунок В40. Переход к фрагменту программы, содержащему ошибку

    В40 Переход к фрагменту программы содержащему ошибку

    В табл. В10 перечислены наиболее типичные ошибки и соответствующие им сообщения компилятора.



    В41 Запуск программы из среды разработки

    Рисунок В41. Запуск программы из среды разработки


    В41 Запуск программы из среды разработки




    В42 Пример ошибки времени

    Рисунок В42. Пример ошибки времени выполнения (программа запущена из Windows)

    В42 Пример ошибки времени

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

    Если в настройке Windows указано, что разделитель целой и дробной частей числа — запятая (для России это стандартная установка), а пользователь во время работы программы введет в поле редактирования, например, строку 3.20, то при выполнении инструкции

    t = StrToFloat(Edit2.Text)

    возникнет исключение, т. к. при стандартной , для России настройке Windows содержимое поля Edit2 и, следовательно, аргумент функции strToFloat не являются изображением дробного числа.

    Если программа запущена из среды разработки, то при возникновении исключения выполнение программы приостанавливается, и на экране появляется окно с сообщением об ошибке и ее типе. В качестве примера на Рисунок В43 приведено окно с сообщением о том, что введенная пользователем строка не является дробным числом.



    В43 Пример сообщения о

    Рисунок В43. Пример сообщения о возникновении исключения (программа запущена из Delphi)

    В43 Пример сообщения о

    После нажатия кнопки ОК программист может продолжить выполнение программы (для этого надо из меню Run выбрать команду Step Over) или прервать выполнение программы. В последнем случае нужно из меню Run выбрать команду Program Reset.

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

    В листинге В5 приведена версия программы Скорость бега, в которой реализована защита от некоторых некорректных действий пользователя, в частности, программа.позволяет вводить в поле Дистанция (Editl) только цифры.

    В44 Используя вкладку

    Рисунок В44. Используя вкладку Application, можно задать значок и название программы

    В44 Используя вкладку

    Чтобы назначить приложению значок, отличный от стандартного, нужно щелкнуть мышью на кнопке Load Icon. Затем, используя стандартное окно просмотра папок, найти подходящий значок (значки хранятся в файлах с расширением ico).


    В5 Определение папки проектов

    Рисунок В5. Определение папки проектов


    В5 Определение папки проектов




    В6 Запуск Delphi

    Рисунок В6. Запуск Delphi

    В6 Запуск Delphi

    Вид экрана после запуска Delphi несколько необычен (Рисунок В7). Вместо одного окна на экране появляются пять:

  • главное окно — Delphi 7;
  • окно стартовой формы — Form 1;
  • окно редактора свойств объектов — Object Inspector;
  • окно просмотра списка объектов — Object TreeView;
  • окно редактора кода — Unitl.pas.
  • Окно редактора кода почти полностью закрыто окном стартовой формы.



    В7 Вид экрана после запуска Delphi

    Рисунок В7. Вид экрана после запуска Delphi

    В7 Вид экрана после запуска Delphi

    В главном окне (Рисунок В8) находится меню команд, панели инструментов и палитра компонентов.

    Окно стартовой формы (Forml) представляет собой заготовку главного окна разрабатываемого приложения.

    Программное обеспечение принято делить на системное и прикладное. Системное программное обеспечение — это все то, что составляет операционную систему. Остальные программы принято считать прикладными. Для краткости прикладные программы называют приложениями.



    В8 Главное окно

    Рисунок В8. Главное окно

    В8 Главное окно

    Окно Object Inspector (Рисунок В9) — окно редактора свойств объектов предназначено для редактирования значений свойств объектов. В терминологии визуального проектирования объекты — это диалоговые окна и элементы управления (поля ввода и вывода, командные кнопки, переключатели и др.). Свойства объекта — это характеристики, определяющие вид, положение и поведение объекта. Например, свойства width и Height задают размер (ширину и высоту) формы, свойства тор и Left — положение формы на экране, свойство caption — текст заголовка.



    В9 На вкладке Properties

    Рисунок В9. На вкладке Properties перечислены свойства объекта и указаны их значения


    В9 На вкладке Properties





    ВЗ Запрет установки компонента

    Рисунок ВЗ. Запрет установки компонента

    ВЗ Запрет установки компонента

    Если выбран тип установки Typical, то в результате щелчка на кнопке Next открывается окно Destination Folder, в котором указаны каталоги, куда будет установлен пакет Delphi и его компоненты.

    Очередной щелчок на кнопке Next открывает окно Save Installation Database, в котором пользователю предлагается сохранить информацию о процессе установки на жестком диске компьютера, что обеспечит возможность удаления (деинсталляции) Delphi в дальнейшем без использования установочного CD-ROM. На этом процесс подготовки к установке заканчивается. На экране появляется окно Ready To Install the Program, щелчок на кнопке Install в котором активизирует процесс установки.

    По окончании процесса установки на экране появляется окно с информационным сообщением о том, что установка выполнена (Рисунок В4). Щелчок на кнопке Finish закрывает это окно.



    Шаблоны кода

    Шаблоны кода

    В процессе набора текста удобно использовать шаблоны кода (Code Templates). Шаблон кода — это инструкция программы, записанная в общем виде. Например, шаблон для инструкции case выглядит так:

    case of :;

    :;

    else ;

    end;

    Редактор кода предоставляет программисту большой набор шаблонов: объявления массивов, классов, функций, процедур; инструкций выбора (if, case), циклов (for, while). Для некоторых инструкций , например if и while, есть несколько вариантов шаблонов.

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

    Программист может создать свой собственный шаблон кода и использовать его точно так же, как и стандартный. Для того чтобы создать шаблон кода, нужно из меню Tools выбрать команду Editor Options, во вкладке Source Options щелкнуть на кнопке Edit Code Templates, в появившемся диалоговом окне Code Templates щелкнуть на кнопке Add и в появившемся окне Add Code Template (Рисунок ВЗЗ) задать имя шаблона (Shortcut Name) и его краткое описание (Description). Затем, после щелчка на кнопке ОК, в поле Code диалогового окна Code Templates ввести шаблон (Рисунок В34).



    Система подсказок

    Система подсказок

    В процессе набора текста программы редактор кода выводит справочную информацию о параметрах процедур и функций, о свойствах и методах объектов.

    Например, если в окне редактора кода набрать MessageDig (имя функции, которая выводит на экран окно сообщения) и открывающую скобку, то на экране появится окно подсказки, в котором будут перечислены параметры функции MessageDig с указанием их типа (Рисунок В29). Один из параметров выделен полужирным. Так редактор подсказывает программисту, какой параметр он должен вводить. После набора параметра и запятой в окне подсказки будет выделен следующий параметр. И так до тех пор, пока не будут указаны все параметры.

    Для объектов редактор кода выводит список свойств и методов. Как только программист наберет имя объекта (компонента) и точку, так сразу на экране появляется окно подсказки — список свойств и методов этого объекта (Рисунок В30). Перейти к нужному элементу списка можно при помощи клавиш перемещения курсора или набрав на клавиатуре несколько первых букв имени нужного свойства или метода. После того как будет выбран нужный элемент списка и нажата клавиша , выбранное свойство или метод будут вставлены в текст программы.

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



    Событие и процедура обработки события

    Событие и процедура обработки события

    Вид созданной формы подсказывает, как работает приложение. Очевидно, что пользователь должен ввести в поля редактирования исходные данные и щелкнуть мышью на кнопке Вычислить. Щелчок на изображении командной кнопки — это пример того, что в Windows называется событием.

    Событие (Event) — это то, что происходит во время работы программы. В Delphi каждому событию присвоено имя. Например, щелчок кнопкой мыши - это событие OnClick, двойной щелчок мышью событие OnDblClick.

    В табл. В9 приведены некоторые события Windows.



    Сохранение проекта

    Сохранение проекта

    Проект — это набор файлов, используя которые компилятор создает исполняемый файл программы (ЕХЕ-файл). В простейшем случае проект состоит из файла описания проекта (DOF-файл), файла главного модуля (DPR-файл), файла ресурсов (RES-файл), файла описания формы (DFM-файл), файла модуля формы, в котором находятся основной код приложения, в том числе функции обработки событий на компонентах формы (PAS-файл), файл конфигурации (CFG-файл).

    Чтобы сохранить проект, нужно из меню File выбрать команду Save Project As. Если проект еще ни разу не был сохранен, то Delphi сначала предложит сохранить модуль (содержимое окна редактора кода), поэтому на экране появится окно Save Unitl As. В этом окне (Рисунок В36) надо выбрать папку, предназначенную для файлов проекта, и ввести имя модуля. После нажатия кнопки Сохранить, появляется следующее окно (Рисунок В37), в котором необходимо ввести имя файла проекта.



    Сообщение

    Сообщение

    Вероятная причина

    Missing operator or semicolon (Отсутствует оператор или точка с запятой)

    После инструкции не поставлена точка с запятой

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

    Если в программе нет синтаксических ошибок, компилятор создает исполняемый файл программы. Имя исполняемого файла такое же, как и у файла проекта, а расширение — exe. Delphi помещает исполняемый файл в тот же каталог, где находится файл проекта.

    Создание значка для приложения

    Создание значка для приложения

    В состав Delphi входит программа Image Editor (Редактор изображений), при помощи которой программист может создать для своего приложения уникальный значок. Запускается Image Editor выбором соответствующей команды из меню Tools или из Windows — командой Пуск | Программы Borland Delphi 7 | Image Editor.

    Чтобы начать работу по созданию нового значка, нужно из меню File выбрать команду New, а из появившегося списка — опцию Icon File.

    После выбора типа создаваемого файла открывается окно Icon Properties, в котором необходимо выбрать характеристики создаваемого значка: size (Размер) — 32x32 (стандартный размер значков Windows) и Colors (Палитра) — 16 цветов. В результате нажатия кнопки ОК открывается окно Icon1.ico, в котором можно, используя стандартные инструменты и палитру, нарисовать нужный значок.

    Процесс рисования в Image Editor практически ничем не отличается от процесса создания картинки в обычном графическом редакторе, например, в Microsoft Paint. Однако есть одна тонкость. Первоначально поле изображения закрашено "прозрачным" (transparent) цветом. Если значок нарисовать на этом фоне, то при его выводе части поля изображения, закрашенные "прозрачным" цветом, примут цвет фона, на котором будет находиться значок.

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

    Кроме "прозрачного" цвета, в палитре есть "инверсный" цвет. Нарисованные этим цветом части рисунка при выводе на экран окрашиваются инверсным цветом относительно цвета фона.

    Сохраняется созданный значок обычным образом, т. е. выбором из меню File команды Save.

    Справочная система

    Справочная система

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

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



    Структура проекта

    Структура проекта

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

    Главный модуль представляет собой файл с расширением dpr. Для того чтобы увидеть текст главного модуля приложения, нужно из меню Project выбрать команду View Source.

    В листинге ВЗ приведен текст главного модуля программы вычисления скорости бега.



    Свойство

    Свойство

    Описание

    Name

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

    Caption

    Текст заголовка

    Width

    Ширина формы

    Height

    Высота формы

    Top

    Расстояние от верхней границы формы до верхней границы экрана

    Left

    Расстояние от левой границы формы до левой границы экрана

    BorderStyle

    Вид границы. Граница может быть обычной (bsSizeable), тонкой (bs Single) или отсутствовать (bsNone). Если у окна обычная граница, то во время работы программы пользователь может при помощи мыши изменить размер окна. Изменить размер окна с тонкой границей нельзя. Если граница отсутствует, то на экран во время работы программы будет выведено окно без заголовка. Положение и размер такого окна-во время работы программы изменить нельзя

    Свойство

    Описание

    Borderlcons

    Icon
    Color

    Font

    Кнопки управления окном. Значение свойства определяет, какие кнопки управления окном будут доступны пользователю во время работы программы. Значение свойства задается путем присвоения значений уточняющим свойствам biSystemMenu, biMinimaze, biMaximaze И biHelp. Свойство biSystemMenu определяет доступность кнопки Свернуть и кнопки системного меню, biMinimaze— кнопки Свернуть, biMaximaze— кнопки Развернуть, biHelp — кнопки вывода справочной информации

    Значок в заголовке диалогового окна, обозначающий кнопку вывода системного меню

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

    Шрифт. Шрифт, используемый "по умолчанию" компонентами, находящимися на поверхности формы. Изменение свойства Font формы приводит к автоматическому изменению свойства Font компонента, располагающегося на поверхности формы. То есть компоненты наследуют свойство Font от формы (имеется возможность запретить наследование)

    При создании формы в первую очередь следует изменить значение свойства caption (Заголовок). В нашем примере надо заменить текст Form1 на "скорость бега". Чтобы это сделать, нужно в окне Object Inspector щелкнуть мышью на строке Caption, в результате чего будет выделено текущее значение свойства, в строке появится курсор, и можно будет ввести текст "скорость бега" (Рисунок В12).

    Аналогичным образом можно установить значения свойств Height и width, которые определяют высоту и ширину формы. Размер формы и ее положение на экране, а также размер других элементов управления и их положение на поверхности формы задают в пикселах, т. е. точках экрана. Свойствам Height и width надо присвоить значения 250 и 330 соответственно.

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



    В1 Свойства формы (объекта mform)

    Таблица В1. Свойства формы (объекта mform)



    В10 Сообщения компилятора об ошибках

    Таблица В10. Сообщения компилятора об ошибках



    В11 Предупреждения компилятора

    Таблица В11. Предупреждения компилятора



    В2 Значения свойств стартовой формы

    Таблица В2. Значения свойств стартовой формы

    Свойство

    Значение

    Caption

    Скорость бега

    Height

    250

    Width

    330

    BorderStyle

    bsSingle

    Свойство

    Значение

    BorderIcons . biMinimize

    False

    BorderIcons . biMaximize

    False

    Font. Size

    10

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



    В4 Значения свойств компонентов Edit

    Таблица В4. Значения свойств компонентов Edit

    Свойство

    Компонент

    Edit1

    Edit2

    Text





    Тор

    56

    88

    Left

    128

    128

    Height

    21

    21

    Width

    121

    121

    Помимо полей редактирования в окне программы должна находиться краткая информация о программе и назначении полей ввода. Для вывода текста в форму используют поля вывода текста. Поле вывода текста (поле статического текста) — это компонент Label. Значок компонента Label находится на вкладке Standard (Рисунок В22). Добавляется компонент Label в форму точно так же, как и поле редактирования.



    В5 Свойства компонента Label (поле вывода текста)

    Таблица В5. Свойства компонента Label (поле вывода текста)

    Свойство

    Описание

    Name

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

    Caption

    Отображаемый текст

    Font

    Шрифт, используемый для отображения текста

    ParentFont

    Признак наследования компонентом характеристик шрифта формы, на которой находится компонент. Если значение свойства равно True, текст выводится шрифтом, установленным для формы

    AutoSize

    Признак того, что размер поля определяется его содержимым

    Left

    Расстояние от левой границы поля вывода до левой границы формы

    Top

    Расстояние от верхней границы поля вывода до верхней границы формы

    Height

    Высота поля вывода

    Width

    Ширина поля вывода

    Wordwrap

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

    Следует обратить внимание на свойства Autosize и Wordwrap. Эти свойства нужно использовать, если поле вывода должно содержать несколько строк текста. После добавления к форме компонента Label значение свойства Autosize равно True, т. е. размер поля определяется автоматически в процессе изменения значения свойства caption. Если вы хотите, чтобы находящийся в поле вывода текст занимал несколько строк, то надо сразу после добавления к форме компонента Label присвоить свойству Autosize значение False, свойству wordwrap — значение True. Затем изменением значений свойств width и Height нужно задать требуемый размер поля. Только после этого можно ввести в свойство caption текст, который должен быть выведен в поле.

    После добавления полей вывода текста (четырех компонентов Label) и установки значений их свойств в соответствии с табл. В6 форма программы принимает вид, приведенный на Рисунок В23.

    Обратите внимание, что значение свойства caption вводится как одна строка. Расположение текста внутри поля вывода определяется размером поля, значением свойств Autosize и wordwrap, а также зависит от характеристик используемого для вывода текста шрифта.



    В6 Значения свойств компонентов

    Таблица В6. Значения свойств компонентов Label1, Label2, Label3 И Label4

    Компонент

    Свойство

    Значение

    Labell













    AutoSize

    False

    Wordwrap

    True

    Caption

    Программа вычислит скорость, с которой спортсмен пробежал дистанцию

    Top

    8

    Left

    8

    Height

    33

    Width

    209

    Label2





    Top

    56

    Left

    8

    Caption

    Дистанция (метров)

    Label3





    Top

    88

    Left

    8

    Caption

    Время (минуты, секунды)

    Label4





    AutoSize

    False

    Wordwrap

    True

    Top

    120

    Компонент

    Свойство

    Значение

    Label 4





    Left

    8

    Height

    41

    Width

    273

    Последнее, что надо сделать на этапе создания формы — добавить в форму две командные кнопки: Вычислить и Завершить. Назначение этих кнопок очевидно.

    Командная кнопка, компонент Button, добавляется в форму точно так же, как и другие компоненты. Значок компонента Button находится на вкладке Standard (Рисунок В24). Свойства компонента приведены в табл. В7.



    В7 Свойства компонента Button (командная кнопка)

    Таблица В7. Свойства компонента Button (командная кнопка)

    Свойство

    Описание

    Name

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

    Caption

    Текст на кнопке

    Enabled

    Признак доступности кнопки. Кнопка доступна, если значение свойства равно True, и недоступна, если значение свойства равно False

    Left

    Расстояние от левой границы кнопки до левой границы формы

    Top

    Расстояние от верхней границы кнопки до верхней границы формы

    Height

    Высота кнопки

    Width

    Ширина кнопки

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



    Таблица В8. Значения свойств компонентов Button1 и Button2

    Свойство

    Компонент

    Button1

    Button2

    Caption



    В9 События

    Таблица В9. События

    Событие

    Происходит

    OnClick

    При щелчке кнопкой мыши

    OnDblClick

    При двойном щелчке кнопкой мыши

    OnMouseDown

    При нажатии кнопки мыши

    OnMouseUp

    При отпускании кнопки мыши

    OnMouseMove

    При перемещении мыши

    OnKeyPress

    При нажатии клавиши клавиатуры

    OnKeyDown

    При нажатии клавиши клавиатуры. События OnKeyDown и OnKeyPress — это чередующиеся, повторяющиеся события, которые происходят до тех пор, пока не будет отпущена удерживаемая клавиша (в этот момент происходит событие OnKeyUp)

    OnKeyUp

    При отпускании нажатой клавиши клавиатуры

    OnCreate

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

    OnPaint

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

    OnEnter

    При получении элементом управления фокуса

    OnExit

    При потере элементом управления фокуса

    Реакцией на событие должно быть какое-либо действие. В Delphi реакция на событие реализуется как процедура обработки события. Таким образом, для того чтобы программа выполняла некоторую работу в ответ на действия пользователя, программист должен написать процедуру обработки соответствующего события. Следует обратить внимание на то, что значительную часть обработки событий берет на себя компонент. Поэтому программист должен разрабатывать процедуру обработки события только в том случае, если реакция на событие отличается от стандартной или не определена. Например, если по условию задачи ограничений на символы, вводимые в поле Edit, нет, то процедуру обработки события OnKeyPress писать не надо, т. к. во время работы программы будет использована стандартная (скрытая от программиста) процедура обработки этого события.

    Методику создания процедур обработки событий рассмотрим на примере процедуры обработки события OnClick для командной кнопки Вычислить.

    Чтобы приступить к созданию процедуры обработки события, надо сначала в окне Object Inspector выбрать компонент, для которого создается процедура обработки события. Затем в этом же окне нужно выбрать вкладку Events (События).



    ВЗ Свойства компонента

    Таблица ВЗ. Свойства компонента Edit (поле ввода-редактирования)

    Свойство

    Описание

    Name

    Имя компонента. Используется в программе для доступа к компоненту и его свойствам, в частности — для доступа к тексту, введенному в поле редактирования

    Text

    Текст, находящийся в поле ввода и редактирования

    Left

    Расстояние от левой границы компонента до левой границы формы

    Top

    Расстояние от верхней границы компонента до верхней границы формы

    Height

    Высота поля

    Width

    Ширина поля

    Font

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

    ParentFont

    Признак наследования компонентом характеристик шрифта формы, на которой находится компонент. Если значение свойства равно True, то при изменении свойства Font формы автоматически меняется значение свойства Font компонента

    Delphi позволяет изменить размер и положение компонента при помощи мыши.

    Для того чтобы изменить положение компонента, необходимо установить курсор мыши на его изображение, нажать левую кнопку мыши и, удерживая ее нажатой, переместить контур компонента в нужную точку формы, затем отпустить кнопку мыши. Во время перемещения компонента (Рисунок В18) отображаются текущие значения координат левого верхнего угла компонента (значения свойств Left и тор).

    Для того чтобы изменить размер компонента, необходимо его выделить, установить указатель мыши на один из маркеров, помечающих границу компонента, нажать левую кнопку мыши и, удерживая ее нажатой, изменить положение границы компонента. Затем отпустить кнопку мыши. Во время изменения размера компонента отображаются текущие значения свойств Height И Width (Рисунок В19).

    Свойства компонента так же, как и свойства формы, можно изменить при помощи Object Inspector. Для того чтобы свойства требуемого компонента были выведены в окне Object Inspector, нужно выделить этот компонент (щелкнуть мышью на его изображении). Можно также выбрать компонент из находящегося в верхней части окна Object Inspector раскрывающегося списка объектов (Рисунок В20) или из списка в окне Object TreeView (Рисунок В21).



    Установка Delphi

    Установка Delphi

    Существует четыре варианта пакета Borland Delphi 7 Studio: Personal, Professional, Enterprise и Architect. Каждый из этих комплектов включает стандартный набор средств, обеспечивающих разработку высокоэффективных программ различного назначения, в том числе для работы с базами данных. Вместе с тем, чем выше уровень комплекта (от Personal до Architect), тем большие возможности он предоставляет программисту. Так, комплект Enterprise позволяет разрабатывать приложения работы с удаленными базами данных (например, InterBase), а комплект Personal — нет. Подробную информацию о структуре, составе и возможностях пакетов Borland Delphi 7 Studio можно найти на сайте Borland (www.borland.com/delphi).

    Материал книги не привязан к конкретному комплекту Delphi. Все задачи, рассмотренные в качестве примеров, могут быть реализованы в рамках набора Personal.

    Установка Delphi 7 на компьютер выполняется с CD-ROM, на котором находятся все необходимые файлы и программа инициализации установки (Delphi Setup Launcher). Программа инициализации установки запускается автоматически, как только установочный диск будет помещен в CD-дисковод.

    В результате запуска программы инициализации установки на экране появляется окно Delphi 7 Setup Launcher (Рисунок В1) с указанием программных продуктов, которые могут быть инсталлированы на компьютер с установочного CD-ROM. Это, прежде всего, Delphi 7, сервер базы данных InterBase 6.5, локальный сервер базы данных InterBase 6.5, инструмент удаленной отладки Remote Debugger Server, утилита ModelMaker и InstallShield Express — утилита создания установочных CD-ROM.



    Внесение изменений

    Внесение изменений

    После нескольких запусков программы Скорость бега возникает желание внести изменения в программу. Например, было бы неплохо, чтобы после ввода дистанции и нажатия клавиши курсор переходил в поле Время. Или если бы в поля Дистанция и Время пользователь мог ввести только цифры.

    Чтобы внести изменения в программу, нужно запустить Delphi и открыть соответствующий проект. Сделать это можно обычным способом, выбрав из меню File команду Open Project. Можно также воспользоваться командой Reopen из меню File. При выборе команды Reopen открывается список проектов, над которыми программист работал в последнее время.

    В листинге В5 приведена программа Скорость бега, в которую добавлены

    Процедуры обработки событий OnKeyPress Для компонентов Edit1 и Edit2.

    Следует обратить внимание на то, что для добавления в программу процедуры обработки события нужно в окне Object Inspector выбрать компонент, для которого создается процедура, затем на вкладке Events выбрать событие и сделать двойной щелчок в поле имени процедуры. Delphi сформирует шаблон процедуры обработки события. После этого можно вводить инструкции, реализующие процедуру обработки.



    Вычислить

    Вычислить

    Завершить

    Тор

    176

    176

    Left

    16

    112

    Height

    25

    25

    Width

    75

    75

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



    Запуск программы

    Запуск программы

    Пробный запуск программы можно выполнить непосредственно из Delphi, не завершая работу со средой разработки. Для этого нужно из меню Run выбрать команду Run или щелкнуть на соответствующей кнопке панели инструментов Debug (Рисунок В41).



    Основы языка Delphi

    Алгоритм и программа

    Алгоритм и программа

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

    Алгоритм решения задачи может быть представлен в виде словесного описания или графически — в виде блок-схемы. При изображении алгоритма в виде блок-схемы используются специальные символы (Рисунок 1.1).



    Алгоритм программы вычисления

    Рисунок 1.2. Алгоритм программы вычисления стоимости покупки — совокупность алгоритмов обработки событий на компонентах формы


    Алгоритм программы вычисления





    Целый тип

    Целый тип

    Язык Delphi поддерживает семь целых типов данных: shortint, smailint, Longint, Int64, Byte, word и Longword, описание которых приведено в табл. 1.1.



    Число

    Число

    Алгебраическая форма

    Форма с плавающей точкой

    1 000 000
    -123.452
    0,0056712

    1х106
    -1,23452x102
    5,6712х10-3

    1 .0000000000Е+06
    -1 .2345200000Е+02
    5,6712000000Е-03



    Числовые константы

    Числовые константы

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

    Ниже приведены примеры числовых констант:

    123 0.0

    -524.03 0

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

    В табл. 1.3 приведены примеры чисел, записанных в обычной форме, в алгебраической форме и форме с плавающей точкой.



    Функции преобразования

    Функции преобразования

    Функции преобразования (табл. 1.7) наиболее часто используются в инструкциях, обеспечивающих ввод и вывод информации. Например, для того чтобы вывести в поле вывода (компонент Label) диалогового окна значение переменной типа real, необходимо преобразовать число в строку символов, изображающую данное число. Это можно сделать при помощи функции FloatToStr, которая возвращает строковое представление значения выражения, указанного в качестве параметра функции.

    Например, инструкция Labeii.caption := FioatTostr(x) выводит значе-ние переменной х в поле Labeii.



    Именованная константа

    Именованная константа

    Именованная константа — это имя (идентификатор), которое в программе используется вместо самой константы.

    Именованная константа, как и переменная, перед использованием должна быть объявлена. В общем виде инструкция объявления именованной константы выглядит следующим образом:

    константа = значение;

    где:

  • константа — имя константы;
  • значение — значение константы.
  • Именованные константы объявляются в программе в разделе объявления констант, который начинается словом const. Ниже приведен пример объявления именованных констант (целой, строковой и дробной).

    const

    Bound = 10;

    Title = 'Скорость бега';

    pi = 3.1415926;

    После объявления именованной константы в программе вместо самой константы можно использовать ее имя.

    В отличие от переменной, при объявлении константы тип явно не указывают. Тип константы определяется ее видом, например:

  • 125 — константа целого типа;
  • 0.0 — константа вещественного типа;
  • ' выполнить ' — строковая константа;
  • ' \' — символьная константа.


  • Инструкция присваивания

    Инструкция присваивания

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

    В результате выполнения инструкции присваивания значение переменной меняется, ей присваивается значение.

    В общем виде инструкция присваивания выглядит так: Имя : = Выражение;

    где:

  • Имя — переменная, значение которой изменяется в результате выполнения инструкции присваивания;
  • : = — символ инструкции присваивания.
  • Выражение — выражение, значение которого присваивается переменной, имя которой указано слева от символа инструкции присваивания.
  • Пример:

    Surama := Сеnа * Kol; Skidka := 10; Found := False;

    Использование функций

    Использование функций

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

    n := Round((x2-x1)/dx);

    x1:= (-b + Sqrt(d)) / (2*а);

    m := Random(10);

    cena := StrToInt(Edit1.Text);

    Edit2.Text := IntToStr(100);

    mes := 'x1=' + FloatToStr(xl);

    Язык программирования Delphi

    Язык программирования Delphi

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

    Каждая инструкция состоит из идентификаторов. Идентификатор может обозначать:

  • Инструкцию языка (:=, if, while, for);
  • переменную;
  • константу (целое или дробное число);
  • арифметическую (+, -,*,/) или логическую (and, or, not) операцию;
  • подпрограмму (процедуру или функцию);
  • отмечать начало (procedure, function) или конец (end) подпрограммы ИЛИ блока (begin, end).


  • Этапы разработки программы

    Этапы разработки программы

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

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

    1. Спецификация (определение, формулирование требований к программе).

    2. Разработка алгоритма.

    3. Кодирование (запись алгоритма на языке программирования).

    4. Отладка.

    5. Тестирование.

    6. Создание справочной системы.

    7. Создание установочного диска (CD-ROM).

    Кодирование

    Кодирование

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


    Компиляция

    Компиляция

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

    Компилятор, схема работы которого приведена на Рисунок 1.4, выполняет последовательно две задачи:

    1. Проверяет текст исходной программы на отсутствие синтаксических ошибок.

    2. Создает (генерирует) исполняемую программу — машинный код.



    Компонент Edit1 используется для ввода данных

    Рисунок 1.6. Компонент Edit1 используется для ввода данных

    Компонент Edit1 используется для ввода данных

    На Рисунок 1.6 приведен вид диалогового окна программы пересчета веса из фунтов в килограммы. Компонент Editl используется для ввода исходных данных. Инструкция ввода данных в этом случае будет иметь вид:

    Funt := StrToFloat(Editl.Text);

    Константа

    Константа

    Тип сообщения

    Значок

    mtWarning

    Внимание



    Константы

    Константы

    В языке Delphi существует два вида констант: обычные и именованные.

    Обычная константа — это целое или дробное число, строка символов или отдельный символ, логическое значение.

    Программа Стоимость покупки

    Листинг 1.1. Программа Стоимость покупки

    unit pokupka_1;

    interface uses

    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForra)

    Edit1: TEdit;

    Edit2: TEdit;

    Label1: TLabel;

    Label2: TLabel;

    Button1: TButton;

    Label3: TLabel;

    procedure ButtonlClick(Sender: TObject);


    procedure Edit2KeyPress(Sender: TObject;
    var Key: Char);


    procedure EditlKeyPress(Sender: TObject;
    var Key: Char);
    private

    { Private declarations } public

    { Public declarations }
    end;

    var

    Forml: TForm1;

    implementation

    {$R *.dfm}

    // подпрограмма
    procedure Summa;
    var

    cena: real; // цена

    kol: integer; // количество

    s: real; // сумма

    mes: string[255]; // сообщение
    begin

    cena := StrToFloat(Form1.Edit1.Text);


    kol := StrToInt(Forml.Edit2.Text);


    s := cena * kol;

    if s >
    500 then


    begin

    s := s * 0.9;

    mes := 'Предоставляется скидка 10%' + #13;
    end;
    mes := mes+ 'Стоимость покупки: '

    + FloatToStrF(s,ffFixed,4,2) +' руб.';
    Forml.Label3.Caption := mes;
    end;

    // щелчок на кнопке Стоимость

    procedure TForml.ButtonlClick(Sender: TObject);


    begin

    Summa; // вычислить сумму покупки
    end;

    // нажатие клавиши в поле Количество

    procedure TForml.Edit2KeyPress(Sender: TObject; var Key: Char);


    begin

    case Key of

    '0' .. '9',#8: ; // цифры и клавиша

    #13: Summa; // вычислить стоимость покупки
    else Key := Chr(O);
    // символ не отображать
    end;
    end;

    // нажатие клавиши в поле Цена

    procedure TForm1.EditlKeyPress(Sender: TObject; var Key: Char);


    begin

    case Key of

    '0' .. '9', #8 : ; // цифры и клавиша


    #13: Form1.Edit2.SetFocus; // клавиша


    '.' ,'.' :

    begin

    if Key = '.'

    then Key:=', if Pos(',',Edit1.Text) <>
    0

    then Key:= Chr(0);

    end;
    else // все остальные символы запрещены

    Key := Chr(0);

    end;
    end;

    end.



    Логические константы

    Логические константы

    Логическое высказывание (выражение) может быть либо истинно, либо ложно. Истине соответствует константа True, значению "ложь" - константа False.

    Логический тип

    Логический тип

    Логическая величина может принимать одно из двух значений True (истина) или False (ложь). В языке Delphi логические величины относят к типу Boolean.

    Математические функции

    Математические функции

    Математические функции (табл. 1.6) позволяют выполнять различные вычисления.



    Окно (форма) программы Стоимость покупки

    Рисунок 1.3. Окно (форма) программы Стоимость покупки


    Окно (форма) программы Стоимость покупки




    Основные символы используемые

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

    Основные символы используемые

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

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

    В качестве примера на Рисунок 1.2 приведена совокупность алгоритмов программы Стоимость покупки, а на Рисунок 1.3 — ее диалоговое окно. После разработки диалогового окна и алгоритмов обработки событий можно приступить к написанию программы. Ее текст приведен в листинге 1.1.



    Отладка

    Отладка

    Отладка — это процесс поиска и устранения ошибок. Ошибки в программе разделяют на две группы: синтаксические (ошибки в тексте) и алгоритмические. Синтаксические ошибки — наиболее легко устраняемые. Алгоритмические ошибки обнаружить труднее. Этап отладки можно считать законченным, если программа правильно работает на одном-двух наборах входных данных.

    Переменная

    Переменная

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

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

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

    Следует обратить внимание на то, что компилятор языка Delphi не различает прописные и строчные буквы в именах переменных, поэтому имена SUMMA, Summa и summa обозначают одну и ту же переменную.

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

    ах2 + bх + с = 0

    вполне логично присвоить имена а, b, с, x1 и х2. Другой пример. Если в программе есть переменные, предназначенные для хранения суммы покупки и величины скидки, то этим переменным можно присвоить имена

    TotalSumm и Discount или ObSumma и Skidka.

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

    В общем виде инструкция объявления переменной выглядит так:

    Имя : тип;

    где:

  • имя — имя переменной;
  • тип — тип данных, для хранения которых предназначена переменная.
  • Пример:

    а : Real; b : Real; i : Integer;

    В приведенных примерах объявлены две переменные типа real и одна переменная типа integer.

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

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

    а,b,с : Real; x1,x2 : Real;

    Поле Label2 предназначено для

    Рисунок 1.9. Поле Label2 предназначено для вывода результата работы программы

    Поле Label2 предназначено для

    Свойство Caption символьного типа. Поэтому для того, чтобы во время работы программы вывести в поле метки числовое значение, нужно преобразовать число в строку, например, При при помощи фуекции FloatToStr или IntToStr.

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

    Label2.Caption:= FloatToStr(kg)+' кг';

    Пример окна сообщения

    Рисунок 1.7. Пример окна сообщения

    Пример окна сообщения

    Следует обратить внимание на то, что в заголовке окна сообщения, выводимого процедурой ShowMessage, указано название приложения, которое задается на вкладке Application окна Project Options. Если название приложения не задано, то в заголовке будет имя исполняемого файла.

    Функция MessageDig более универсальная. Она позволяет поместить в окно с сообщением один из стандартных значков, например "Внимание", задать количество и тип командных кнопок и определить, какую из кнопок нажал пользователь. На Рисунок 1.8 приведено окно, выведенное в результате выполнения инструкции

    r:=MessageDlg('Файл '+ FName + ' будет удален.', mtWarning, [mbOk,mbCancel] , 0) ;


    Рисунок 1.8. Пример окна сообщения

    Пример окна сообщения

    Значение функции MessageDlg — число, проверив значение которого, можно определить, выбором какой командной кнопки был завершен диалог.

    В общем виде обращение к функции MessageDig выглядит так:

    Выбор: = MessageDlg( Сообщение, Тип, Кнопки, КонтекстСправки)

    где:

  • Сообщение — текст сообщения;
  • Тип — тип сообщения. Сообщение может быть информационным, предупреждающим или сообщением о критической ошибке. Каждому типу сообщения соответствует определенный значок. Тип сообщения задается именованной константой (табл. 1.8);
  • Кнопки — список кнопок, отображаемых в окне сообщения. Список может состоять из нескольких разделенных запятыми именованных констант (табл. 1.9). Весь список заключается в квадратные скобки.

    Пример окна ввода

    Рисунок 1.5. Пример окна ввода

    Пример окна ввода

    Если во время работы программы пользователь введет строку и щелкнет на кнопке ОК, то значением функции inputBox будет введенная строка. Если будет сделан щелчок на кнопке Cancel, то значением функции будет строка, переданная функции в качестве параметра значение.

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

    s := InputBox('Фунты-килограммы1,'Введите вес в фунтах',''); funt := StrToFloat(s);

    Процедуры и функции

    Процедуры и функции

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

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

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

    Программа

    Программа

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


    Разработка алгоритма

    Разработка алгоритма

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

    Схема работы компилятора

    Рисунок 1.4. Схема работы компилятора

    Схема работы компилятора

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

    Генерация машинного кода компилятором свидетельствует лишь о том, что в тексте программы нет синтаксических ошибок. Убедиться, что программа работает правильно можно только в процессе ее тестирования — пробных запусках программы и анализе полученных результатов. Например, если в программе вычисления корней квадратного уравнения допущена ошибка в выражении (формуле) вычисления дискриминанта, то, даже если это выражение будет синтаксически верно, программа выдаст неверные значения корней.

    Символьный тип

    Символьный тип

    Язык Delphi поддерживает два символьных типа: Ansichar и Widechar:

  • тип Ansichar — это символы в кодировке ANSI, которым соответствуют числа в диапазоне от 0 до 255;
  • тип widechar — это символы в кодировке Unicode, им соответствуют числа от 0 до 65 535.
  • Object Pascal поддерживает и наиболее универсальный символьный тип - Char, который эквивалентен Ansichar.

    Создание справочной системы

    Создание справочной системы

    Если разработчик предполагает, что программой будут пользоваться другие, то он обязательно должен создать справочную систему и обеспечить пользователю удобный доступ к справочной информации во время работы с программой. В современных программах справочная информация представляется в форме СНМ- или HLP-файлов. Помимо справочной информации, доступ к которой осуществляется из программы во время ее работы, в состав справочной системы включают инструкцию по установке (инсталляции) программы, которую оформляют в виде Readme-файла в одном из форматов: TXT, DOC или НТМ.

    Процесс создания справочной системы и механизмы доступа к справочной информации описаны в гл. 14.

    Создание установочного диска

    Создание установочного диска

    Установочный диск или CD-ROM создаются для того, чтобы пользователь мог самостоятельно, без помощи разработчика, установить программу на свой компьютер. Обычно помимо самой программы на установочном диске находятся файлы справочной информации и инструкция по установке программы (Readme-файл). Следует понимать, что современные программы, в том числе разработанные в Delphi, в большинстве случаев (за исключением самых простых программ) не могут быть установлены на компьютер пользователя путем простого копирования, так как для своей работы требуют специальных библиотек и компонентов, которых может и не быть у конкретного пользователя. Поэтому установку программы на компьютер пользователя должна выполнять специальная программа, которая помещается на установочный диск. Как правило, установочная программа создает отдельную папку для устанавливаемой программы, копирует в нее необходимые файлы и, если надо, выполняет настройку операционной системы путем внесения дополнений и изменений в реестр.

    Процесс создания установочного диска (CD-ROM) при помощи входящей в состав Delphi утилиты InstallShield Express описан в гл. 18.

    Спецификация

    Спецификация

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

    Стандартные функции

    Стандартные функции

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

    Значение функции связано с ее именем. Поэтому функцию можно использовать в качестве операнда выражения, например в инструкции присваивания. Так, чтобы вычислить квадратный корень, достаточно записать k:=Sqrt(n), где Sqrt — функция вычисления квадратного корня, п — переменная, которая содержит число, квадратный корень которого надо вычислить.

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


    Стиль программирования

    Стиль программирования

    Работая над программой, программист, особенно начинающий, должен хорошо представлять, что программа, которую он разрабатывает, предназначена, с одной стороны, для пользователя, с другой — для самого программиста. Текст программы нужен прежде всего самому программисту, а также другим людям, с которыми он совместно работает над проектом. Поэтому для того, чтобы работа была эффективной, программа должна быть легко читаемой, ее структура должна соответствовать структуре и алгоритму решаемой задачи. Как этого добиться? Надо следовать правилам хорошего стиля программирования. Стиль программирования — это набор правил, которым следует программист (осознано или потому, что "так делают другие") в процессе своей работы. Очевидно, что хороший программист должен следовать правилам хорошего стиля.

    Хороший стиль программирования предполагает:
  • использование комментариев;
  • использование несущих смысловую нагрузку имен переменных, процедур и функций;
  • использование отступов;
  • использование пустых строк.
  • Следование правилам хорошего стиля программирования значительно уменьшает вероятность появления ошибок на этапе набора текста, делает программу легко читаемой, что, в свою очередь, облегчает процессы отладки и внесения изменений.

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

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

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

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

    Примечание

    Приведенные в книге программы могут служить примером следования правилам хорошего стиля программирования.

    Строковые и символьные константы

    Строковые и символьные константы

    Строковые и символьные константы заключаются в кавычки. Ниже приведены примеры строковых констант:

    'Язык программирования Delphi1 'Delphi 7'

    '2.4'

    'Д'

    Здесь следует обратить внимание на константу ' 2.4'. Это именно символьная константа, т. е. строка символов, которая изображает число "две целые четыре десятых", а не число 2,4.

    Строковый тип

    Строковый тип

    Язык Delphi поддерживает три строковых типа: shortstring, Longstring

  • WideString:
  • тип shortstring представляет собой статически размещаемые в памяти компьютера строки длиной от 0 до 255 символов;
  • тип Longstring представляет собой динамически размещаемые в памяти строки, длина которых ограничена только объемом свободной памяти;
  • тип WideString представляет собой динамически размещаемые в памяти строки, длина которых ограничена только объемом свободной памяти. Каждый символ строки типа WideString является Unicode-символом.
  • В языке Delphi для обозначения строкового типа допускается использование идентификатора string. Тип string эквивалентен типу shortstring.

    В языке Delphi для обозначения строкового типа допускается использование идентификатора string. Тип string эквивалентен типу shortstring.

    Структура функции

    Структура функции

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

    Объявление функции в общем виде выглядит следующим образом:

    function Имя (СписокПараметров) : Тип;

    const // начало раздела объявления констант

    type // начало раздела объявления типов
    var // начало раздела объявления переменных
    begin // начало раздела инструкций

    result := Значение; // связать с именем функции значение
    end;

    Заголовок функции начинается словом function, за которым следует имя функции. После имени функции в скобках приводится список параметров, за которым через двоеточие указывается тип значения, возвращаемого функцией (тип функции). Завершается заголовок функции символом "точка с запятой".

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

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

    Ниже в качестве примера приведена функция FuntToKg, которая пересчитывает вес из фунтов в килограммы:

    // Пересчет веса из фунтов в килограммы
    function FuntToKg(f:real):real;
    const

    // в России 1 фунт равен 409,5 гр.
    К=0.4095; // коэф. Пересчета
    begin

    result:=f*K;
    end;

    Структура процедуры

    Структура процедуры

    Процедура начинается с заголовка, за которым следуют: П раздел объявления констант;

  • раздел объявления типов;
  • раздел объявления переменных;
  • раздел инструкций.
  • В общем виде процедура выглядит так:

    procedure Имя (СписокПараметров);
    const

    // здесь объявления констант
    type

    // здесь объявления типов var

    // здесь объявления переменных
    begin

    // здесь инструкции программы
    end;

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

    Если в процедуре используются именованные константы, то они объявляются в разделе объявления констант, который начинается словом const.

    За разделом констант следует раздел объявления типов, начинающийся словом type.

    После раздела объявления типов идет раздел объявления переменных, в котором объявляются (перечисляются) все переменные, используемые в программе. Раздел объявления переменных начинается словом var.

    За разделом объявления переменных расположен раздел инструкций. Раздел инструкций начинается словом begin и заканчивается словом end, за которым следует символ "точка с запятой". В разделе инструкций находятся исполняемые инструкции процедуры.

    Ниже в качестве примера приведен фрагмент программы вычисления стоимости покупки — процедура Summa.

    procedure Summa;
    var

    cena: real; // цена

    kol: integer; // количество

    s: real; // сумма
    mes: string[255]; // сообщение

    begin

    cena := StrToFloat(Form1.Edit1.Text);
    kol := StrToInt(Form1.Edit2.Text);
    s := cena * kol; if s > 500 then
    begin

    s := s * 0.9;

    mes := 'Предоставляется скидка 10%'
    + #13; end; mes := mes+ 'Стоимость покупки: '

    + FloatToStrF(s,ffFixed,4,2) +' руб.';
    Forml.Label3.Caption := mes; end;

    Целые типы

    Таблица 1.1. Целые типы



    Значения функции MessageDlg

    Таблица 1.10. Значения функции MessageDlg

    Значение функции MessageDig

    Диалог завершен нажатием кнопки

    mrAbort

    Abort

    mrYes

    Yes

    mrOk

    Ok

    mrRetry

    Retry

    mrNo

    No

    mrCancel

    Cancel

    mrIgnore

    Ignore

    mrAll

    All



    Вещественные (дробные) типы

    Таблица 1.2. Вещественные (дробные) типы



    Примеры записи дробных чисел

    Таблица 1.3. Примеры записи дробных чисел



    Алгебраические операторы

    Таблица 1.4. Алгебраические операторы

    Оператор

    Действие

    +

    Сложение

    -

    Вычитание

    *

    Умножение

    /

    Деление

    DIV

    Деление нацело

    MOD

    Вычисление остатка от деления

    При записи выражений между операндом и оператором, за исключением операторов DIV и MOD, пробел можно не ставить.

    Результат применения операторов +, -, * и / очевиден.

    Оператор DIV позволяет получить целую часть результата деления одного числа на другое. Например, значение выражения is DIV i равно 2.

    Оператор MOD, деление по модулю, позволяет получить остаток от деления одного числа на другое. Например, значение выражения 15 MOD 7 равно 1.

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

    Примеры выражений:

    123 0.001 i+1

    А + В/С Summa*0.75 (В1+ВЗ+ВЗ)/3 Cena MOD 100

    При вычислении значений выражений следует учитывать, что операторы имеют разный приоритет. Так у операторов *, /, DIV, MOD более высокий приоритет, чем у операторов + и -.

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

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

    (r1+r2+r3)/(r1*r2*r3)

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

    Правила определения типа выражения

    Таблица 1.5. Правила определения типа выражения

    Оператор

    Тип операндов

    Тип выражения

    *, +, -

    Хотя бы один из операндов real

    real

    *, +, -

    Оба операнда integer

    integer

    /

    real или integer

    Всегда real

    DIV, MOD

    Всегда integer

    Всегда integer



    Математические функции

    Таблица 1.6. Математические функции

    Функция

    Значение

    Аbs (n)

    Абсолютное значение n

    Sqrt (n)

    Квадратный корень из n

    Sqr (n)

    Квадрат n

    Sin (n)

    Синус n

    Cos (n)

    Косинус n

    Arctan (n)

    Арктангенс n

    Ехр(n)

    Экспонента n

    Ln(n)

    Натуральный логарифм n

    Rardom(n)

    Случайное целое число в диапазоне от 0 до n- 1

    Величина угла тригонометрических функций должна быть выражена в радианах. Для преобразования величины угла из градусов в радианы используется формула (а*з.141525б)/180, где: а— величина угла в градусах; 3.1415926 — число л. Вместо дробной константы 3.1415926 можно использовать стандартную именованную константу PI. В этом случае выражение пересчета угла из градусов в радианы будет выглядеть так: a*Pi/180.

    Функции преобразования

    Таблица 1.7. Функции преобразования

    Функция

    Значение функции

    Chr(n) IntToStr (k)

    Символ, код которого равен n Строка, являющаяся изображением целого k

    Функция

    Значение функции

    FloatToStr (n)

    Строка, являющаяся изображением вещественного n

    FloatToStrF(n, f , k,m)

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

    StrToInt (s)

    Целое, изображением которого является строка s

    StrToFloat (s)

    Вещественное, изображением которого является строка s

    Round (n)

    Целое, полученное путем округления n по известным правилам

    Trunc (n)

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

    Frac(n)

    Дробное, представляющее собой дробную часть вещественного n

    Int (n)

    Дробное, представляющее собой целую часть вещественного n



    Константы функции MessageDlg

    Таблица 1.8. Константы функции MessageDlg



    Константы функции MessageDlg

    Таблица 1.9. Константы функции MessageDlg

    Константы функции MessageDlg

    Константа

    Кнопка

    Константа

    Кнопка

    mbYes

    Yes

    mb Abort

    Abort

    mbNo

    No

    mbRetry

    Retry

    mbOK

    OK

    mblgnore

    Ignore

    mbCancel

    Cancel

    mbAll

    All

    mbHelp

    Help





    Например, для того чтобы в окне сообщения появились кнопки ОК и Cancel, список Кнопки должен быть таким:

    [mbOK,mbCancel]

    Кроме приведенных констант можно использовать константы: mbokcancel, mbYesNoCancel и mbAbortRetryIgnore. Эти константы определяют наиболее часто используемые в диалоговых окнах комбинации командных кнопок.

    контекстСправки — параметр, определяющий раздел справочной системы, который появится на экране, если пользователь нажмет клавишу . Если вывод справки не предусмотрен, то значение параметра КонтекстСправки должно быть равно нулю.

    Значение, возвращаемое функцией MessageDig (табл. 1.10), позволяет определить, какая из командных кнопок была нажата пользователем.



    Тестирование

    Тестирование

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

    Тип данных

    Тип данных

    Программа может оперировать данными различных типов: целыми и дробными числами, символами, строками символов, логическими величинами.


    Тип выражения

    Тип выражения

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

    Важно уметь определять тип выражения. При определении типа выражения следует иметь в виду, что тип константы определяется ее видом, а тип переменной задается в инструкции объявления. Например, константы о, 1 и -512 — целого типа (integer), а константы 1.0, 0.0 и 3.2Е-05 — вещественного типа (real).

    В табл. 1.5 приведены правила определения типа выражения в зависимости от типа операндов и вида оператора.



    Тип

    Тип

    Диапазон

    Формат

    Shortint

    -128-127

    8 битов

    Smallint

    -32 768 - 32 767

    16 битов

    Longint

    -2 147 483 648 - 2 147 483 647

    32 бита

    Int64

    -263- 263 - 1

    64 бита

    Byte

    0-255

    8 битов, беззнаковый

    Word

    0-65 535

    16 битов, беззнаковый

    Longword

    0 - 4 294 967 295

    32 бита, беззнаковый

    Object Pascal поддерживает и наиболее универсальный целый тип - Integer, который Эквивалентен Longint.

    Тип

    Тип

    Диапазон

    Значащих цифр

    Байтов

    Real48

    2.9x 10-39-1.7x1038

    11-12

    06

    Single

    1.5 x 10-45-3.4х 1038

    7-8

    04

    Double

    5.0x10-324 -1.7x10308

    15-16

    08

    Extended

    3.6x10-4951 -1.1 х104932

    19-20

    10

    Comp

    263+1 - 263-1

    19-20

    08

    Currency

    -922 337 203 685 477.5808 --922 337 203 685 477.5807

    19-20

    08

    Язык Delphi поддерживает и наиболее универсальный вещественный тип - Real, который э квивалентен Double.

    Вещественный тип

    Вещественный тип

    Язык Delphi поддерживает шесть вещественных типов: Reai48, single, Double, Extended, comp, Currency. Типы различаются между собой диапазо-ном допустимых значений, количеством значащих цифр и количеством байтов, необходимых для хранения данных в памяти компьютера (табл. 1.2).



    Ввод данных

    Ввод данных

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

    Ввод из окна ввода

    Ввод из окна ввода

    Окно ввода — это стандартное диалоговое окно, которое появляется на экране в результате вызова функции inputBox. Значение функции inputBox — строка, которую ввел пользователь.

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

    Переменная := InputBox(Заголовок, Подсказка, Значение);

    где:

  • Переменная — переменная строкового типа, значение которой должно быть получено от пользователя;
  • Заголовок — текст заголовка окна ввода; П подсказка — текст поясняющего сообщения;
  • Значение — текст, который будет находиться в поле ввода, когда окно ввода появится на экране.
  • Ниже в качестве примера приведена инструкция, используя которую можно получить исходные данные для программы пересчета веса из фунтов в килограммы. Окно ввода, соответствующее этой инструкции, приведено на Рисунок 1.5.

    s:=InputBox('Фунты-килограммы','Введите вес в фунтах','0');



    Ввод из поля редактирования

    Ввод из поля редактирования

    Поле редактирования — это компонент Edit. Ввод данных из поля редактирования осуществляется обращением к свойству Text.



    Выполнение инструкции присваивания

    Выполнение инструкции присваивания

    Инструкция присваивания выполняется следующим образом:

    1. Сначала вычисляется значение выражения, которое находится справа от символа инструкции присваивания.

    2. Затем вычисленное значение записывается в переменную, имя которой стоит слева от символа инструкции присваивания.

    Например, в результате выполнения инструкций:

  • i:=0; — значение переменной i становится равным нулю;
  • а:=b+с; — значением переменной а будет число, равное сумме значений переменных ь и с;
  • j :=j+1; — значение переменной j увеличивается на единицу.
  • Инструкция присваивания считается верной, если тип выражения соответствует или может быть приведен к типу переменной, получающей значение. Например, переменной типа real можно присвоить значение выражения, тип которого real или integer, а переменной типа integer можно присвоить значение выражения только типа integer.

    Так, например, если переменные i и п имеют тип integer, а переменная d — тип real, то инструкции

    i:=n/10; i:=1.0;

    неправильные, а инструкция

    d:=i+1; правильная.

    Во время компиляции выполняется проверка соответствия типа выражения типу переменной. Если тип выражения не соответствует типу переменной, то компилятор выводит сообщение об ошибке:

    Incompatible types ... and ...

    где вместо многоточий указывается тип выражения и переменной. Например, если переменная п целого типа, то инструкция n: = m/2 неверная, поэтому во время компиляции будет выведено сообщение :

    Incompatible types 'Integer' and.'Extended'.

    Выражение

    Выражение

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



    Вывод результатов

    Вывод результатов

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


    Вывод в окно сообщения

    Вывод в окно сообщения

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

    Вывести на экран окно с сообщением можно при помощи процедуры ShowMessage или функции MessageDlg.

    Процедура ShowMessage выводит на экран окно с текстом и командной кнопкой ОК.

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

    ShowMessage(Сообщение);

    где сообщение — текст, который будет выведен в окне.

    На Рисунок 1.7 приведен вид окна сообщения, полученного в результате выполнения инструкции:

    ShowMessage('Введите вес в фунтах.');



    Вывод в поле диалогового окна

    Вывод в поле диалогового окна

    Часть диалогового окна, предназначенная для вывода информации, называется полем вывода, или полем метки. Поле вывода — это компонент Label.

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

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

    На Рисунок 1.9 изображено диалоговое окно программы пересчета веса из фунтов в килограммы. Окно содержит два компонента Label. Компонент Label1 обеспечивает вывод информационного сообщения, компонент Label2 — вывод результата работы программы.



    Запись инструкций программы

    Запись инструкций программы

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

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

    Некоторые инструкции (if, case, repeat, while и др.) принято записывать в несколько строк, используя для выделения структуры инструкции отступы. Ниже приведен пример инструкции, которая записана в несколько строк и с использованием отступов:

    if d >= 0 then begin

    x1:=(-b+Sqrt(d))/(2*a);
    x2:=(-b-Sqrt(d))/(2*a);
    ShowMessage('x1='+FloatToStr(xl) +
    'x2='+FloatToStr(x2)) ;
    end

    else

    ShowMessage('Уравнение не имеет корней.');

    Следует обратить внимание на то, что слова then и else записаны одно под другим (с одинаковым отступом) и с отступом относительно слова if. Слово end располагается под словом begin, а инструкции между begin и end размещаются одна под другой, но с отступом относительно begin.

    Приведенную выше инструкцию можно записать и так:

    if d >= 0 then begin

    x1:=(-b+Sqrt(d))/(2*a);

    x2:=(-b-Sqrt(d))/(2*a);

    ShowMessage('x1='+FloatToStr(x1)+'x2='+FloatToStr(x2));

    end

    else ShowMessage('Уравнение не имеет корней.');

    Однако первый вариант лучше, т. к. он отражает структуру алгоритма, реализуемого инструкцией. С первого взгляда видна группа инструкций, которая будет выполнена, если условие d >= о выполняется (в этом случае будут вычислены значения переменных xl и х2), и инструкция, которая будет выполнена, если условие d >=o не выполняется.

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

    Ниже приведен пример записи выражения в несколько строк:

    st:= 'Корни уравнения'+ #13

    +'x1=' + FloatToStr(x1)+ #13 +'х2=' + FloatToStr(x2);

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

    x1:=(-b+Sqrt(d))/(2*a);

    и

    x1 := (-b + Sqrt(d)) / (2 * а);

    Очевидно, что второй вариант воспринимается лучше.

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

    Ниже приведен пример раздела объявления переменных, в котором использованы оба способа записи комментариев:

    var

    { коэффициенты уравнения }
    a:real; // при второй степени неизвестного
    b:real; // при первой степени неизвестного
    с:real; // при нулевой степени неизвестного

    { корни уравнения } x1,x2:real;

    Основы языка Delphi

    Алгоритм инструкции for

    Рисунок 2.13. Алгоритм инструкции for

    Алгоритм инструкции for

    Алгоритм, соответствующий инструкции for, представлен на Рисунок 2.13. Обратите внимание, что если начальное значение счетчика больше конечного значения, то последовательность операторов между begin и end не будет выполнена ни разу.

    Кроме того, после каждого выполнения инструкций тела цикла счетчик циклов увеличивается автоматически.

    Переменную-счетчик можно использовать внутри цикла (но ни в коем случае не изменять). Например, в результате выполнения следующих инструкций:

    tab1: = '' ;
    for i:=l to 5 do
    begin

    tab1:=tabl+IntToStr(i)+' '+IntToStr(i*i)+chr(13);
    end;

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

    Рассмотрим программу, которая вычисляет сумму первых 10 элементов ряда: 1 + + 1/3 + ... (значение i-го элемента ряда связано с его номером формулой 1//). Диалоговое окно программы должно содержать, по крайней мере, два компонента: поле метки (Label1) и командную кнопку (Buttonl).

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

    procedure TForm1.ButtonlClick(Sender: TObject);
    var

    i:integer; { номер элемента ряда }
    elem:real;
    { значение элемента ряда }
    summ:real;
    { сумма элементов ряда )

    begin

    summ:=0;

    label Leapt ion: = ' ' ;
    for i:=l to 10 do begin

    elem:=l/i;

    label1.caption:=labell.caption+

    IntToStr(i)+' '+FloatToStr(elem)+#13; sunrn: =summ+elem;
    end;
    label1.caption:=label1.caption+

    'Сумма ряда:'+FloatToStr(summ);
    end;

    Если в инструкции for вместо слова to записать downto, то после очередного выполнения инструкций тела цикла значение счетчика будет не увеличиваться, а уменьшаться.

    Алгоритм инструкции while

    Рисунок 2.14. Алгоритм инструкции while

    Алгоритм инструкции while

    Для того чтобы цикл завершился, нужно, чтобы последовательность инструкций между begin и end влияла на значение выражения условие (изменяла значения переменных, входящих в выражение условие).

    Рассмотрим программу, которая вычисляет значение числа л с точностью, задаваемой пользователем во время работы программы. В основе алгоритма вычисления лежит тот факт, что сумма ряда 1 - 1/3 + 1/5 -1/7 + 1/9 + ... приближается к значению л/4 при достаточно большом количестве членов ряда.

    Каждый член ряда с номером n вычисляется по формуле: 1/(2*n - 1) и умножается на минус один, если n четное (определить, является ли п четным, можно проверкой остатка от деления п на 2). Вычисление заканчивается тогда, когда значение очередного члена ряда становится меньше, чем заданная точность вычисления.

    Вид диалогового окна программы во время ее работы приведен на Рисунок 2.15. Пользователь вводит точность вычисления в поле ввода (Editi). После щелчка на командной кнопке Вычислить (Buttonl) программа вычисляет значение числа л и выводит результат в поле метки (Labeii).

    Текст программы приведен в листинге 2.6. Как и в предыдущих примерах, основную работу выполняет процедура обработки события OnClick.



    Алгоритм программы Контроль веса

    Рисунок 2.6. Алгоритм программы Контроль веса


    Алгоритм программы Контроль веса





    Алгоритм реализуемый инструкцией ifthen Например инструкция

    Рисунок 2.3. Алгоритм, реализуемый инструкцией if-then Например, инструкция

    Алгоритм реализуемый инструкцией ifthen Например инструкция

    if n=m

    then c:=c+l;

    увеличивает значение переменной с только в том случае, если значения переменных n и m равны.

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

    Как известно, стоимость междугородного разговора по телефону в выходные дни ниже, чем в обычные. Программа, текст которой приведен в листинге 2.1, запрашивает длительность разговора и день недели, а затем вычисляет стоимость разговора. Если день недели — суббота или воскресенье, то стоимость уменьшается на величину скидки. Цена минуты разговора и величина скидки задаются в тексте программы как константы. Вид диалогового окна программы приведен на Рисунок 2.4.

    Для ввода исходных данных (длительность разговора, номер дня недели) используются поля редактирования, для вывода результата и пояснительного текста — поля меток. В табл. 2.3 перечислены компоненты и указано их назначение, а в табл. 2.4 приведены значения свойств этих компонентов.



    Алгоритм реализуемый инструкцией ifthenelse

    Рисунок 2.2. Алгоритм, реализуемый инструкцией if-then-else

    Алгоритм реализуемый инструкцией ifthenelse

    Например, если переменная t обозначает тип соединения сопротивлений в электрической цепи (t=1 соответствует последовательному соединению, t=2 — параллельному), a r1 и r2 — величины сопротивлений, то приведенная ниже инструкция if осуществляет выбор формулы, по которой будет выполнен расчет.

    if t=l then

    begin

    z:=r1+r2;
    end
    else

    begin

    z:=(r1+r2)/(r1*r2);
    end;

    Если в инструкции if между begin и end находится только одна инструкция, то слова begin и end можно не писать.

    Например, инструкцию

    if otv=3
    then

    begin

    prav:=prav+1 ;
    end
    else

    begin

    ShowMessage('Ошибка!');

    end;

    можно переписать так:

    if otv=3 then

    prav:=prav+l
    else

    ShowMessage('Ошибка!') ;

    Если какое-либо действие должно быть выполнено только при выполнении определенного условия и пропущено, если это условие не выполняется, то инструкция if может быть записана так:

    if условие then

    begin

    { инструкции, которые надо выполнить, если условие выполняется, истинно } end

    На Рисунок 2.3 представлен алгоритм, соответствующий инструкции if-then.



    Алгоритм реализуемый инструкцией

    Рисунок 2.7. Алгоритм, реализуемый инструкцией case Ниже приведены примеры инструкции case.

    Алгоритм реализуемый инструкцией

    case n_day of

    1,2,3,4,5: day:='Рабочий день. ' ;

    6: day:='Cyббoтa!';

    7: day:='Воскресенье!';
    end;

    case n_day of

    1..5: day:='Рабочий день.';

    6: day:='Суббота!';

    7: day:='Воскресенье!';
    end;

    case n_day of

    6: day:='Суббота!';

    7: day:='Воскресенье!';

    else day:='Рабочий день.';
    end;

    В качестве примера использования инструкции case рассмотрим программу, которая пересчитывает вес из фунтов в килограммы. Программа учитывает, что в разных странах фунт "весит" по-разному. Например, в России фунт равен 409,5 граммов, в Англии — 453,592 грамма, а в Германии, Дании и Исландии фунт весит 500 граммов.

    В диалоговом окне программы, изображенном на Рисунок 2.8, для выбора страны используется список Страна.



    Алгоритм соответствующий инструкции repeat

    Рисунок 2.16. Алгоритм, соответствующий инструкции repeat

    Алгоритм соответствующий инструкции repeat

    Внимание!

    Инструкции цикла, находящиеся между repeat и until, выполняются как минимум один раз. Для того чтобы цикл завершился, необходимо, чтобы инструкции цикла, располагающиеся между repeat и until, изменяли значения переменных, входящих в выражение условие.

    В качестве примера использования инструкции repeat рассмотрим программу, которая проверяет, является ли введенное пользователем число простым (как известно, число называется простым, если оно делится только на единицу и само на себя). Например, число 21 — обычное (делится на 3), а число 17 — простое (делится только на 1 и на 17).

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

    Форма приложения Простое число изображена на Рисунок 2.17, программа приведена в листинге 2.7.



    Циклы

    Циклы

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

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

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

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

    В программе цикл может быть реализован при помощи инструкций for,

    while и repeat.

    Диалоговое окно программы Пример использования case

    Рисунок 2.8. Диалоговое окно программы Пример использования case

    Диалоговое окно программы Пример использования case

    Для выбора названия страны используется список — компонент ListBox. Значок компонента ListBox находится на вкладке Standard (Рисунок 2.9). Добавляется список к форме приложения точно так же, как и другие компоненты, например, командная кнопка или поле редактирования. В табл. 2.5 приведены свойства компонента ListBox.



    Диалоговое окно программы Стоимость разговора

    Рисунок 2.4. Диалоговое окно программы Стоимость разговора

    Диалоговое окно программы Стоимость разговора

    Примечание

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



    Диалоговое окно программы Вычисление ПИ

    Рисунок 2.15. Диалоговое окно программы Вычисление ПИ


    Диалоговое окно программы Вычисление ПИ





    Диалоговое окно программы

    Рисунок 2.12. Диалоговое окно программы


    Диалоговое окно программы





    Два варианта алгоритма решения одной задачи

    Рисунок 2.1. Два варианта алгоритма решения одной задачи

    Два варианта алгоритма решения одной задачи

    Простое условие состоит из двух операндов и оператора сравнения. В общем виде условие записывается следующим образом:

    Оn1 Оператор On2

    где:

  • On1 и Оп2 — операнды условия, в качестве которых может выступать переменная, константа, функция или выражение;
  • Оператор — оператор сравнения.
  • В языке Delphi есть шесть операторов сравнения, которые приведены в табл. 2.1.



    Форма приложения Простое число

    Рисунок 2.17. Форма приложения Простое число


    Форма приложения Простое число





    Управляющие структуры

    Глава 2. Управляющие структуры языка Delphi

    На практике редко встречаются задачи, алгоритм решения которых является линейным. Часто оказывается, что алгоритм решения даже элементарной задачи не является линейным. Например, пусть надо вычислить по формуле ток в электрической цепи. Если предположить, что пользователь всегда будет вводить верные данные, то алгоритм решения этой задачи действительно является линейным. Однако полагаться на то, что пользователь будет вести себя так, как надо программе, не следует. Формула расчета предполагает, что величина сопротивления не равна нулю. А что будет, если пользователь введет 0? Ответ простой: возникнет ошибка "Деление на ноль", и программа аварийно завершит работу. Можно, конечно, возложить ответственность за это на пользователя, но лучше внести изменения в алгоритм решения (Рисунок 2.1), чтобы расчет выполнялся только в том случае, если введены верные данные.

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



    Инструкция case

    Инструкция case

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

    В языке Delphi есть инструкция case, которая позволяет эффективно реализовать множественный выбор. В общем виде она записывается следующим образом:

    case Селектор of список1:
    begin

    { инструкции 1 } end; список2:
    begin

    { инструкции 2 } end; списокМ:
    begin

    { инструкции N }
    end;
    else

    begin

    { инструкции )
    end;
    end;

    где:

  • Селектор — выражение, значение которого определяет дальнейший ход выполнения программы (т. е. последовательность инструкций, которая будет выполнена);
  • Список N — список констант. Если константы представляют собой диапазон чисел, то вместо списка можно указать первую и последнюю константу диапазона, разделив их двумя точками. Например, список 1, 2, 3, 4, 5, 6 может быть заменен диапазоном 1..6.
  • Выполняется инструкция case следующим образом:

    1. Сначала вычисляется значение выражения-селектора.

    2. Значение выражения-селектора последовательно сравнивается с константами из списков констант.

    3. Если значение выражения совпадает с константой из списка, то выполняется соответствующая этому списку группа инструкций. На этом выполнение инструкции саsе завершается.

    4. Если значение выражения-селектора не совпадает ни с одной константой из всех списков, то выполняется последовательность инструкций, следующая за else.

    Синтаксис инструкции case позволяет не писать else и соответствующую последовательность инструкций. В этом случае, если значение выражения не совпадает ни с одной константой из всех списков, то выполняется следующая за case инструкция программы.

    На Рисунок 2.7 приведен алгоритм, реализуемый инструкцией case.



    Инструкция for

    Инструкция for

    Рассмотрим следующую задачу. Пусть нужно написать программу, которая вычисляет значение функции у = 5х2 - 7 в точках —1, -0.5, 0, 0.5 и 1

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

    procedure TForm1.ButtonlClick(Sender: TObject); var

    у: real; // значение функции

    x: real; // аргумент функции

    dx: real; // приращение аргумента

    st: string; // изображение таблицы
    begin

    st:='';

    x := -1; dx := 0.5;

    у := 5*х*х -7;

    st := st+ FloatToStr(x)+' '+ FloatToStr(y)+chr(13);

    x :=x + dx;

    у := 5*х*х -7;

    st := st+ FloatToStr(x)+* '+ FloatToStr(y)+chr(13);

    x :=x + dx;

    у := 5*х*х -7;

    st := st+ FloatToStr(x)+* '+ FloatToStr(y)+chr(13);

    x :=x + dx;

    у := 5*х*х -7;

    st := st+ FloatToStr(x)+' ' + FloatToStr(y)+chr(13);

    x :=x + dx;

    у := 5*х*х -7;

    st := st+ FloatToStr(x)+' '+ FloatToStr(y)+chr(13);

    x :=x + dx;

    Label1.Caption := st;
    end;
    Из текста процедуры видно, что группа инструкций

    у := 5*х*х -7;

    st := st+ FloatToStr(x)+' '+ FloatToStr(y)+chr(13);

    x :=x + dx;

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

    Воспользовавшись инструкцией for, приведенную процедуру можно переписать следующим образом:

    procedure TForm1.ButtonlClick(Sender: TObject);
    var

    у: real; // значение функции

    x: real; // аргумент функции

    dx: real; // приращение аргумента

    st: string; // изображение таблицы

    i : integer; // счетчик циклов

    begin

    st:=''; x := -1; dx := 0.5;
    for i:=l to 5 do begin

    у := 5*x*x -7;

    st := st+ FloatToStr(x)+' '+ FloatToStr(y)+chr(13); x :=x + dx; end;

    Label1.Caption := st;
    end;

    Инструкция goto

    Инструкция goto

    Инструкции if и case используются для перехода к последовательности инструкций программы в зависимости от некоторого условия. Поэтому их иногда называют инструкциями условного перехода. Помимо этих инструкций управления ходом выполнения программы существует еще одна — инструкция безусловного перехода goto.

    В общем виде инструкция goto записывается следующим образом:

    goto Метка

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

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

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

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



    Инструкция if

    Инструкция if

    Инструкция if позволяет выбрать один из двух возможных вариантов развития программы. Выбор осуществляется в зависимости от выполнения условия.

    В общем виде инструкция if записывается так:

    if условие then

    begin

    // здесь инструкции, которые надо выполнить,
    // если условие истинно.
    end
    else
    begin

    // здесь инструкции, которые надо выполнить, // если условие ложно. end;

    Обратите внимание, что перед else (после end) точка с запятой не ставится.

    Выполняется инструкция if следующим образом:

    1. Вычисляется значение условия (условие — выражение логического типа, значение которого может быть равно True или False).

    2. Если условие истинно (значение выражения условие равно True), то выполняются инструкции, следующие за словом then (между begin и end). На этом выполнение операции if заканчивается, то есть инструкции, следующие за else, не будут выполнены.

    Если условие ложно (значение выражения условие равно False), то выполняются инструкции, следующие за словом else (между begin и end).

    На Рисунок 2.2 представлен алгоритм, соответствующий инструкции if-tnen-else.



    Инструкция repeat

    Инструкция repeat

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

    В общем виде инструкция repeat записывается следующим образом:

    repeat

    // инструкции unti1 условие

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

    Инструкция repeat выполняется следующим образом:

    1. Сначала выполняются находящиеся между repeat и until инструкции тела цикла.

    2. Затем вычисляется значение выражения условие. Если условие ложно (значение выражения условие равно False), то инструкции тела цикла выполняются еще раз.

    3. Если условие истинно (значение выражения условие равно True), то выполнение цикла прекращается.

    Таким образом, инструкции цикла, находящиеся между repeat и unti1, выполняются до тех пор, пока условие ложно (значение выражения условие
    равно False).

    Алгоритм, соответствующий инструкции repeat, представлен на Рисунок 2.16.



    Инструкция while

    Инструкция while

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

    Типичными примерами использования цикла while являются вычисления с заданной точностью, поиск в массиве или в файле.

    В общем виде инструкция while записывается следующим образом:

    while условие do begin

    // здесь инструкции, которые надо выполнить несколько раз
    end

    где условие — выражение логического типа, определяющее условие выполнения инструкций цикла.

    1. Инструкция while выполняется следующим образом:

    2. Сначала вычисляется значение выражения условие.

    3. Если значение выражения условие равно False (условие не выполняется), то на этом выполнение инструкции while завершается.

    4. Если значение выражения условие равно True (условие выполняется), то выполняются расположенные между begin и end инструкции тела цикла. После этого снова проверяется выполнение условия. Если условие выполняется, то инструкции цикла выполняются еще раз. И так до тех пор, пока условие не станет ложным (False).

    Алгоритм, соответствующий инструкции while, представлен на Рисунок 2.14.

    Внимание!

    Для того чтобы инструкции цикла while, которые находятся между begin и end, были выполнены хотя бы один раз, необходимо, чтобы перед выполнением инструкции while значение выражения условие было истинно.



    Кнопка запуска редактора списка

    Рисунок 2.10. Кнопка запуска редактора списка

    Кнопка запуска редактора списка

    В открывшемся диалоговом окне String List Editor (Рисунок 2.11) нужно ввести список, набирая каждый элемент списка в отдельной строке. После ввода очередного элемента списка для перехода к новой строке необходимо нажать клавишу . После ввода последнего элемента клавишу нажимать не надо. Завершив ввод списка, следует щелкнуть на кнопке ОК.



    Компонент ListBox

    Рисунок 2.9. Компонент ListBox


    Компонент ListBox





    Компонент

    Компонент

    Назначение

    ListBoxl

    Для выбора страны, для которой надо выполнить пересчет

    Editl

    Для ввода веса в фунтах

    Label1, Label2, Label3

    Для вывода пояснительного текста о назначении полей ввода

    Label4

    Для вывода результата пересчета

    Button1

    Для активизации процедуры пересчета веса из фунтов в килограммы




    Вычисление стоимости телефонного разговора

    Листинг 2.1. Вычисление стоимости телефонного разговора

    unit Phone_u;

    interface

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    Editl: TEdit; // поле ввода длительности разговора

    Edit2: TEdit; // поле ввода номера дня недели

    Button1: TButton; // кнопка Вычислить

    Label1: TLabel;

    Label2: TLabel;

    Label3: TLabel;

    procedure ButtonlClick(Sender: TObject);
    private

    / Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    ($R *.DFM}

    procedure TForm1.Button1Click(Sender: TObject);

    const

    PAY =0.15; // цена одной минуты разговора 0.15 рубля
    DISCOUNT = 0.2; // скидка 20 процентов
    var

    Time:Real; // длительность разговора
    Day:integer; // день недели
    Summa:real; // стоимость разговора
    begin

    // получить исходные данные
    Time:=StrToFloat(Editl.Text) ;

    Day:=StrToInt(Edit2.Text);


    // Вычислить стоимость разговора

    Summa:= PAY*Time;

    // Если день суббота или воскресенье, то уменьшить

    // стоимость на величину скидки

    if (Day = 6) OR (Day = 7)

    then Surama:=Summa*(1 - DISCOUNT);


    // вывод результата вычисления

    label3.caption:='K оплате '
    + FloatToStr(Summa) + 'руб.'; end;

    end.

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

    Рост(см)- 100.

    Реальный вес может отличаться от оптимального: вес может быть меньше оптимального, равняться ему или превышать оптимальное значение.

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



    Контроль веса

    Листинг 2.2.Контроль веса

    unit wtest_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm) Label1: TLabel;
    Label2: TLabel;
    Edit1: TEdit; // поле ввода веса

    Edit2: TEdit; // поле ввода роста
    Button1: TButton; // кнопка Вычислить

    Label3: TLabel; // поле вывода сообщения —результата работы
    // программы

    procedure ButtonlClick(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    ($R *.DFM}

    procedure TForml.ButtonlClick(Sender: TObject);

    var

    w:real; { вес } h:real; { рост } opt:real;
    { оптимальный вес }
    d:real;
    { отклонение от оптимального веса }
    begin

    w:=StrToFloat(Editl.text);

    h:=StrToInt(Edit2.Text);

    opt:=h-100;
    if w=opt then

    Label3.caption:='Bu в хорошей форме!'
    else

    if w < opt then

    begin

    d:=opt-w;

    Labels.caption:='Вам надо поправиться, на '

    + FloatToStr(d)+ 'кг.';
    end
    else

    begin

    d:=w-opt;

    Labels.caption:='Haдo немного похудеть, на '

    + FloatTostr(d)+ ' кг.';
    end;
    end;

    end.

    В приведенном примере множественный выбор реализован при помощи

    двух инструкций if, одна из которых "вложена" в другую.

    Пересчет веса из фунтов в килограммы

    Листинг 2.3. Пересчет веса из фунтов в килограммы

    unit Unit1;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    Label2: TLabel;

    Editl: TEdit; // поле ввода веса в фунтах

    Button1: TButton; // кнопка Вычислить

    Label1: TLabel;

    LabelS: TLabel;

    ListBox1: TListBox; // список стран

    Label4: TLabel; // поле вывода рез-та — веса в килограммах

    procedure FqrmCreate(Sender: TObject);


    procedure ButtonlClick(Sender: TObject);
    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForml;

    implementation

    {$R *.DFM}

    procedure TForml.FormCreate(Sender: TObject);

    begin

    {

    ListBox1.items.add('Россия');


    ListBox1.items.add('Австрия');


    ListBox1.iterns.add('Англия');


    ListBox1.items.add('Германия');


    ListBox1.iterns.add ('Дания');


    ListBoxl.iterns.add('Исландия');


    ListBox1.iterns.add ('Италия');


    ListBox1.items.add ('Нидерланды');
    }

    ListBox1.itemindex:=0; end;

    procedure TForm1.ButtonlClick(Sender: TObject);

    var

    funt:real; // вес в фунтах
    kg:real; // вес в килограммах
    k:real; // коэффициент пересчета
    begin

    case ListBoxl.Itemindex of
    0: k:=0.4095; // Россия
    1: k:=0.453592; // Англия
    2:k:=0.56001; // Австрия

    3..5,7:k:=0.5; // Германия, Дания, Исландия, Нидерланды
    6: k:=0.31762; // Италия
    end;

    funt:=StrToFloat(Editl.Text);

    kg:=k*funt;
    label4.caption:=Editl.Text

    + ' ф. — это '

    + FloatToStrF(kg,ffFixed, 6,3) + 'кг.';
    end;

    end.

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

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

    Например, в зависимости от числового значения поясняющий текст к денежной величине может быть: "рубль", "рублей" или "рубля" (123 рубля, 120 рублей, 121 рубль). Очевидно, что окончание поясняющего слова определяется последней цифрой числа, что отражено в табл. 2.8.



    Формирование поясняющего текста

    Листинг 2.4. Формирование поясняющего текста

    unit. rub_l; interface

    uses

    Windows, Messages, SysUtils,
    Variants, Classes, Graphics, Controls, Forms,

    Dialogs, StdCtrls;

    type

    TForm1 = class(TForm) Label1: TLabel;
    Editl: TEdit; Label2: TLabel;
    procedure EditlKeyPress(Sender: TObject; var Key: Char);


    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    {$R *.dfm}

    // нажатие клавиши

    procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char) var

    n : integer; // число

    r : integer; // остаток от деления n на 10
    text: string[10]; // формируемый поясняющий текст
    begin

    if Key = chr(VK_RETURN) then
    begin

    n := StrToInt(Editl.Text);
    if n >
    100

    then n:=n mod 100;
    if (n >
    = 11) and (n <= 14) then


    text:=' рублей' else begin

    r:= n mod 10; case r of

    1: text:=' рубль'; 2 .. 4: text:=' рубля';
    else text:=' рублей';
    end;
    end;

    Label2.Caption := IntToStr(n)+ text; end;

    end;
    end.

    Рассмотрим фрагмент программы (листинг 2.5), которая вычисляет дату следующего дня, используя сегодняшнюю дату, представленную тремя переменными: day (день), month (месяц) и year (год).

    Сначала с помощью инструкции сазе проверяется, является ли текущий день последним днем месяца. Если текущий месяц — февраль и если текущее число — 28, то дополнительно выполняется проверка, является ли год високосным. Для этого вычисляется остаток от деления года на 4. Если остаток равен нулю, то год високосный, и число 28 не является последним днем месяца.

    Если выясняется, что текущий день — последний день месяца, то следующее число — первое. Затем проверяется, не является ли текущий месяц декабрем. Если нет, то увеличивается номер месяца, а если да, то увеличивается номер года, а номеру месяца присваивается значение 1.



    Вычисление даты следующего дня (фрагмент)

    Листинг 2.5. Вычисление даты следующего дня (фрагмент)

    // вычисление даты следующего дня
    var

    day: integer; // день

    month: integer; // месяц

    year: integer; // гОД

    last:boolean; // если день — последний день месяца,

    // то last = True

    r:integer; // если год не високосный, то остаток
    // от деления year на 4 не равен нулю

    begin

    { переменные day, month и year содержат сегодняшнюю дату }

    last := False; // пусть день — не последний день месяца
    case month of 4,6,9,11:
    if day = 30 then last:= True; 2:
    if day = 28 then begin

    r:= year mod 4; if r <>
    0 then last:= True;
    end;

    else: if day=31 then last:= True;
    end; if last then

    begin // последний день месяца day:= 1;
    if month =12 then

    begin // последний месяц
    month:= 1;
    year:= year + 1;
    end

    else month:= month + 1;
    end
    else day:= day + 1;

    // переменные day, month и year // содержат завтрашнюю дату
    end;

    Вычисление числа я

    Листинг 2. 6. Вычисление числа я

    unit pi_; interface

    uses

    Windows, Messages, SysUtils, Classes, Graphics,
    Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    Edit1: TEdit; // точность вычисления

    Button1: TButton; // кнопка Вычислить

    Label1: TLabel;

    Label2: TLabel; // поле вывода результата

    procedure ButtonlClick(Sender: TObject);
    private

    { Private declarations }
    public

    { Public declarations )
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.Button1Click(Sender: TObject);

    var

    pi:real; // вычисляемое значение ПИ
    t:real; // точность вычисления
    n:integer; // номер члена ряда
    elem:real; // значение члена ряда
    begin

    pi := 0;
    n := 1;

    t := StrToFloat(editl.text) ;
    elem := 1; // чтобы начать цикл
    while elem >
    = t do

    begin

    elem := 1 / (2*n - 1) ; if n MOD 2=0

    then pi := pi — elem else pi := pi + elem; n := n + 1;
    end;

    pi: = pi * 4; labell.caption:= 'ПИ равно '+ FloatToStr(pi) + #13

    + 'Просуммировано '+IntTostr(n)+' членов ряда.'; end;

    end.

    Простое число

    Листинг 2.7. Простое число

    unit simple_;

    interface

    uses

    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

    StdCtrls;
    type

    TForm1 = class(TForm)

    Button1: TButton; // кнопка Проверить

    Label1: TLabel;

    Edit1: TEdit; // поле ввода числа

    Label2: TLabe1; // поле вывода результата

    procedure ButtonlClickfSender: TObject);
    private

    { Private declarations }
    public

    { Public declarations }

    end;
    var

    Form1: TForm1;
    implementation

    {$R *.DFM}

    procedure TForm1.ButtonlClick(Sender: TObject) ;
    var

    n: integer; // проверяемое число d: integer; // делитель

    r: integer; // остаток от деления п на d
    begin

    n:=StrToInt(Editl.text);


    d := 2; // сначала будем делить на два

    repeat

    r := n mod d;

    if r <>
    0 // n не разделилось нацело на d

    then d := d + 1;

    until r = 0; // найдено число, на которое п разделилось без остатка
    label2.caption:=Edit1.text;
    if d = n

    then Iabel2.caption:=label2.caption + ' — простое число.'
    else label2.caption:=label2.caption + ' — обычное число.';
    end;
    end.

    Простое число (использование инструкции goto)

    Листинг 2.8. Простое число (использование инструкции goto)

    procedure TForm1.Button1Click(Sender: TObject);

    label // раздел объявления меток

    bye; var

    n: integer; // проверяемое число
    d: integer; // делитель
    r: integer; // остаток от деления п на d
    begin

    n:=StrToInt(Editl.text);

    if n <= 0 then begin

    MessageDlg('Число должно быть больше нуля.',

    mtError, [mbOk] , 0) ; Editl.text:= ";
    goto bye;
    end;

    // введено положительное число
    d:= 2; // сначала будем делить на два
    repeat

    r:= n mod d;

    if r <>
    0 // n не разделилось нацело на d

    then d:= d + 1;
    unti1 r = 0;

    label2.caption:=Editl.text;
    if d = n

    then label2.caption:=label2.caption

    + ' — простое число.'

    else label2.caption:=label2.caption

    +' — обычное число.';
    bye:
    end;

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

    Окно программы Контроль веса

    Рисунок 2.5. Окно программы Контроль веса

    Окно программы Контроль веса

    Алгоритм программы Контроль веса изображен на Рисунок 2.6.

    Как и в предыдущей программе, вычисления выполняются при щелчке на кнопке Вычислить (ее имя Buttoni). В листинге 2.2 приведен текст программы.



    Редактор списка

    Рисунок 2.11. Редактор списка

    Редактор списка

    В табл. 2.6 перечислены компоненты формы приложения, а в табл. 2.7 приведены значения свойств компонентов.



    Операторы сравнения

    Таблица 2.1. Операторы сравнения

    Оператор

    Описание

    Результат сравнения

    >

    Больше

    True, если первый операнд больше второго, иначе False

    <

    Меньше

    True, если первый операнд меньше второго, иначе False

    =

    Равно

    True, если первый операнд равен второму, иначе

    False

    Оператор

    Описание

    Результат сравнения

    <>

    Не равно

    True, если первый операнд не равен второму, иначе False

    >=

    Больше или равно

    True, если первый операнд больше или равен второму, иначе False

    <=

    Меньше или равно

    True, если первый операнд меньше или равен второму, иначе False

    Ниже приведены примеры условий:

    Summa < 1000 Score >= HBound Sim = Chr(13)

    В первом примере операндами условия является переменная и константа. Значение этого условия зависит от значения переменной Summa. Условие будет верным и, следовательно, иметь значение True, если значение переменной Summa меньше, чем 1000. Если значение переменной Summa больше или равно юоо, то значение этого условия будет False.

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

    В третьем примере в качестве второго операнда используется функция. Значение этого условия будет True, если в переменной Sim находится символьный код клавиши , равный 13.

    При записи условий следует обратить особое внимание на то, что операнды условия должны быть одного типа или, если тип операндов разный, то тип одного из операндов может быть приведен к типу другого операнда. Например, если переменная Key объявлена как integer, то условие

    Key = Chr(13)

    синтаксически неверное, т. к. значение возвращаемое функцией Chr имеет тип char (символьный).

    Во время трансляции программы при обнаружении неверного условия компилятор выводит сообщение: incompatible types (несовместимые типы).

    Из простых условий при помощи логических операторов: and — "логическое И", or -- "логическое ИЛИ" и not - "отрицание" можно строить сложные условия.

    В общем виде сложное условие записывается следующим образом:

    условие1 оператор условие2

    где:

  • условие1 и условие2 — простые условия (выражения логического типа);
  • оператор — оператор and или or.
  • Например:

    (ch >= '0') and (ch <= '9')

    (day = 7) or (day = 6)

    (Forml.Editl.Text <> ' ' ) or (Forml.Edit2.Text <> '' )

    Forml.CheckBoxl.Checked and (Forml.Editl.Text <> '' )

    Результат выполнения логических операторов and, or и not представлен в табл. 2.2.



    Выполнение логических операций

    Таблица 2.2. Выполнение логических операций

    Op1

    Op2

    Opt and Op2

    Op1 or Op2

    not Op1

    False

    False

    False

    False

    True

    False

    True

    False

    True

    True

    True

    False

    False

    True

    False

    True

    True

    True

    True

    False

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

    Например, пусть условие предоставления скидки сформулировано следующим образом: "Скидка предоставляется, если сумма покупки превышает 100 руб. и день покупки — воскресенье", Если день недели обозначен как переменная Day целого типа, и равенство ее значения семи соответствует воскресенью, то условие предоставления скидки можно записать:

    (Summa > 100) and (Day = 7)

    Если условие предоставления скидки дополнить тем, что скидка предоставляется в любой день, если сумма покупки превышает 500 руб., то условие можно записать:

    ((Summa > 100) and (Day =7)) or (Summa > 500)

    Компоненты формы приложения Стоимость разговора

    Таблица 2.3. Компоненты формы приложения Стоимость разговора

    Компонент

    Назначение

    Edit1
    Edit2
    Label1, Label

    Для ввода длительности разговора в минутах
    Для ввода номера дня недели 2
    Для вывода пояснительного текста о назначении полей ввода

    Компонент

    Назначение

    Label3
    Button1

    Для вывода результата вычисления — стоимости разговора
    Для активизации процедуры вычисления стоимости разговора


    Примечание

    В таблицах, содержащих описание значений свойств компонентов формы, указывается имя компонента и через точку — имя свойства. Например, строка таблицы Form1 . Caption Стоимость разговора обозначает, что во время создания формы приложения свойству Caption формы приложения надо присвоить указанное значение — текст "Стоимость разговора".



    Значения свойств компонентов

    Таблица 2.4. Значения свойств компонентов

    Свойство

    Значение

    Form1 . Caption

    Стоимость разговора

    Edit1.Text



    Edit2.Text



    Label1 .Caption

    Длительность (мин.)

    Label2 .Caption

    Номер дня недели

    Label3 .Caption



    Button1 . Caption

    Вычислить

    Программа производит вычисления в результате щелчка на командной кнопке Вычислить. При этом возникает событие onclick, которое обрабатывается процедурой TForm1.Button1Click.



    Свойства компонента ListBox

    Таблица 2.5. Свойства компонента ListBox

    Свойство

    Определяет

    Name

    Имя компонента. В программе используется для доступа к свойствам компонента

    Items

    Элементы списка

    Itemindex

    Номер выбранного элемента списка. Номер первого элемента списка равен нулю

    Left

    Расстояние от левой границы списка до левой границы формы

    Top

    Расстояние от верхней границы списка до верхней границы формы

    Height

    Высоту поля списка

    Width

    Ширину поля списка

    Font

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

    Parent-Font

    Признак наследования свойств шрифта родительской формы

    Наибольший интерес представляют свойства Items и Itemindex. Свойство items содержит элементы списка.

    Свойство itemindex задает номер выбранного элемента списка. Если ни один из элементов не выбран, то значение свойства равно минус единице.

    Список может быть сформирован во время создания формы или во время работы программы.

    Для формирования списка во время создания формы надо в окне Object Inspector выбрать свойство items и щелкнуть на кнопке запуска редактора списка строк (Рисунок 2.10).



    Компоненты формы

    Таблица 2.6. Компоненты формы



    Значения свойств компонентов

    Таблица 2.7. Значения свойств компонентов

    Свойство

    Значение

    Form1 .Caption

    Пример использования case

    Editl. Text



    Label1 . Caption

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

    Label2 .Caption

    Страна

    Label3 . Caption

    Фунтов

    Button1 . Caption

    Вычислить

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

    В листинге 2.3 приведен текст программы пересчета веса из фунтов в килограммы.



    Зависимость окончания

    Таблица 2.8. Зависимость окончания текста от последней цифры числа

    Цифра

    Поясняющий текст

    0, 5, 6, 7, 8, 9

    Рублей

    1

    Рубль

    2,3,4

    Рубля

    Приведенное в таблице правило имеет исключение для чисел, оканчивающихся на 11, 12, 13, 14. Для них поясняющий текст должен быть "рублей".

    Диалоговое окно программы приведено на Рисунок 2.12, а текст — в листинге 2.4. Поясняющий текст формирует процедура обработки события onKeyPress.



    Условие

    Условие

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

  • Величина сопротивления равна нулю?
  • Ответ правильный?
  • Сумма покупки больше 300 рублей?
  • В программе условие — это выражение логического типа (Boolean), которое может принимать одно из двух значений: True (истина) или False (ложь).



    Выбор

    Выбор

    Выбор в точке разветвления алгоритма очередного шага программы может быть реализован при помощи инструкций if и case. Инструкция if позволяет выбрать один из двух возможных вариантов, инструкция case — один из нескольких.

    Основы языка Delphi

    Форма приложения во время работы

    Рисунок 3.2. Форма приложения во время работы


    Форма приложения во время работы





    Форма приложения во время разработки

    Рисунок 3.1. Форма приложения во время разработки


    Форма приложения во время разработки





    Функция length

    Функция length

    Функция length возвращает длину строки. У этой функции один параметр — выражение строкового типа. Значением функции length (целое число) является количество символов, из которых состоит строка.

    Например, в результате выполнения инструкций

    n:=length('Иванов');

    m:=length(' Невский проспект ');

    значение переменных n и m будет равно 6 и 20.


    Функция роs

    Функция роs

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

    pos (Подстрока,Строка) ;

    где Подстрока — строковая константа или переменная, которую надо найти в строковой константе или переменной строка.

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

    р := pos('Пе','Санкт-Петербург');

    значение переменной р будет равно 7. Если в строке нет искомой подстроки, то значение функции роз будет равно нулю.

    Ниже приведена инструкция while, в результате выполнения которой удаляются начальные пробелы из строки st.

    while(pos(' ',st) = 1) and(length(st) > 0) do delete (st,1,1);

    Пробелы удаляет инструкция delete (st, i, i), которая выполняется в цикле до тех пор, пока первым символом строки является пробел (в этом случае значение роs (' ',st) равно единице). Необходимость проверки условия length (st) > 0 объясняется возможностью того, что введенная строка состоит только из пробелов.

    Функция сору

    Функция сору

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

    сору( Строка, р, п ) где:

    строка — выражение строкового типа, содержащее строку, фрагмент которой надо получить;

  • р — номер первого символа, с которого начинается выделяемая подстрока;
  • n — длина выделяемой подстроки. Например, в результате выполнения инструкций
  • st:= 'Инженер Иванов'; fam:=copy(st, 9, 6) ;

    значением переменной fam будет строка 'Иванов1.

    Компьютер может обрабатывать не только

    Глава 3. Символы и строки

    Компьютер может обрабатывать не только числовую информацию, но и символьную. Язык Delphi оперирует с символьной информацией, которая может быть представлена как отдельными символами, так и строками (по-cледовательностью символов).



    символов

    Листинг 3.1.

    Операции со строками

    Операции со строками

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

    Процедура delete

    Процедура delete

    Процедура delete позволяет удалить часть строки. В общем виде обращение к этой процедуре выглядит так:

    delete(Строка, р, п)

    где:

  • Строка — переменная или константа строкового типа;
  • р — номер символа, с которого начинается удаляемая подстрока;
  • п — длина удаляемой подстроки.
  • Например, в результате выполнения инструкций

    p:='Город Санкт-Петербург';
    delete(s,7,6);

    значением переменной s будет строка ' город Петербург'.


    Символы

    Символы

    Для хранения и обработки символов используются переменные типа Ansichar и wideChar. Тип Ansichar представляет собой набор ANSI-символов, з котором каждый символ кодируется восьмиразрядным двоичным числом (байтом). Тип wideChar представляет собой набор символов в кодировке Unicode, в которой каждый символ кодируется двумя байтами.

    Для обеспечения совместимости с предыдущими версиями поддерживается тип Char, эквивалентный AnsiChar.

    Значением переменной символьного типа может быть любой отображаемый символ:

  • буква русского или латинского алфавитов;
  • цифра;
  • знак препинания;
  • И специальный символ, например, "новая строка".

    Переменная символьного типа должна быть объявлена в разделе объявления переменных. Инструкция объявления символьной переменной в общем виде выглядит так:

    Имя: char;

    где:

  • имя — имя переменной символьного типа;
  • char — ключевое слово обозначения символьного типа.
  • Примеры:

    otv: char; ch: char;

    Как и любая переменная программы, переменная типа char может получить значение в результате выполнения инструкции присваивания. Если переменная типа char получает значение в результате выполнения операции присваивания, то справа от знака := должно стоять выражение типа char, например, переменная типа char или символьная константа — символ, заключенный в кавычки.

    В результате выполнения инструкций c1 := '*';

    с2 := c1;

    переменная c1 получает значение присваиванием значения константы, а переменная с2 — присваиванием значения переменной cl (предполагается, что переменные c1 и с2 являются переменными символьного типа).

    Переменную типа char можно сравнить с другой переменной типа char или с символьной константой. Сравнение основано на том, что каждому символу поставлено в соответствие число (см. приложение 2), причем символу 'о' соответствует число меньшее, чем символу У, символу 'А' — меньшее, чем 'в', символу V — меньшее, чем а. Таким образом, можно записать:

    '0'<'1'<..<'9'<..<'A'<'B'<..<'Z'<'a'<'b'<..<'z'

    Символам русского алфавита соответствуют числа большие, чем символам латинского алфавита, при этом справедливо следующее:

    'А'<'Б'<'В'<..<'Ю'<'Я'<'а'<'б'<'в'<...<'э'<'ю'<'я'

    В тексте программы вместо символа можно указать его код, поставив перед числом оператор #. Например, вместо константы 'в' можно записать #193. Такой способ записи, как правило, используют для записи служебных символов или символов, которые во время набора программы нельзя ввести с клавиатуры. К примеру, часто используемый при записи сообщений символ "новая строка" записывается так: #13.

    В программах обработки символьной информации часто используют функции chr и Ord. Значением функции chr является символ, код которого указан в качестве параметра. Например, в результате выполнения инструкции c:=chr(32) переменной с будет присвоено значение пробел. Функция ord позволяет определить код символа, который передается ей в качестве параметра. Например, в результате выполнения инструкции k:=ord('*') переменная k будет содержать число 42 — код символа *.

    Программа, текст которой приведен в листинге 3.1, выводит таблицу кодировки букв русского алфавита. Вид окна программы представлен на Рисунок 3.1.

    Основную работу выполняет процедура обработки события OnActivate, которая формирует и выводит в поле метки (Label1) таблицу. Событие OnActivate происходит при активизации формы приложения, и поэтому процедура TForm1.FormActivate выполняется автоматически, сразу после появления формы на экране.



    Строки

    Строки

    Строки могут быть представлены следующими типами: shortstring, Longstring и widestring. Различаются эти типы предельно допустимой длиной строки, способом выделения памяти для переменных и методом кодировки символов.

    Переменной типа shortstring память выделяется статически, т. е. до начала выполнения программы, и количество символов такой строки не может превышать 255. Переменным типа Longstring и widestring память выделяется динамически — во время работы программы, поэтому длина таких строк практически не ограничена.

    Помимо перечисленных выше типов можно применять универсальный cтроковый тип String. Тип String эквивалентен типу Shortstring.

    Переменная строкового типа должна быть объявлена в разделе объявления переменных. Инструкция объявления в общем виде выглядит так:

    Имя: String;

    или

    Имя: String [длина]

    где:

  • имя — имя переменной;
  • string — ключевое слово обозначения строкового типа;
  • длина — константа целого типа, которая задает максимально допустимую длину строки.
  • Пример объявления переменных строкового типа:

    name: string[30];

    buff: string;

    Если в объявлении строковой переменной длина строки не указана, то ее длина задается равной 255 символам, т. е. объявления

    stroka: string [255]; stroka: string;

    эквивалентны.

    В тексте программы последовательность символов, являющаяся строкой (строковой константой), заключается в одинарные кавычки. Например, чтобы присвоить строковой переменной parol значение, нужно записать:

    parol:= 'Большой секрет';

    или

    parol:= '2001';

    Следует обратить внимание, что инструкция parol:=2001; неверная, т.к. тип константы не соответствует типу переменной. Во время компиляции этой инструкции будет выведено сообщение: incompatible types: 'Char' and 'Integer' (типы Char и Integer несовместимы).

    Используя операции =, <, >, <=, >= и о, переменную типа string можно сравнить с другой переменной типа string или со строковой константой. Строки сравниваются посимвольно, начиная с первого символа. Если все символы сравниваемых строк одинаковые, то такие строки считаются равными. Если в одинаковых позициях строк находятся разные символы, большей считается та строка, у которой в этой позиции находится символ с большим кодом. В табл. 3.1 приведены примеры сравнения строк.



    Сравнение строк

    Таблица 3.1. Сравнение строк

    Строка 1

    Строка 2

    Результат сравнения

    Иванов

    Иванов

    Строки равны

    Васильев

    Васильев

    Строка 1 больше строки 2

    Алексеев

    Петров

    Строка 1 меньше строки 2

    Иванова

    Иванов

    Строка 1 больше строки 2

    Кроме операции сравнения, к строковым переменным и константам можно применить операцию сложения, в результате выполнения которой получается новая строка. Например, в результате выполнения инструкций

    f irst__name: ='Иван' ;

    last_name:='Иванов';

    ful_name:=first_name+last_name;

    переменная fui_name получит значение 'Иван Иванов'.

    Таблица символов содержит только

    Таблица символов содержит только один компонент -поле метки (Label1l). Для того чтобы колонки таблицы имели одинаковую ширину, свойству Label1.Font.Name следует присвоить имя шрифта, у которого все символы имеют одинаковую ширину, например, courier New cyr.

    Вид окна приложения во время работы приведен на Рисунок 3.2.

    Таблица символов unit tablsim_;

    interface

    uses

    Windows, Messages, SysUtils, Classes, Graphics,
    Controls, Forms, Dialogs, StdCtrls;
    type

    TForm1 = class(TForm)

    Label1: TLabe1;

    procedure FormActivate(Sender: TObject); private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.FormActivate(Sender: TObject);
    var

    st:string; // таблица формируется как строка символов
    dec: byte; // код символа

    i,j:integer; // номер строки и колонки таблицы
    begin

    st:='';

    dec:=192;

    for i:=0 to 15 do // шестнадцать строк

    begin

    dec:=i + 192;

    for j:=1 to 4 do // четыре колонки

    begin

    st:=st+chr(dec)+'-'+IntToStr(dec)+' '; dec:=dec + 16;
    end;

    st:=st + #13; // переход к новой строке экрана
    end;

    Label1.caption:=st;
    end;

    end.

    Форма приложения

    Основы языка Delphi

    DOSокно в котором работает консольное приложение

    Рисунок 4.2. DOS-окно, в котором работает консольное приложение


    DOSокно в котором работает консольное приложение




    Хотя данная книга посвящена программированию

    Глава 4. Консольное приложение

    Хотя данная книга посвящена программированию в Windows, нельзя обойти вниманием так называемые консольные приложения. Консоль — это монитор и клавиатура, рассматриваемые как единое устройство. Консольное приложение — программа, предназначенная для работы в операционной системе MS-DOS (или в окне DOS), для которой устройством ввода является клавиатура, а устройством вывода — монитор, работающий в режиме отображения символьной информации (буквы, цифры и специальные знаки).

    Консольные приложения удобны как иллюстрации при рассмотрении общих вопросов программирования, когда надо сосредоточиться на сути проблемы, а также как небольшие утилиты "для внутреннего потребления".

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



    Инструкции read и readln

    Инструкции read и readln

    Инструкция read предназначена для ввода с клавиатуры значений переменных (исходных данных). В общем виде инструкция выглядит следующим образом:

    read (Переменная1, Переменная2, ... ПеременнаяN)

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

    Приведем примеры записи инструкции read:

    read(a); read(Cena,Kol);

    При выполнении инструкции read происходит следующее:

    1. Программа приостанавливает свою работу и ждет, пока на клавиатуре будут набраны нужные данные и нажата клавиша .

    2. После нажатия клавиши введенное значение присваивается переменной, имя которой указано в инструкции.

    Например, в результате выполнения инструкции
    read(Temperat);

    и ввода с клавиатуры строки 21, значением переменной Temperat будет число 21.

    Одна инструкция read позволяет получить значения нескольких переменных. При этом вводимые числа должны быть набраны в одной строке и разделены пробелами. Например, если тип переменных а, ь и с — real, то в результате выполнения инструкции read(a,b,c); и ввода с клавиатуры строки:

    4.5 23 0.17

    переменные будут иметь следующие значения:
    а = 4,5; b = 23,0; с = 0,17.

    Если в строке набрано больше чисел, чем задано переменных в инструкции read, то оставшаяся часть строки будет обработана следующей инструкцией read. Например, в результате выполнения инструкций

    read(А,В); read(С);

    и ввода с клавиатуры строки

    10 25 18

    переменные получат следующие значения: А=10, B = 25. Инструкция read (С); присвоит переменной с значение 18.

    Инструкция readln отличается от инструкции read тем, что после выделения очередного числа из введенной с клавиатуры строки и присваивания его последней переменной из списка инструкции readin, оставшаяся часть строки теряется, и следующая инструкция read или readin будет требовать нового ввода.

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

    readin(А,В); read(С);

    и вводе с клавиатуры строки

    10 25 18

    переменные получат следующие значения: А=10, B = 25. После чего программа будет ожидать ввода нового числа, чтобы присвоить его переменной с.

    Перед каждой инструкцией read или readin следует располагать инструкцию write, для того чтобы подсказать пользователю, какие данные ожидает от него программа. Например, фрагмент программы вычисления стоимости покупки может иметь вид:

    writeln('Введите исходные данные.');
    write('Цена изделия:');
    readln(Сеnа);

    write('Количество в партии:');
    readln(Kol);
    write('Скидка:');
    readln(Skidka);

    Если тип данных, вводимых с клавиатуры, не соответствует или не может быть приведен к типу переменных, имена которых указаны в инструкции read (readin), то программа аварийно завершает работу (инструкции, следующие за read, не выполняются), и на экран выводится сообщение об ошибке.

    Инструкции write и writeln

    Инструкции write и writeln

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

    Например:

    write(Summa);

    write('Результат вычислений');

    write('Корни уравнения. xl=', xl, ' х2=', х2);

    После имени переменной через двоеточие можно поместить описание (формат) поля вывода значения переменной.

    Для переменной типа Integer формат — это целое число, которое задает ширину поля вывода (количество позиций на экране).

    Например, инструкция

    write(d:5);

    показывает, что для вывода значения переменной d используется 5 позиций.

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

    Например, если значение переменной Koi типа integer равно 15, то в результате выполнения инструкции

    write('Всего изделий:', Kol:5);

    на экран будет выведено:

    Всего изделий: 15

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

    Например, пусть переменные x1 и х2 типа real имеют значения 13.25 и -0.3401, тогда в результате выполнения инструкции

    write('xl=',x1:5:2,' х2=',х2:12)

    на экран будет выведено:

    x1=13.25 х2=-3.40100Е-01

    Если ширины поля, указанной в формате, недостаточно для вывода значения переменной, то выводится число в формате с плавающей точкой и десятью цифрами после запятой (все поле вывода в этом случае занимает 17 позиций).

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

    х:=-2.73;

    write('Значение перем');

    write('енной:');

    write('х=');

    write(x:8:5);

    на экран будет выведено:

    Значение переменной: х=-2.73000

    Инструкция writein отличается от инструкции write только тем, что после вывода сообщения или значений переменных курсор переводится в начало следующей строки. Например, если значением переменной x1 является число -3.561, а значением переменной х2 — число 10.345, то результатом выполнения инструкций

    writein('Значения корней уравнения:');
    writeln('x1=',x:7:3);
    writein('х2=',х:7:3);

    на экран будет выведено:

    Значения корней уравнения:

    xl=-3.5610

    х2= 10.345

    Пересчет веса из фунтов

    Листинг 4.1. Пересчет веса из фунтов в килограммы (консольное приложение)

    program funt2kg; {$APPTYPE CONSOLE}

    // Функция Rus преобразует ANSI-строку в ASCII-строку
    function Rus(mes: string):string;

    // В ANSI русские буквы кодируются числами от 192 до 255,

    // в ASCII - от 128 до 175 (А..Яа..п) и от 224 до 239 (р..я).

    var

    i: integer; // номер обрабатываемого символа
    begin

    for i: =1 to length(mes) do case mes[i] of

    'A'-.'n' :
    mes[i] := Chr(Ord(mes[i]) - 64);
    'р'..'я' :
    mes[i] .:= Chr (Ord(mes [i] ) -16);

    end;

    rus := mes; end;

    // основная программа
    var

    f:real; // вес в фунтах

    w:real; // вес в граммах

    k:integer; // кол-во килограммов

    g:integer; // кол-во граммов

    // w = f*0,4095 = k*1000 + g
    begin

    writeln(Rus('Фунты-килограммы'));


    writeln(Rus('Введите вес в фунтах и нажмите
    '));


    write('->
    ');


    readln(f);


    w := f * 409.5; // один фунт — это 409,5 гр.
    if w >
    1000 then begin

    k:=Trunc(w/1000);
    g:=Round(w - k*1000);

    end else

    begin k:=0;

    g:=Round(w) ; end;

    write(f:4:2, Rus(' ф. -это '));

    if k >
    = 1 then write(k, Rus(' кг. '));

    writeln(g, Rus(' rp.')};

    write(Rus('Для завершения нажмите
    '));
    readln;
    end.

    Начинается текст программы строкой {$APPTYPE CONSOLE}, которая, хотя и похожа на комментарий, таковым не является, т. к. сразу за открывающей скобкой следует знак денежной единицы. Эта директива предназначена для компилятора. Следуя ее указаниям, компилятор генерирует исполняемую программу как консольное приложение.

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

    После успешной компиляции программа может быть запущена выбором из меню Run команды Run. При запуске консольного приложения на экране появляется стандартное окно DOS-программы. На Рисунок 4.2 приведен вид DOS-окна, в котором работает консольное приложение, созданное в Delphi.

    Процесс сохранения проекта консольного приложения стандартный. В результате выбора из меню File команды Save на экране появляется диалоговое окно Save Project, в котором нужно ввести имя проекта.



    Шаблон главной процедуры консольного приложения

    Рисунок 4.1. Шаблон главной процедуры консольного приложения

    Шаблон главной процедуры консольного приложения

    Начинается консольное приложение инструкцией program, за которой следует имя программы. Сначала оно совпадает с именем проекта "по умолчанию". В момент сохранения проекта оно будет автоматически заменено на имя, под которым программист сохранит проект.

    Следует обратить внимание на то, что консольное приложение создается в Windows, а выполняется как программа DOS. В DOS используется
    кодировка ASCII, а в Windows — ANSI, буквы русского алфавита в которых имеют разные коды. Это приводит к тому, что вместо сообщений на русском языке консольное приложение выводит "абракадабру". Поэтому консольные приложения должны выводить сообщения на английском, что не всегда удобно.

    Проблему вывода сообщений на русском языке консольными приложениями можно решить, разработав функцию перекодировки ANSI-строки в строку ASCII. Если эту функцию назвать RUS, то инструкция вывода сообщения на русском языке может выглядеть, например, так:

    writeln(Rus('У лукогморья дуб зеленый')).

    В листинге 4.1 приведен пример программы, которая запрашивает у пользователя вес в фунтах, пересчитывает его в килограммы и выводит результат на экран. Для вывода сообщений используется функция RUS, которая преобразует строку символов в кодировке ANSI в строку символов в кодировке ASCII.



    Создание консольного приложения

    Создание консольного приложения

    Создается консольное приложение следующим образом. Сначала нужно из меню File выбрать команду New | Other Application, затем на вкладке New появившегося диалогового окна New Items выбрать тип создаваемого приложения — Console Application. В результате этих действий на экране появится окно Projectl.dpr, в котором находится шаблон главной процедуры консольного приложения. В этом окне можно набирать инструкции программы.



    Основы языка Delphi

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

    Рисунок 5.11. Алгоритм бинарного поиска в упорядоченном по возрастанию массиве

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

    2. После того как определена часть массива, в которой может находиться искомый элемент, по формуле (niz-verh) /2+verh вычисляется новое значение sred и поиск продолжается.

    Алгоритм бинарного поиска, блок-схема которого представлена на Рисунок 5.11, заканчивает свою работу, если искомый элемент найден или если перед выполнением очередного цикла поиска обнаруживается, что значение verh больше, чем niz.

    Вид диалогового окна программы Бинарный поиск в массиве приведен на Рисунок 5.12. Поле метки Label3 используется для вывода результатов поиска и протокола поиска. Протокол поиска выводится, если установлен флажок выводить протокол. Протокол содержит значения переменных verh, niz, sred. Эта информация, выводимая во время поиска, полезна для понимания сути алгоритма.



    Алгоритм простого перебора

    Алгоритм простого перебора

    Ниже приведен текст программы поиска в массиве целых чисел. Перебор элементов массива осуществляется инструкцией repeat, в теле которой инструкция if сравнивает текущий элемент массива с образцом и присваивает переменной found значение true, если текущий элемент и образец равны.

    Цикл завершается, если в массиве обнаружен элемент, равный образцу (в этом случае значение переменной found равно true), или если проверены все элементы массива. По завершении цикла по значению переменной found можно определить, успешен поиск или нет.

    Вид диалогового окна программы Поиск в массиве приведен на Рисунок 5.9.



    Диалоговое окно приложения Ввод массива

    Рисунок 5.5. Диалоговое окно приложения Ввод массива


    Диалоговое окно приложения Ввод массива





    Диалоговое окно программы Бинарный поиск в массиве

    Рисунок 5.12. Диалоговое окно программы Бинарный поиск в массиве

    Диалоговое окно программы Бинарный поиск в массиве

    В форме приложения появился новый компонент, который до этого момента в программах не использовался, — флажок (компонент CheckBox). Значок компонента checkBox находится на вкладке Standard (Рисунок 5.13). Добавляется к форме он точно так же, как и другие компоненты. Свойства компонента CheckBox перечислены в табл. 5.5.



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

    Рисунок 5.20. Диалоговое окно программы Итоги олимпиады

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

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



    Диалоговое окно программы Поиск в массиве

    Рисунок 5.9. Диалоговое окно программы Поиск в массиве

    Диалоговое окно программы Поиск в массиве

    Щелчок на командной кнопке Поиск (Buttoni) запускает процедуру TForm1.Button1Click (ее текст приведен в листинге 5.7), которая из компонента stringGridi вводит массив, а из поля редактирования Edit2 — число (образец). Затем выполняется проверка, содержит ли массив введенное число. После завершения проверки процедура showMessage выводит сообщение о результате поиска.



    Диалоговое окно программы Сортировка массива

    Рисунок 5.16. Диалоговое окно программы Сортировка массива


    Диалоговое окно программы Сортировка массива




    Диалоговое окно программы Сортировка методом обмена

    Рисунок 5.18. Диалоговое окно программы Сортировка методом обмена

    Диалоговое окно программы Сортировка методом обмена

    На Рисунок 5.18 приведено диалоговое окно программы сортировки массива методом обмена.

    Процедура сортировки, текст которой приведен в листинге 5.10, запускается нажатием кнопки Сортировка (Button1). Значения элементов массива вводятся из ячеек компонента stringGrid1. Во время сортировки, после выполнения очередного цикла обменов элементов массива, программа выводит массив в поле метки Label2.



    Диалоговое окно программы сортировки массива простым выбором

    Рисунок 5.15. Диалоговое окно программы сортировки массива простым выбором

    Диалоговое окно программы сортировки массива простым выбором

    Процедура сортировки, текст которой приведен в листинге 5.9, запускается нажатием кнопки Сортировка (Button1). Значения элементов массива вводятся из ячеек компонента StringGrid1. После выполнения очередного цикла поиска минимального элемента в части массива процедура выводит массив в поле метки (Label2).



    Диалоговое окно программы Ввод и обработка массива

    Рисунок 5.3. Диалоговое окно программы Ввод и обработка массива

    Диалоговое окно программы Ввод и обработка массива

    Добавляется компонент stringGrid в форму точно так же, как и другие компоненты. После добавления компонента к форме нужно выполнить его настройку в соответствии с табл. 5.2. Значения свойств Height и width следует при помощи мыши установить такими, чтобы размер компонента был равен размеру строки.

    Текст программы приведен в листинге 5.2.



    Форма и диалоговое окно приложения Вывод массива

    Рисунок 5.1. Форма и диалоговое окно приложения Вывод массива


    Форма и диалоговое окно приложения Вывод массива





    это структура данных, представляющая собой

    Глава 5. Массивы

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



    Использование компонента Memo

    Использование компонента Memo

    В некоторых случаях для ввода массива можно использовать компонент Memo. Компонент Memo позволяет вводить текст, состоящий из достаточно большого количества строк, поэтому его удобно использовать для ввода символьного массива. Компонент Memo добавляется в форму обычным образом. Значок компонента находится на вкладке Standard (Рисунок 5.4).



    Использование компонента StringGrid

    Использование компонента StringGrid

    Для ввода массива удобно использовать компонент StringGrid. Значок компонента StringGrid находится на вкладке Additional (Рисунок 5.2).



    Компонент CheckBox

    Рисунок 5.13. Компонент CheckBox

    Компонент CheckBox

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



    Компонент Memo

    Рисунок 5.4. Компонент Memo

    Компонент Memo

    В табл. 5.3 перечислены некоторые свойства компонента Memo.



    Компонент StringGrid

    Рисунок 5.2. Компонент StringGrid

    Компонент StringGrid

    Компонент StringGrid представляет собой таблицу, ячейки которой содержат строки символов. В табл. 5.1 перечислены некоторые свойства компонента StringGrid.



    Инициализация и вывод массива

    Листинг 5.1. Инициализация и вывод массива

    unit outar_;

    interface

    uses

    Windows, Messages, SysUtils, Variants,
    Classes, Graphics, Controls, Forms,

    Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    Button1: TButton;

    Label1: TLabel;

    procedure ButtonlClick(Sender: TObject);

    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    ($R *.dfm}

    const

    NT = 5;

    var

    team: array[1..NT] of string[10] =

    ('Зенит','Динамо','Ротор','Спартак','СКА'

    procedure TForml.ButtonlClick(Sender: TObject);

    var

    st:string; // список команд

    i:integer; // индекс, номер элемента массива
    begin

    // формирование списка для отображения в форме

    for i:=l to NT do st := st + IntToStr(i)+ ' '
    + team[i] + #13; // вывод списка Label1.Caption := st;
    end;

    end.

    Сортировка массива методом обмена

    Листинг 5.10. Сортировка массива методом обмена

    procedure TForm1.Button1Click(Sender: TObject);


    const

    SIZE=5;

    var

    a:array[1..SIZE] of integer;

    k:integer; // текущий элемент массива

    i:integer; // индекс для ввода и вывода массива

    changed:boolean; // TRUE, если в текущем цикле были обмены

    buf:integer; // буфер для обмена элементами массива

    begin

    // ввод массива
    for i:=1 to SIZE do

    a[i] := StrToInt(StringGrid1.Cells[i-1, 0] );

    label2.caption:='';

    // сортировка массива repeat

    Changed:=FALSE; // пусть в текущем цикле нет обменов
    for k:=l to SIZE-1 do

    if a[k] >
    a[k+l] then

    begin // обменяем k-й и k+1-й элементы
    buf := a[k]; a[k] := a[k+l]; a[k+l] := buf;

    changed := TRUE;
    end;

    // вывод массива
    for i:=l to SIZE do

    Label2.caption:=label2.caption+' '+IntTostr(a[i]);

    Label2.caption:=label2.caption+#13;

    until not changed; // если не было обменов, значит
    // массив отсортирован

    Label2.caption:=label2.caption
    +#13+'Maccив отсортирован.';
    end;

    Инициализация таблицы

    Листинг 5.11. Инициализация таблицы

    procedure TForml.FormActivate(Sender: TObject);
    begin

    tabl.Cells[0,0] ='Страна';
    tabl.Cells[1,0] ='Золотых';
    tabl.Cells[2,0] ='Серебряных';
    tabl.Cells[3,0] ='Бронзовых';
    tabl.Cells[4,0] ='Bcero';
    tabl.Cells[5,0] ='Баллов';
    tabl.Cells[0,1] ='Австралия';
    tabl.Cells[0,2] ='Белоруссия';
    tabl.Cells[0,3] ='Великобритания';
    tabl.Cells[0,4] ='Германия';
    tabl.Cells[0,5] ='Италия';
    tabl.Cells[0,6] ='Китай';
    tabl.Cells[0,7] ='Корея';
    tabl.Cells[0,8] ='Куба';
    tabl.Cells[0,9] ='Нидерланды';

    tabl.Cells[0,10]— 'Россия';

    tabl.Cells[0,ll]:='США';

    tabl,Cells[0,12]:='Франция';

    tabl.Cells[0,13]:='Япония'; end;

    Программа обработки исходной таблицы (листинг 5.12) запускается щелчком мыши на командной кнопке Итоги (Buttoni).



    Обработка двумерного массива

    Листинг 5.12. Обработка двумерного массива

    procedure TForml.ButtonlClick(Sender: TObject);

    var

    c,r:integer; // номер колонки и строки таблицы

    s:integer; // всего медалей у команды

    р:integer; // очков у команды

    m:integer; // номер строки с максимальным количеством очков

    buf:array[0..5] of string; // буфер для обмена строк

    i:integer; // номер строки. Используется во время сортировки

    begin

    for r:=l to tab1.rowcount do // обработать все строки
    begin s:=0;

    // вычисляем общее кол-во медалей
    for c:=l to 3 do

    if tabl.cells[c,r] <>
    ''

    then s:=s+StrToInt(tab1.cells[c,r])
    else tabl.cells[c,r]:='0'; // вычисляем количество очков
    p:=7*StrToInt(tab1.cells[l,r])+
    6*StrToInt(tabl.cells[2, r] )
    + 5*StrToInt(tabl.cells[3,r]};

    // вывод результата

    tabl.cells[4,r]:=IntToStr(s);
    // всего медалей
    tabl.cells[5,r]:=IntToStr(p);
    // очков
    end;

    // сортировка таблицы по убыванию в соответствии

    // с количеством баллов (по содержимому 5-го столбца)

    // сортировка методом выбора

    for r:=l to tab1.rowcount-1 do

    begin

    m:=r; // максимальный элемент — в r-й строке
    for i:=r to tabl.rowcount-1 do

    if StrToInt(tabl.cells[5,i])>
    StrToInt(tabl.cells[5,m])
    then m:=i;

    if r <>
    m then


    begin // обменяем г-ю и m-ю строки таблицы
    for c:=0 to 5 do begin

    buf[с]:=tab1.Cells[c,r];

    tab1.Cells[c,r]:=tabl.Cells[c,m];

    tab1.Cells[c,m]:=buf[c];

    end;
    end;
    end;
    end;

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

    На Рисунок 5.21 приведено диалоговое окно программы после завершения процесса обработки массива.



    Ввод и обработка массива целых чисел

    Листинг 5.2. Ввод и обработка массива целых чисел

    unit getar_;

    interface

    uses

    Windows, Messages, SysUtils, Variants,
    Classes, Graphics, Controls, Forms, Dialogs, Grids, StdCtrls;

    type

    TForm1 = class(TForm)

    Label1: TLabel;

    StringGridl: TStringGrid;

    Button1: TButton;

    Label2: TLabel;

    procedure ButtonlClick(Sender: TObject);
    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForml ;

    implementation

    {$R *.dfm}

    procedure TForml.ButtonlClick(Sender: TObject);
    var

    a : array[1..5] of integer; // массив
    summ: integer; // сумма элементов

    sr: real; // среднее арифметическое

    i: integer; // индекс

    begin

    // ввод массива

    // считаем, что если ячейка пустая, то соответствующий

    // ей элемент массива равен нулю

    for i:= 1 to 5 do

    if Length(StringGridl.Cells[i-1, 0]) <>
    0

    then a[i] := StrToInt(StringGridl.Cells[i-1,0])
    else a[i] := 0;

    // обработка массива

    summ := 0;

    for i :=1 to 5 do

    summ := summ + a[i]; sr := summ / 5;

    У вывод результата Label2.Caption :=

    'Сумма элементов: ' + IntToStr(summ)
    + #13+ 'Среднее арифметическое: ' + FloatToStr(sr);

    end;
    end.

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

    Текст процедуры обработки события OnKeyPress приведен в листинге 5.3. Следует обратить внимание на свойство Col, которое во время работы программы содержит номер колонки таблицы, в которой находится курсор. Это свойство можно также использовать для перемещения курсора в нужную ячейку таблицы. Однако нужно учитывать, что колонки таблицы, впрочем, как и строки, нумеруются с нуля.



    Процедура обработки события OnKeyPress

    Листинг 5.3. Процедура обработки события OnKeyPress

    procedure TForm1.StringGridlKeyPress(Sender: TObject;
    var Key: Char);

    begin

    case Key of

    #8,'0'..'9' : ; // цифры и клавиша

    #13: // клавиша


    if StringGridl.Col < StringGridl.ColCount — 1

    then StringGridl.Col := StringGridl.Col + 1;
    else key := Chr(0);
    // остальные символы запрещены
    end;
    end;

    Если нужно ввести массив дробных чисел (a: array [1. .5] of real), то процедура обработки события OnKeyPress несколько усложнится, т. к. помимо цифр допустимыми символами являются символ-разделитель (запятая или точка — зависит от настройки Windows) и минус. С целью обеспечения некоторой дружественности программы по отношению к пользователю можно применить трюк: подменить вводимый пользователем неверный разделитель верным. Определить, какой символ-разделитель допустим в текущей настройке Windows, можно, обратившись к глобальной переменной Decimaiseparator.

    В листинге 5.4 приведен текст модуля приложения ввода и обработки массива дробных чисел. Процедура обработки события OnKeyPress обеспечивает ввод в ячейку таблицы только допустимых при записи дробного числа символов.



    Ввод и обработка массива дробных чисел

    Листинг 5.4. Ввод и обработка массива дробных чисел

    unit. getar_1; interface

    uses

    Windows, Messages, SysUtils, Variants, Classes,
    Graphics, Controls, Forms, Dialogs, Grids, StdCtrls;

    type

    TForm1= class(TForm)

    Label1: TLabel;

    StringGrid1: TStringGrid;

    Button1: TButton;

    Label2: TLabel;

    procedure Button1ClicktSender: TObject);


    procedure StringGridlKeyPress(Sender: TObject; var Key: Char);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.dfm}

    procedure TForm1.ButtonlClick(Sender: TObject);

    var

    a : array[1..5] of real; // массив
    suram: real; // сумма элементов

    sr: real; // среднее арифметическое

    i: integer; // индекс

    begin

    // ввод массива

    // считаем, что если ячейка пустая, то соответствующий

    // ей элемент массива равен нулю

    for i:= 1 to 5 do

    if Length(StringGridl.Cells[i-l,0])<>
    0

    then a[i] := StrToFloat(StringGridl.Cells[i-1, 0]) else a[i] := 0;

    // обработка массива

    summ := 0;

    for i :=1 to 5 do

    summ := summ + a[i]; sr := summ / 5;

    // вывод результата

    Label2.Caption :=

    'Сумма элементов: ' + FloatToStr(summ)
    + #13+ 'Среднее арифметическое: ' + FloatToStr(sr);
    end;

    '/ Функция обеспечивает ввод в ячейку только допустимых символов
    procedure TForm1.StringGridlKeyPress(Sender: TObject; var Key: Char);

    begin

    case Key of

    #8,'0'..'9' : ; // цифры и


    #13: // клавиша


    if StringGridl.Col < StringGridl.ColCount - 1

    then StringGridl.Col := StringGridl.Col + 1; '.',',':
    // разделитель целой и дробной частей числа
    begin

    if Key <>
    DecimalSeparator then

    Key := DecimalSeparator; // заменим разделитель

    // на допустимый

    if Pos(StringGridl.Cells[StringGridl.Col,0],

    DecimalSeparator) <>
    0
    then Key := Chr(O);
    // запрет ввода второго

    // разделителя end;

    ' -' : // минус можно ввести только первым символом,
    // т. е. когда ячейка пустая

    if Length(StringGrid1.Cells[StringGrid1.Col, 0]) <>
    0 then
    Key := Chr(0) ;

    else // остальные символы запрещены

    key := Chr(0);

    end;
    end;

    end.

    Ввод массива строк из компонента Memo

    Листинг 5.5. Ввод массива строк из компонента Memo

    unit fr_memo_; interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, Menus, StdCtrls;

    type

    TForm1 = class(TForm)

    Memo1: TMemo;

    Button1: TButton;

    Label1: TLabel;

    procedure ButtonlClick(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Forml: TForm1;

    implementation

    ($R *.DFM}

    procedure TForml .ButtonlClick(Sender: TObject);

    const

    SIZE=5; // размер массива var

    a:array[l..SIZE]of string[30]; //массив
    n: integer; // количество строк, введенных в поле Memo
    i:integer; // индекс элемента массива
    st:string;
    begin

    n:=Memo1.Lines.Count;
    if n = 0 then begin

    ShowMessage('Исходные данные не введены!');

    Exit; // выход из процедуры обработки события
    end;

    // в поле Memo есть текст
    if n >
    SIZE then begin

    ShowMessage('Количество строк превышает размер массива.');

    n:=SIZE; // будем вводить только первые SIZE строк
    end;
    for i:=1 to n do

    a[i]:=Form1.Memol.Lines[i-1]; // строки Memo пронумерованы с нуля

    // вывод массива в окно сообщения
    if n >
    0 then begin

    st:='Введенный массив:'+#13;
    for i: =1 to n do

    st:=st+IntToStr(i)+' '+ a[i]+f13; ShowMessage(st);

    end;

    end;
    end.

    Основную работу выполняет процедура TForm1.Button1Click, которая сначала проверяет, есть ли в поле Memo1 текст. Если текст есть (в этом случае значение свойства Lines.Count больше нуля), то процедура сравнивает количество введенных строк и размер массива. Если это количество превышает размер массива, то программа изменяет значение п, тем самым подготавливает ввод только первых SIZE строк.

    На Рисунок 5.6 приведен вид диалогового окна приложения Ввод массива. После щелчка на командной кнопке Ввод появляется окно (Рисунок 5.7), которое содержит значения элементов массива, полученные из Memo-поля.



    Поиск минимального элемента массива

    Листинг 5.6. Поиск минимального элемента массива

    unit lookmin_;

    interface

    Windows, Messages, SysUtils, Classes, Graphics,
    Controls, Forms, Dialogs, StdCtrls, Grids;

    type

    TForm1 = class(TForm)

    Label1: TLabel;

    Button1: TButton;

    Label2: TLabel;

    StringGridl: TStringGrid;

    procedure ButtonlClick(Sender: TObject);
    private

    { Private declarations )
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.ButtonlClick(Sender: TObject);


    const

    SIZE=5;

    var

    a:array[l..SIZE]of integer; // массив целых

    min:integer; // номер минимального элемента массива

    i:integer; // номер элемента, сравниваемого с минимальным

    begin

    // ввод массива for i:=1 to SIZE do

    a[i]:=StrToInt(StringGridl.Cells[i-1,0]);


    // поиск минимального элемента

    min:=1; // пусть первый элемент минимальный

    for i:=2 to SIZE do

    if a[i]< a[min]then min:=i;

    // вывод результата

    label2.caption:='Минимальный элемент массива:'
    +IntToStr(a[min] +#13+'Номер элемента:'+ IntToStr(min);


    end;

    end.

    На Рисунок 5.8 приведен вид диалогового окна приложения после щелчка на кнопке Поиск.



    Поиск в массиве

    Листинг 5.7. Поиск в массиве

    unit s_found_; interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs,

    StdCtrls, Grids;

    type

    TForm1 = class(TForm)

    Label1: TLabel;

    Label2: TLabel;

    Button1: TButton;

    Edit2: TEdit;

    StringGridi: TStringGrid;

    procedure ButtonlClick(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations )
    end;

    var

    Form1: TForm1 ;

    implementation

    {$R *.DFM}

    { поиск в массиве перебором }

    procedure TForml.ButtonlClick(Sender: TObject);


    const

    SIZE=5; var

    a: array[1..SIZE] of integer; //массив

    obr: integer; // образец для поиска

    found: boolean; // TRUE — совпадение образца с элементом

    // массива

    i: integer; // индекс элемента массива

    begin

    // ввод массива for i:=l to SIZE do

    a[i] := StrToInt(StringGridl.Cells[i-1,0]);


    // ввод образца для поиска
    obr := StrToInt(edit2.text);


    // поиск

    found := FALSE; // пусть нужного элемента в массиве нет

    i:= 1;

    repeat

    if a[i] = obr

    then found := TRUE else i := i+1;
    until (i >
    SIZE) or (found = TRUE);


    if found

    then ShowMessage('Совпадение с элементом номер '

    +IntToStr(i)+#13+'Поиск успешен.')
    else ShowMessage('Совпадений с образцом нет.');

    end;

    end.

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

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

    Бинарный поиск в массиве

    Листинг 5.8. Бинарный поиск в массиве

    unit b_found_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls, Grids;

    type

    TForm1 = class(TForm)

    Label1: TLabel;

    Label2: TLabel;

    Button1: TButton;

    Label3: TLabel;

    CheckBox1: TCheckBox;

    StringGrid1: TStringGrid;

    Editl: TEdit;

    procedure ButtonlClick(Sender: TObject);


    procedure StringGridlKeyPress(Sender: TObject; var Key: Char);


    procedure EditlKeyPress(Sender: TObject; var Key: Char);
    private

    {Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    { Бинарным поиск в массиве }

    procedure TForm1.Button1Click(Sender: TObject);

    const

    SIZE=10; var

    a:array[1..SIZE] of integer; { массив )

    obr:integer; { образец для поиска}

    verh:integer; { верхняя граница поиска }

    niz: integer; { нижняя граница поиска }

    sred:integer; { номер среднего элемента )

    found:boolean; { TRUE — совпадение образца с элементом массива }

    n:integer; / число сравнений с образцом }

    i:integer;

    begin

    // ввод массива и образца
    for i:=l to SIZE do

    a[i]:=StrToInt(StringGridl.Cells[i-l,0] ) ;
    obr := StrToInt(Editl.text);


    // поиск verh:=1;
    niz:=SIZE; n:=0;

    found:=FALSE; labels.caption:='';

    if CheckBoxl.State = cbChecked

    then Labels.caption: ='verh'+#9+'niz'#9'sred' #13;

    // бинарный поиск в массиве repeat

    sred:=Trunc ( (niz-verh) /2)+verh; if CheckBox1.Checked

    then Labels.caption:=label3.caption +IntToStr(yerh) + #9

    +IntToStr(niz) + #9 +IntToStr(sred) + #13; n:=n+1;

    if a[sred] = obr then found:=TRUE else

    if obr < a[sred]

    then niz:=sred-1 else verh:=sred+1;
    until (verh >
    niz) or found;

    if found

    then labels.caption:=label3.caption

    +'Совпадение с элементом номер '
    + IntToStr(sred)+#13 + 'Сравнений '
    + IntToStr(n)
    else label3.caption:=label3.caption

    +'Образец в массиве не найден.';
    end;

    // нажатие клавиши в ячейке StringGrid

    procedure TForml.StringGridlKeyPress(Sender: TObject; var Key: Char),

    begin

    if Key = #13 then // нажата клавиша


    if StringGrid1.Col < StringGridl.ColCount - 1
    then // курсор в следующую ячейку таблицы
    StringGridl.Col := StringGrid1.Col +1
    else // курсор в поле Editl, в поле ввода образца

    Editl.SetFocus;
    end;

    // нажатие клавиши в поле Editl

    procedure TForm1.Edit1KeyPress(Sender: TObject;. var Key: Char);


    begin

    if Key = #13 // нажата клавиша


    then // сделать активной командную кнопку

    Button1.SetFocus;
    end;

    end.

    Ниже приведены примеры диалоговых окон программы Бинарный поиск в массиве после выполнения поиска— с выводом протокола (Рисунок 5.14, а) и без протокола (Рисунок 5.14, б).

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



    Сортировка массива простым выбором

    Листинг 5.9. Сортировка массива простым выбором

    procedure TForm1.ButtonlClick(Sender: TObject);

    const

    SIZE=10;
    var

    a:array[1..SIZE] of integer;

    min:integer; { номер минимального элемента в части

    массива от i до верхней границы массива }

    j:integer; { номер элемента, сравниваемого с минимальным }
    buf:integer; { буфер, используемый при обмене элементов массива }
    i,k:integer;

    begin

    // ввод массива
    for i:=l to SIZE do

    a[i]:=StrToInt(StringGridl.Cells[i-1,0]) ; Iabel2.caption:='';

    for i:=l to SIZE-1 do begin

    { поиск минимального элемента в части массива от а[1] до a[SIZE]} min:=i;

    for j:=i+l to SIZE do if a[j] < a [min]

    then min:=j;

    { поменяем местами a [min] и a[i] }
    buf:=a[i]; a[i]:=a[min]; a[min]:=buf;

    { вывод массива }
    for k:=l to SIZE do

    Label2.caption:=label2.caption+' '+IntTostr(a[k]);

    Label2.caption:=label2.caption+#13; end;

    Label2.caption:=label2.caption+#13+'MaccMB отсортирован.';
    end;

    На Рисунок 5.16 приведено диалоговое окно программы после завершения процесса сортировки.



    Массив введенный из Memoполя

    Рисунок 5.7. Массив, введенный из Memo-поля


    Массив введенный из Memoполя




    Метод бинарного поиска

    Метод бинарного поиска

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

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

    Метод (алгоритм) бинарного поиска реализуется следующим образом:

    1. Сначала образец сравнивается со средним (по номеру) элементом массива (Рисунок 5.10, а).

  • Если образец равен среднему элементу, то задача решена.
  • Если образец больше среднего элемента, то это значит, что искомый элемент расположен ниже среднего элемента (между элементами с номерами sred+1 и niz), и за новое значение verb принимается sred+i, а значение niz не меняется (Рисунок 5.10, б).
  • Если образец меньше среднего элемента, то это значит, что искомый элемент расположен выше среднего элемента (между элементами с номерами verh и sred-1), и за новое значение niz принимается sred-1, а значение verh не меняется (Рисунок 5.10, в).


  • Многомерные массивы

    Многомерные массивы

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



    Объявление массива

    Объявление массива

    Массив, как и любая переменная программы, перед использованием должен быть объявлен в разделе объявления переменных. В общем виде инструкция объявления массива выглядит следующим образом:

    Имя: array [нижний_индекс. .верхний_индекс] of тип

    где:

  • имя — имя массива;
  • array — зарезервированное слово языка Delphi, обозначающее, что объявляемое имя является именем массива;
  • нижний_индекс и верхний_и"декс — целые константы, определяющие диапазон изменения индекса элементов массива и, неявно, количество элементов (размер) массива;
  • тип — тип элементов массива.
  • Примеры объявления массивов:

    temper:array[1..31] of real;
    коef:array[0. .2] of integer;
    name:array[1..30] of string[25];

    При объявлении массива удобно использовать именованные константы. Именованная константа объявляется в разделе объявления констант, который обычно располагают перед разделом объявления переменных. Начинается раздел объявления констант словом const. В инструкции объявления именованной константы указывают имя константы и ее значение, которое отделяется от имени символом "равно". Например, чтобы объявить именованную константу нв, значение которой равно 10, в раздел const надо записать инструкцию: нв=ю. После объявления именованной константы ее можно использовать в программе как обычную числовую или символьную константу. Ниже в качестве примера приведено объявление массива названий команд-участниц чемпионата по футболу, в котором используются именованные константы.

    const

    NT = 18; // число команд

    SN = 25; // предельная длина названия команды var

    team: array[1..NT] of string[SN];

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

    team [ 1] := 'Зенит';

    d := koef[l]*koef[l]-4*koef[2]*koef[1];

    ShowMessage(name[n+1]);

    temper[i] := StrToFloat(Edit1.text);

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

    Имя:array [нижний_индекс..верхний_индекс] of тип = (список);

    где список — разделенные запятыми значения элементов массива. Например:

    a: array[10] of integer = (0,0,0,0,0,0,0,0,0,0);

    Team: array[1..5] of String[10]=

    ('Зенит','Динамо','Спартак','Ротор','СКА');

    Обратите внимание, что количество элементов списка инициализации должно соответствовать размерности массива. Если это будет не так, то компилятор выведет сообщения об ошибке: Number of elements differs from declaration (количество элементов не соответствует указанному в объявлении).

    При попытке инициализировать локальный массив компилятор выводит сообщение об ошибке: Cannot initialize local variables (локальная переменная не может быть инициализирована). Локальный массив можно инициализировать только во время работы программы, например, так:

    for i := 1 to 10 do

    a[i]:= 0;

    Окно приложения Поиск минимального элемента массива

    Рисунок 5.8. Окно приложения Поиск минимального элемента массива


    Окно приложения Поиск минимального элемента массива




    Окно приложения Ввод массива

    Рисунок 5.6. Окно приложения Ввод массива


    Окно приложения Ввод массива





    Окно программы Итоги олимпиады

    Рисунок 5.21. Окно программы Итоги олимпиады


    Окно программы Итоги олимпиады




    Операции с массивами

    Операции с массивами

    Типичными операциями при работе с массивами являются:

  • вывод массива;
  • ввод массива;
  • поиск максимального или минимального элемента массива;
  • поиск заданного элемента массива;
  • сортировка массива.


  • Ошибки при использовании массивов

    Ошибки при использовании массивов

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

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

    day : array[0..6] of string[ll],

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

    day [7] := 'Воскресенье';

    будет помечена как ошибочная.

    Если для доступа к элементу массива в качестве индекса используется переменная или выражение, то возможно возникновение ошибки (исключения) времени выполнения программы. Например, если в программе объявлен массив

    tab1: array [1..N] of integer;

    то инструкция

    for i:=0 to N do tab1[i] := 5;

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

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

    При запуске рассматриваемой программы из Delphi возникает исключение, и сообщение имеет вид, приведенный на Рисунок 5.22.



    Поиск минимального (максимального) элемента массива

    Поиск минимального (максимального) элемента массива

    Задачу поиска минимального элемента массива рассмотрим на примере массива целых чисел.

    Алгоритм поиска минимального (максимального) элемента массива довольно очевиден: сначала делается предположение, что первый элемент массива является минимальным (максимальным), затем остальные элементы массива последовательно сравниваются с этим элементом. Если во время очередной проверки обнаруживается, что проверяемый элемент меньше (больше) принятого за минимальный (максимальный), то этот элемент становится минимальным (максимальным) и продолжается проверка оставшихся элементов.

    Диалоговое окно приложения поиска минимального элемента массива содержит соответствующим образом настроенный компонент stringGridi, который применяется для ввода элементов массива, два поля меток (Label1 и Labeia), использующиеся для вывода информационного сообщения и результата работы программы, и командную кнопку (Buttonl), при щелчке на которой выполняется поиск минимального элемента массива. В табл. 5.4 приведены значения свойств компонента stringGridi.



    Поиск в массиве заданного элемента

    Поиск в массиве заданного элемента

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

    Для организации поиска в массиве могут быть использованы различные алгоритмы. Наиболее простой — это алгоритм простого перебора. Поиск осуществляется последовательным сравнением элементов массива с образцом до тех пор, пока не будет найден элемент, равный образцу, или не будут проверены все элементы. Алгоритм простого перебора применяется, если элементы массива не упорядочены.


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

    Рисунок 5.19. Пример работы программы сортировки массива методом обмена

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

    На Рисунок 5.19 приведено диалоговое окно программы сортировки массива методом обмена после завершения процесса сортировки.

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

    Рисунок 5.14. Примеры работы программы бинарного поиска в массиве


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




    Процесс сортировки массива

    Рисунок 5.17. Процесс сортировки массива


    Процесс сортировки массива





    Сообщение об ошибке при обращении

    Рисунок 5.22. Сообщение об ошибке при обращении к несуществующему элементу массива (программа запущена из Delphi)

    Сообщение об ошибке при обращении

    Если программа запущена из Windows, то при попытке присвоить значение несуществующему элементу массива на экран будет выведено сообщение Range check error (ошибка контроля диапазона). В заголовке окна будет указано имя приложения, в процессе выполнения которого произошла ошибка (Рисунок 5.23).



    Рисунок 5.23. Сообщение об ошибке при обращении к несуществующему элементу массива (программа запущена из Windows)

    Сообщение об ошибке при обращении

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

    Для того чтобы программа контролировала значения индексных выражений (в этом случае Delphi добавляет в выполняемую программу инструкции, обеспечивающие этот контроль), необходимо на вкладке Compiler диалогового окна Project Options, которое открывается выбором из меню Project команды Options, установить флажок Range checking (Контроль диапазона), находящийся в группе Runtime errors (Ошибки времени выполнения) (Рисунок 5.24).

    Сортировка массива

    Сортировка массива

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

    а[1] < а[2] < .. .< a[SIZE]

    где SIZE — верхняя граница индекса массива.

    Примечание

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

    Существует много методов (алгоритмов) сортировки массивов.
    Рассмотрим два из них:

  • метод прямого выбора;
  • метод прямого обмена.


  • Сортировка методом обмена

    Сортировка методом обмена

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

    На Рисунок 5.17 цифрой 1 обозначено исходное состояние массива и перестановки на первом проходе, цифрой 2 — состояние после перестановок на первом проходе и перестановки на втором проходе, и т. д.



    Сортировка методом прямого выбора

    Сортировка методом прямого выбора

    Алгоритм сортировки массива по возрастанию методом прямого выбора может быть представлен так:

    1. Просматривая массив от первого элемента, найти минимальный элемент и поместить его на место первого элемента, а первый — на место минимального.

    2. Просматривая массив от второго элемента, найти минимальный элемент и поместить его на место второго элемента, а второй — на место минимального.

    3. И так далее до предпоследнего элемента.

    Ниже представлена программа сортировки массива целых чисел по возрастанию, диалоговое окно которой изображено на Рисунок 5.15.



    Свойство

    Свойство

    Определяет

    Name

    Имя компонента. Используется в программе для доступа к свойствам компонента

    Свойство

    Определяет

    ColCount

    Количество колонок таблицы

    RowCount

    Количество строк таблицы

    Cells

    Соответствующий таблице двумерный массив. Ячейка таблицы, находящаяся на пересечении столбца номер col и строки номер row определяется элементом cells [col, row]

    FixedCols

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

    FixedRows

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

    Options . goEditing

    Признак допустимости редактирования содержимого ячеек таблицы. True — редактирование разрешено, False — запрещено

    Options . goTab

    Разрешает (True) или запрещает (False) использование клавиши <Таb> для перемещения курсора в следующую ячейку таблицы

    Options . GoAlways-ShowEditor

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

    DefaultColWidth

    Ширину колонок таблицы

    DefaultRowHeight

    Высоту строк таблицы

    GridLineWi-dth

    Ширину линий, ограничивающих ячейки таблицы

    Left

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

    Top

    Расстояние от верхней границы поля таблицы до верхней границы формы

    Height

    Высоту поля таблицы

    Width

    Ширину поля таблицы

    Font

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

    ParentFont

    Признак наследования характеристик шрифта формы

    В качестве примера использования компонента stringGrid для ввода массива рассмотрим программу, которая вычисляет среднее арифметическое значение элементов массива. Диалоговое окно программы приведено на Рисунок 5.3. Компонент stringGrid используется для ввода массива, компоненты Label1 и Label2 — для вывода пояснительного текста и результата расчета, Buttoni — для запуска процесса расчета.



    Свойства компонента StringGrid

    Таблица 5.1. Свойства компонента StringGrid



    Значения свойств компонента StringGrid1

    Таблица 5.2. Значения свойств компонента StringGrid1

    Свойство


    Значение


    ColCount

    5

    FixedCols

    0

    RowCount

    1

    DefaultRowHeight

    24

    Height

    24

    DefaultColWidth

    64

    Width

    328

    Options . goEditing

    True

    Options . AlwaysShowEditing

    True

    Options .goTabs

    True





    Свойства компонента Memo

    Таблица 5.3. Свойства компонента Memo

    Свойство

    Определяет

    Name

    Имя компонента. Используется в программе для доступа к свойствам компонента

    Text

    Текст, находящийся в поле Memo. Рассматривается как единое целое

    Lines

    Текст, находящийся в поле Memo. Рассматривается как совокупность строк. Доступ к строке осуществляется по номеру

    Lines .Count

    Количество строк текста в поле Memo

    Left

    Расстояние от левой границы поля до левой границы формы

    Top

    Расстояние от верхней границы поля до верхней границы формы

    Height

    Высоту поля

    Width

    Ширину поля

    Font

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

    ParentFont

    Признак наследования свойств шрифта родительской формы

    При использовании компонента Memo для ввода массива значение каждого элемента массива следует вводить в отдельной строке и после ввода каждого элемента массива нажимать клавишу .

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

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

    Основной цикл процедуры ввода символьного массива из компонента Memo может выглядеть так:

    for i:=l to SIZE do

    a [ i ]:= Memol.Lines[i];

    где:

  • SIZE — именованная константа, определяющая размер массива;
  • а — массив;
  • Memol — имя Memo-компонента;
  • Lines — свойство компонента Memo, представляющее собой массив, каждый элемент которого содержит одну строку находящегося в поле Memo текста.
  • Форма программы приведена на Рисунок 5.5. Помимо поля Memo она содержит командную кнопку (Buttonl), при щелчке на которой выполняется ввод значений элементов массива из поля Memo.



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

    Таблица 5.4. Значения свойств компонента stringGrid1

    Свойство

    Значение

    ColCount

    005

    FixedCols

    000

    RowCount

    001

    DefaultRowHeight

    024

    Height

    024

    DefaultColWidth

    064

    Width

    328

    Options . goEditing

    True

    Options . AlwaysShowEditing

    True

    Options .goTabs

    True

    В листинге 5. 6 приведена процедура обработки события Onclick для командной кнопки Button1, которая вводит массив, выполняет поиск мини-мального элемента и выводит результат — номер и значение минимального элемента массива.



    Свойства компонента CheckBox

    Таблица 5.5. Свойства компонента CheckBox

    Свойство

    Определяет

    Name

    Имя компонента. Используется в программе для доступа к свойствам компонента

    Caption

    Текст, поясняющий назначение флажка

    Checked

    Состояние, внешний вид флажка: если флажок установлен (в квадратике есть "галочка"), то checked = TRUE; если флажок сброшен (нет "галочки"), то Checked=FALSE

    State

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

    cbChecked (установлен); cbGrayed (серый, неопределенное состояние); cbUnChecked (сброшен)

    AllowGrayed

    Может ли флажок быть в промежуточном состоянии: если AllowGrayed = FALSE, то флажок может быть только установленным или сброшенным;

    если AllowGrayed = TRUE, то допустимо промежуточное состояние

    Свойство

    Определяет

    Left
    Top
    Height
    Width
    Font
    ParentFont

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




    приведен текст процедуры обработки

    Таблица 5.6. Значения свойств компонента CheckBox1

    Свойство

    Значение

    Caption

    Checked

    Выводить протокол

    True

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

    При вычислении номера среднего элемента используется функция тгипс, которая округляет до ближайшего целого и преобразует к типу integer выражение, полученное в качестве аргумента. Необходимость использования тгипс объясняется тем, что выражение (niz-verh) /2 — дробного типа, переменная sred — целого, а переменной целого типа присвоить дробное значение нельзя (компилятор выдаст сообщение об ошибке).

    Обратите внимание на процедуры обработки события onKeyPress для компонентов stringGridl и Editl. Первая из них обеспечивает перемещение курсора в следующую ячейку таблицы или в поле Editl (из последней ячейки) в результате нажатия клавиши , вторая — активизирует командную кнопку Поиск также в результате нажатия клавиши .



    строки таблицы, как правило, состоят

    Таблица 5.7



    Январь

    Февраль

    Март

    ...

    Ноябрь

    Декабрь

    ВA3 2106













    ВA3 2107













    ВA3 2108













    ВA3 2109













    ВАЗ 2110













    ВАЗ 2111













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

    vaz2106: array [1..12] of integer;

    vaz2107: array [1..12] of integer;

    vaz2108: array [1..12] of integer;

    vaz2109: array [1..12] of integer;

    vaz2110: array [1..12] of integer;

    vaz2111: array [1..12] of integer;

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

    Возможно и такое представление таблицы:

    jan: array [1..6] of integer;
    feb: array [1..6] of integer;
    mar: array [1..6] of integer;

    dec: array [1..6] of integer;

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

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

    В общем виде инструкция объявления двумерного массива выглядит так:

    Имя: array[ НижняяГраница1..ВерхняяГраница1,

    НижняяГраница2..ВерхняяГраница2] of Тип

    где:

  • Имя — имя массива;
  • array — слово языка Delphi, указывающее, что объявляемый элемент данных является массивом;
  • НижняяГраница1, ВерхняяГраница1, НижпяяГраница2, ВерхняяГраница2 — целые константы, определяющие диапазон изменения индексов и, следовательно, число элементов массива;
  • Тип — тип элементов массива.
  • Табл. 5.7 может быть представлена в виде двумерного массива следующим образом:

    itog: array [1..12, 1..6] of integer

    Количество элементов двумерного массива можно вычислить по формуле:

    (ВГ1-НГ1+1) х (ВГ2-НГ2+1):

    где:

  • ВГ1 и ВГ2 — верхняя граница первого и второго индексов;
  • НГ1 и НГ2 — нижняя граница первого и второго индексов. Таким образом, массив itog состоит из 60 элементов типа integer.
  • Для того чтобы использовать элемент массива, нужно указать имя массива и индексы элемента. Первый индекс обычно соответствует номеру строки таблицы, второй — номеру колонки. Так, элемент itog [2,3] содержит число проданных в марте (третий месяц) автомобилей марки ВАЗ 2107 (данные о продаже ВАЗ 2107 находятся во второй строке таблицы).

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

    s := 0;

    for j := 1 to 12 do

    s := s + itog[2,j];

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

    s:=0;

    for i := 1 to 6 do // шесть моделей автомобилей

    for j := 1 to 12 do //12 месяцев s := s + itog[i,j];

    В приведенном фрагменте программы каждый раз, когда внутренний цикл (цикл по j) завершается, во внешнем цикле значение i увеличивается на единицу и внутренний цикл выполняется вновь. Таким образом, к текущему значению переменной s последовательно прибавляются значения элементов массива itog: itog[l,l], itog[l,2], ..., itog[l,12], itog[2,l], itog[2,2], ..., itog[2,12] и т. д.

    В качестве примера рассмотрим программу, которая обрабатывает результаты спортивных соревнований летней олимпиады в Сиднее, 2000 г. Исходные данные представлены в табл. 5.8.



    Результаты олимпиады 2000 г в Сиднее

    Таблица 5.8. Результаты олимпиады 2000 г. в Сиднее

    Страна

    Золотых

    Серебряных

    Бронзовых

    Австралия

    16

    25

    17

    Беларусь

    3

    3

    11

    Великобритания

    11

    10

    7

    Германия

    14

    17

    26

    Италия

    13

    8

    13

    Китай

    28

    16

    15

    Корея

    8

    9

    11

    Куба

    11

    11

    7

    Нидерланды

    12

    9

    4

    Россия

    32

    28

    28

    Румыния

    11

    6

    9

    США

    39

    25

    33

    Франция

    13

    14

    11

    Япония

    5

    8

    5

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

    Вид диалогового окна программы приведен на Рисунок 5.20.



    Ячейки первой зафиксированной строки таблицы

    Таблица 5.9. Значения свойства компонента StringGrid1

    Свойство

    Значение

    Name

    Tab1

    ColCount

    6

    RowCount

    14

    FixedCols

    0

    FixedRows

    1

    Options . goEditing

    TRUE

    DefaultColWidth

    65

    DefaultRowHeight

    14

    GridLineWidth

    1

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

    процедура обработки события OnActivate (ее текст приведен в листинге 5.11), которое происходит во время активизации формы приложения. Кроме того, эта процедура вписывает в первую колонку таблицы названия стран-участниц соревнований.



    Вкладка Compiler диалогового окна Project Options

    Рисунок 5.24. Вкладка Compiler диалогового окна Project Options


    Вкладка Compiler диалогового окна Project Options




    Ввод массива

    Ввод массива

    Под вводом массива понимается процесс получения от пользователя (или из файла) во время работы программы значений элементов массива.

    "Лобовое" решение задачи ввода элементов массива — для каждого элемента массива создать поле ввода. Однако если требуется ввести достаточно большой массив, то такое решение неприемлемо. Представьте форму, например, с десятью полями редактирования!

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

    StringGrid И Memo.

    Выбор среднего элемента массива при бинарном поиске

    Рисунок 5.10. Выбор среднего элемента массива при бинарном поиске


    Выбор среднего элемента массива при бинарном поиске





    Вывод массива

    Вывод массива

    Под выводом массива понимается вывод на экран монитора (в диалоговое окно) значений элементов массива.

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

    В качестве примера на Рисунок 5.1 приведено диалоговое окно приложения, которое демонстрирует инициализацию и процесс вывода значений элементов массива в поле метки. Программа выводит пронумерованный список футбольных команд. Следует обратить внимание, что для того чтобы список команд выглядел действительно как список, свойству Label1.AutoSize нужно присвоить значение False (присвойте свойству Label1.AutoSize значение True и посмотрите, как будет работать программа). Текст программы приведен в листинге 5.1.



    Основы языка Delphi

    Функция

    Функция

    Функция — это подпрограмма, т. е. последовательность инструкций, имеющая имя.

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

    В общем виде инструкция обращения к функции выглядит так:

    Переменная := Функция (Параметры) ;

    где:

  • переменная — имя переменной, которой надо присвоить значение, вычисляемое функцией;
  • Функция — имя функции, значение которой надо присвоить переменной;
  • Параметры — список формальных параметров, которые применяются для вычисления значения функции. В качестве параметров обычно используют переменные или константы.
  • Следует обратить внимание на то, что:

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


  • Использование функции

    Использование функции

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



    Использование модуля

    Использование модуля

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

    В листинге 6.9 приведен вариант программы Поездка на дачу. Процедура обработки события onKeyPress в полях ввода исходных данных обращается к функции IsFloat, которая находится в модуле my_unit.pas, поэтому в списке используемых модулей указано имя модуля my_unit.



    Использование процедуры

    Использование процедуры

    Разработанную процедуру нужно поместить в раздел implementation, перед подпрограммой, которая использует эту процедуру.

    Инструкция вызова процедуры в общем виде выглядит так:

    Имя(СписокПараметров);

    где:

    П имя — имя вызываемой процедуры;

  • списокПараметров — разделенные запятыми фактические параметры.
  • Фактическим параметром, в зависимости от описания формального параметра в объявлении процедуры, может быть переменная, выражение или константа соответствующего типа.

    Например, инструкция вызова приведенной выше процедуры решения квадратного уравнения может выглядеть следующим образом:

    SqRoot(StrToFloat(Edit1.Text),
    StrToFloat(Edit2.Text),
    StrToFloat(Edit3.Text), k1,k2,rez);

    Если в описании процедуры перед именем параметра стоит слово var, то при вызове процедуры на месте соответствующего параметра должна стоять переменная основной программы. Использование константы или выражения считается ошибкой, и компилятор в этом случае выведет сообщение: Types of actual and formal var parameters must be identical (ТИП фактического параметра должен соответствовать типу формального параметра).

    В листинге 6.6 приведена программа решения квадратного уравнения, в которой используется процедура SqRoot. Окно программы представлено на Рисунок 6.2.



    Пересчет веса из фунтов в килограммы

    Листинг 6.1. Пересчет веса из фунтов в килограммы

    unit Unit1;

    interface

    uses

    Windows, Messages, SysUtils, Variants,
    Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    Label1: TLabel; // пояснительный текст

    Edit1: TEdit; // поле ввода веса в фунтах

    Button1: TButton; // кнопка Вычислить

    Label2: TLabel; // поле вывода результата

    procedure ButtonlClick(Sender: TObject);


    procedure EditlKeyPress(Sender: TObject;
    var Key: Char);
    private

    { Private declarations } public

    { Public declarations }

    end;

    var

    Form1: TForm1 ;

    implementation

    {$R *.dfm}

    // щелчок на кнопке Вычислить

    procedure TForml.Button1Click(Sender: TObject);


    var

    f : real; // вес в фунтах

    kg : real; // вес в килограммах
    begin

    f := StrToFloat(Edit1.Text);


    kg := f; * 0.4059;

    Label2.Caption := Edit1.Text + ' ф. — это ' +

    FloatToStrF(kg, ffGeneral, 4, 2} + 'кг.'; end;

    // нажатие клавиши в поле ввода исходных данных

    procedure TForml.Edit1KeyPress(Sender: TObject; var Key: Char);


    var

    f : real; // вес в фунтах kg : real; // вес в килограммах
    begin

    if Key = Char(VK_RETURN) then
    begin

    f: = . StrToFloat(Editl.Text) ;

    kg := f * 0.4059;

    Label2.Caption := Editl.Text + ' ф. - это ' +

    FloatToStrF(kg, ffGeneral, 4, 2) + 'кг.'1.;
    end;
    end;

    end.

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

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



    Пересчет веса из фунтов

    Листинг 6.2. Пересчет веса из фунтов в килограммы (использование процедуры)

    unit Onit1; interface

    uses

    Windows, Messages, SysUtils, Variants,
    Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1= class(TForm)

    Label1: TLabel; // пояснительный текст

    Edit1: TEdit; // поле ввода веса в фунтах

    Button1: TButton; // кнопка Вычислить

    Label2: TLabel; // поле вывела результата

    procedure Button1Click(Sender: TObject);


    procedure EditlKeyPress(Sender: TObject;
    var Key: Char);
    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    {$R *.dfm}

    // процедура программиста
    procedure FuntToKg;

    var

    f : real; // вес в фунтах

    kg : real; // вес в килограммах
    begin

    f := StrToFloat(Form1.Edit1.Text);


    kg := f * 0.4059;

    Forml.Label2.Caption := Forml.Edit1.Text + ' ф. — это ' +

    FloatToStrF(kg, ffGeneral, 4, 2) + 'кг.';
    end;

    // щелчок на кнопке Вычислить

    procedure TForml.ButtonlClick(Sender: TObject);


    begin

    FuntToKg; // вызов процедуры FuntToKg end;

    // нажатие клавиши в поле ввода исходных данных

    procedure TForm1.EditlKeyPress(Sender: TObject;
    var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then FuntToKg; // вызов процедуры FuntToKg end;

    end.

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

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

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

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

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

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

    Параметры используются:

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

    Примеры функций

    Листинг 6.3. Примеры функций

    // проверяет, является ли символ допустимым

    // во время ввода целого числа

    function Islnt(ch : char) : Boolean;

    begin

    if (ch >
    = '0'} and (ch <= '9') // цифры

    or (ch = 113) // клавиша


    or (ch = #8) // клавиша


    then Islnt := True // символ допустим
    else Islnt := False; // недопустимый символ

    end;

    // проверяет, является ли символ допустимым

    // во время ввода дробного числа

    function IsFloat(ch : char; st: string) : Boolean;

    begin

    if (ch >
    = '0') and (ch <= '9') // цифры

    or (ch = #13) // клавиша


    or (ch = #8) // клавиша


    then

    begin

    IsFloat := True; // символ верный
    Exit; // выход из функции

    end;
    case ch of

    '-': if Length(st) = 0
    then IsFloat := True; ',':
    if (Pos(',',st) = 0)

    and (st[Length(st)]'>
    = '0') and (st[Length(st)] <= '9')

    then // разделитель можно ввести только после цифры // и если он еще не введен

    IsFloat := True; else // остальные символы запрещены

    IsFloat := False;
    end;
    end;

    Пример использования функций программиста

    Листинг 6.4. Пример использования функций программиста

    unit fazenda_;

    interface

    Windows, Messages, SysUtils, Variants,
    Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    Edit1: TEdit; // расстояние

    Edit2: TEdit; // цена литра бензина

    Edit3: TEdit; // потребление бензина на 100 км

    CheckBox1: TCheckBox; // True - поездка туда и обратно

    Button1: TButton; // кнопка Вычислить

    Label4: TLabel; // поле вывода результата расчета

    Label1: TLabel;

    Label2: TLabel;

    Label3: TLabel;

    procedure EditlKeyPress(Sender: TObject;
    var Key: Char);


    procedure Edit2KeyPress(Sender: TObject;
    var Key: Char);


    procedure Edit3KeyPress(Sender: TObject;
    var Key: Char);


    procedure Button1Click(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.dfm}

    // проверяет, является ли символ допустимым

    // во время ввода дробного числа

    function IsFloat(ch : char; st: string) : Boolean;

    begin

    if (ch >
    = '0') and (ch <= '9') // цифры

    or (ch = #13) // клавиша


    or (ch = #8) // клавиша


    then

    begin

    IsFloat := True; // символ верный
    Exit; // выход из функции

    end; case ch of

    '-': if Length(st) = 0 then IsFloat := True; ', ':
    if (Pos(',',st) = 0)

    and (st[Length(st)] >
    = '0') and (st[Length(st)] <= '9')

    then // разделитель можно ввести только после цифры
    // и если он еще не введен

    IsFloat := True/else // остальные символы запрещены

    IsFloat := False;
    end;
    end;

    // нажатие клавиши в поле Расстояние

    procedure TForm1.EditlKeyPress(Sender: TObject;
    var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then Edit2.SetFocus // переместить курсор в поле Цена
    else
    If not IsFloat(Key,Edit2.Text) then Key := Chr(O);


    end;

    // нажатие клавиши в поле Цена

    procedure TForml.Edit2KeyPress(Sender: TObject;
    var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then Edit3.SetFocus // переместить курсор в поле Потребление
    else If not IsFloat(Key,Edit2.Text)
    then Key := Chr (0);


    end;

    // нажатие клавиши в поле Потребление

    procedure TForml.Edit3KeyPress(Sender: TObject;
    var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then Buttonl.SetFocus // // сделать активной кнопку Вычислить
    else If not IsFloat(Key,Edit2.Text) then Key := Chr (0);


    end;

    // щелчок на кнопке Вычислить

    procedure TForm1.ButtonlClick(Sender: TObject);


    var

    rast : real; // расстояние

    cena : real; // цена

    potr : real; // потребление на 100 км

    summ : real; // сумма

    mes: string;
    begin

    rast := StrToFloat(Edit1.Text);


    cena := StrToFloat(Edit2.Text);


    potr := StrToFloat(Edit3.Text);


    summ := rast / 100 * potr * cena;

    if CheckBoxl.Checked then summ := summ * 2;

    mes := 'Поездка на дачу';

    if CheckBoxl.Checked then mes := mes + ' и обратно';

    mes := mes + 'обойдется в '
    + FloatToStrF(summ,ffGeneral,4,2) + ' руб.';

    Label4.Caption := mes;
    end;
    end.

    Процедура SgRoot

    Листинг 6.5. Процедура SgRoot

    // решает квадратное уравнение

    procedure SqRoot(a,b,c : real;
    var xl,x2 : real;
    var ok : boolean);

    { a,b,c — коэффициенты уравнения x1,x2 — корни уравнения ok = True — решение есть ok = False — решения нет }
    var

    d : real; // дискриминант
    begin

    d:= Sqr(b) - 4*a*c; if d < 0 then

    ok := False // уравнение не имеет решения
    else

    begin

    ok := True;

    x1 := (-b + Sqrt(d)) / (2*a) ; x2 := (b + Sqrt(d)) / (2*a);

    end;
    end;

    Решение квадратного

    Листинг 6.6. Решение квадратного уравнения (использование процедуры)

    unit SqRoot_; interface

    uses

    Windows, Messages, SysUtils, Variants, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForml = class(TForm)

    Editl: TEdit;

    Edit2: TEdit;

    Edit3: TEdit;

    Label1: TLabe1;

    Label2: TLabe1;

    Label3: TLabe1;

    Label4: TLabe1;

    Button1: TButton;

    Label5: TLabel;

    procedure ButtonlClick(Sender: TObject);
    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.dfm}

    // решает квадратное уравнение

    procedure SqRoot(a,b,c : real; var xl, x2 : real; var ok : boolean);

    { a,b,c — коэффициенты уравнения x1,x2 — корни уравнения

    ok = True — решение есть ok = False — решения нет }
    var

    d : real; // дискриминант begin

    d:= Sqr(b) - 4*a*c; if d < 0 then

    ok := False // уравнение не имеет решения
    else

    begin

    ok := True;

    xl := (-b + Sqrt(d)) / (2*a);
    x2 := (b + Sqrt(d)) / (2*a) ;
    end;
    end;

    procedure TForml.ButtonlClick(Sender: TObject);

    var

    k1,k2: real; // корни уравнения

    rez: boolean; // True —решение есть, False —решения нет mes:
    string; // сообщение begin

    SqRoot(StrToFloat(Editl.Text), StrToFloat(Edit2.Text) ,

    StrToFloat(Edit3.Text) , k1,k2,rez);

    if rez then

    mes := 'Корни уравнения' + #13 +

    'x1='+FloatToStrF(kl,ffGeneral,
    4,2)+#13+ 'x2='+FloatToStrF(k2,ffGeneral,4,2)+#13 else

    mes := 'Уравнение не имеет решения'; labels.Caption := mes;
    end;

    end.

    Шаблон модуля

    Листинг 6.7. Шаблон модуля

    unit Unit1;

    interface implementation
    end.

    Начинается модуль заголовком — инструкцией unit, в которой указано имя модуля. Во время сохранения модуля это имя будет автоматически заменено на имя, указанное программистом.

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

    В раздел implementation (реализация) нужно поместить процедуры и функции, объявленные в разделе interface.

    В качестве примера в листинге 6.8 приведен модуль программиста, который содержит рассмотренные ранее функции IsInt и isFioat.



    Модуль программиста

    Листинг 6.8. Модуль программиста

    unit my__unit;

    interface // объявления процедур и функций,

    // доступных программам,

    // использующим этот модуль

    function IsInt(ch : char) : Boolean;
    // функция Islnt проверяет, является ли символ
    // допустимым во время ввода целого числа

    function IsFloat(ch : char; st: string) : Boolean;

    // Функция IsFloat проверяет, является ли символ допустимым

    // во время ввода дробного числа

    // ch — очередной символ

    // st — уже введенные символы

    implementation // реализация

    // проверяет, является ли символ допустимым
    // во время ввода целого числа
    function Islnt(ch : char) : Boolean;
    begin

    if (ch >
    = '0') and (ch <= '9') // цифры

    or (ch = #13) // клавиша


    or (ch = #8) // клавиша


    then Islnt := True // символ допустим
    else Islnt := False; // недопустимый символ
    end;

    // проверяет, является ли символ допустимым
    // во время ввода дробного числа

    function IsFloat(ch : char; st: string) : Boolean;
    // ch — очередной символ // st — уже введенные символы
    begin

    if (ch >
    = '0') and (ch <= '9') // цифры

    or (ch = #13) // клавиша


    or (ch = #8) // клавиша


    then

    begin

    IsFloat := True; // символ верный
    Exit; // выход из функции

    end; case ch of

    '-': if Length(st) = 0 then IsFloat := True; ',':
    if (Pos(',',st) = 0)

    and (st[Length(st)] >
    = '0') and (st[Length(st)] <= '9')

    then // разделитель можно ввести только после цифры
    // и если он еще не введен

    IsFloat := True; else // остальные символы запрещены

    IsFloat := False; end

    // это раздел инициализации // он в данном случае не содержит инструкция end.

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

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

    Листинг 6.9. Использование функции из модуля программиста

    unit fazenda_;
    interface

    uses

    Windows, Messages, SysUtils, Variants,
    Classes, Graphics, Controls, Forms,
    Dialogs, StdCtrls, my_unit; // модуль программиста

    type

    TForm1 = class(TForm)

    Edit1: TEdit; // расстояние

    Edit2: TEdit; // цена литра бензина

    Edit3: TEdit; // потребление бензина на 100 км

    CheckBoxl: TCheckBox; // True — поездка туда и обратно

    Button1: TButton; // кнопка Вычислить

    Label4: TLabel; // поле вывода результата расчета

    Label1: TLabel;

    Label2: TLabel;

    Label3: TLabel;

    procedure EditlKeyPress(Sender: TObject;
    var Key: Char);


    procedure Edit2KeyPress(Sender: TObject;
    var Key: Char);


    procedure Edit3KeyPress(Sender: TObject;
    var Key: Char);


    procedure Button1Click(Sender: TObject);

    private

    { Private declarations} public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    {$R *.dfm}

    // нажатие клавиши в поле Расстояние

    procedure TForml.EditlKeyPress(Sender: TObject;
    var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then Edit2.SetFocus // переместить курсор в поле Цена
    else If not IsFloat(Key,Edit2.Text)
    then Key := Chr(O);


    end;

    // нажатие клавиши в поле Цена

    procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then Edit3.SetFocus // переместить курсор в поле Потребление .
    else If not IsFloat(Key,Edit2.Text) then Key := Chr(0);

    end;

    // нажатие клавиши в поле Потребление

    procedure TForm1.EditSKeyPress(Sender: TObject;
    var Key: Char);


    begin

    if Key = Char(VK_RETURN)

    then Button1.SetFocus // // сделать активной кнопку Вычислить
    else If not IsFloat(Key,Edit2.Text) then Key := Chr(0);


    end;

    // щелчок на кнопке Вычислить

    procedure TForml.ButtonlClick(Sender: TObject);


    var

    rast : real; // расстояние

    cena : real; // цена

    potr : real; // потребление на 100 км

    summ : real; // сумма

    mes: string;
    begin

    rast := StrToFloat(Editl.Text) ;

    cena := StrToFloat(Edit2.Text);


    potr := StrToFloat(Edit3.Text);


    summ := rast / 100 * potr * cena;

    if CheckBoxl.Checked then summ := summ * 2;

    mes := 'Поездка на дачу';

    if CheckBox1.Checked then

    mes : = mes + ' и обратно' ;

    mes := mes + 'обойдется в '
    + FloatToStrF(summ,ffGeneral, 4,2) + ' руб.';

    Label4.Caption := mes;
    end;

    end.

    После добавления имени модуля в список модулей, используемых приложением, сам модуль нужно добавить в проект. Для этого из меню Project надо выбрать команду Add to Project и в открывшемся диалоговом окне — имя файла модуля. В результате добавления модуля к проекту в окне редактора появится вкладка с текстом добавленного к проекту модуля.

    Увидеть структуру проекта можно в окне Project Manager, которое появляется в результате выбора соответствующей команды из меню View. В качестве примера на Рисунок 6.3 приведена структура проекта Поездка на дачу.



    Объявление функции

    Объявление функции

    Объявление функции в общем виде выглядит так:
    function Имя (параметр1 : тип1, ..., параметрК : типК) : Тип; var

    // здесь объявления локальных переменных begin

    // здесь инструкции функции

    Имя := Выражение; end;

    где:

  • function — зарезервированное слово языка Delphi, обозначающее, что далее следуют инструкции, реализующие функцию программиста;
  • имя — имя функции. Используется для перехода из программы к инструкциям функции;
  • параметр — это переменная, значение которой используется для вычисления значения функции. Отличие параметра от обычной переменной состоит в том, что он объявляется не в разделе объявления переменных, который начинается словом var, а в заголовке функции. Конкретное значение параметр получает во время работы программы в результате вызова функции из основной программы;
  • тип — тип значения, которое функция возвращает в вызвавшую ее программу.
  • Следует обратить внимание, что последовательность инструкций, реализующих функцию, завершается инструкцией, которая присваивает значение имени функции. Тип выражения, определяющего значение функции, должен совпадать с типом функции, указанным в ее объявлении.

    В качестве примера в листинге 6.3 приведены функции isint и isFioat. Функция isint проверяет, является ли символ, соответствующий клавише, нажатой во время ввода целого числа в поле редактирования, допустимым. Предполагается, что допустимыми являются цифры, клавиши и . Функция IsFloat решает аналогичную задачу, но для дробного числа. У функции IsFloat два параметра: код нажатой клавиши и строка символов, которая уже введена в поле редактирования.



    Объявление процедуры

    Объявление процедуры

    В общем виде объявление процедуры выглядит так: procedure Имя (var параметр1: тип1; ... var параметрК: типК) ; var

    // здесь объявление локальных переменных
    begin

    // здесь инструкции процедуры
    end;

    где:

  • procedure — зарезервированное слово языка Delphi, обозначающее, что далее следует объявление процедуры;
  • имя — имя процедуры, которое используется для вызова процедуры;
  • параметр K — формальный параметр, переменная, которая используется в инструкциях процедуры. Слово var перед именем параметра не является обязательным. Однако если оно стоит, то это означает, что в инструкции вызова процедуры фактическим параметром обязательно должна быть переменная.
  • Параметры процедуры используются для передачи данных в процедуру, а также для возврата данных из процедуры в вызвавшую ее программу.

    В качестве примера в листинге 6.5 приведена процедура решения квадратного уравнения (которое в общем виде записывается так: ах2 + Ьх+ с = 0). У процедуры шесть параметров: первые три предназначены для передачи в процедуру исходных данных — коэффициентов уравнения; параметры xi и х2 используются для возврата результата — корней уравнения; параметр ok служит для передачи информации о том, что решение существует.



    Окно программы Квадратное уравнение

    Рисунок 6.2. Окно программы Квадратное уравнение


    Окно программы Квадратное уравнение





    Окно программы Поездка на дачу

    Рисунок 6.1. Окно программы Поездка на дачу

    Окно программы Поездка на дачу

    Следующая программа (ее текст приведен в листинге 6.4, а вид диалогового окна на Рисунок 6.1) вычисляет стоимость поездки на дачу. Исходными данными для программы являются: расстояние, цена одного литра бензина и потребление бензина на 100 км пути. Для ввода исходных данных применяются поля Edit1, Edit2 и Edit3. Функции обработки события OnKeyPress

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



    Повторное использование функций и процедур

    Повторное использование функций и процедур

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

    Процедура

    Процедура

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

  • когда подпрограмма не возвращает в основную программу никаких данных. Например, вычерчивает график в диалоговом окне;
  • когда подпрограмма возвращает в вызвавшую ее программу больше чем одно значение. Например, подпрограмма, которая решает квадратное уравнение, должна вернуть в вызвавшую ее программу два дробных числа — корни уравнения.


  • Создание модуля

    Создание модуля

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

    Чтобы приступить к созданию модуля, нужно сначала закрыть окно формы и окно модуля формы (в ответ на вопрос о необходимости сохранения модуля следует выбрать No, т. е. модуль, соответствующий закрытой форме, сохранять не надо). Затем из меню File нужно выбрать команду New | Unit. В результате открывается окно редактора кода, в котором находится сформированный Delphi шаблон модуля. Его текст приведен в листинге 6.7.



    Структура проекта отражается в окне Project Manager

    Рисунок 6.3. Структура проекта отражается в окне Project Manager

    Структура проекта отражается в окне Project Manager

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


    Основы языка Delphi

    Алгоритм открытия файла с обработкой возможной ошибки

    Рисунок 7.4. Алгоритм открытия файла с обработкой возможной ошибки

    Алгоритм открытия файла с обработкой возможной ошибки

    Ниже приведен фрагмент программы, реализующий приведенный выше алгоритм открытия файла.

    AssignFile(f,filename);

    {$I-}

    Append(f) // открыть для добавления

    {$I+}

    if IOResult<> 0 // ошибка открытия

    then Rewrite(f); // открыть для записи

    // здесь открыт существующий или новый файл

    Чтение чисел

    Чтение чисел

    Следует понимать, что в текстовом файле находятся не числа, а их изображения. Действие, выполняемое инструкциями read или readin, фактически состоит из двух: сначала из файла читаются символы до появления разделителя (пробела или конца строки), затем прочитанные символы, являющиеся изображением числа, преобразуются в число, и полученное значение присваивается переменной, имя которой указано в качестве параметра инструкции read ИЛИ readin.

    Например, если текстовый файл а: \data. txt содержит следующие строки:

    23 15 45 28 56 71

    то в результате выполнения инструкций:

    AssignFile(f, 'a:\data.txt');

    Reset(f); // открыть для чтения

    read(f, а); read(f, b, с); read(f, d);

    значения переменных будут следующими: а = 23, b = 15, с = 45, d = 28.

    Отличие инструкции readin от read состоит в том, что после считывания из файла очередного числа и присвоения полученного значения переменной, имя которой стоит последним в списке параметров инструкции readin, указатель чтения из файла автоматически перемещается в начало следующей строки файла, даже в том случае, если за прочитанным числом есть еще числа.

    Поэтому в результате выполнения инструкций

    AssignFile(f,'a:\data.txt'); Reset(f); readin(f, a); readin(f, b, c); readin(f, d);

    значения переменных будут следующими: а = 23, b = 45, с = 28, d = 56.

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


    Чтение данных из файла

    Чтение данных из файла

    Чтение из файла выполняется при помощи инструкций read и readin, которые в общем виде записываются следующим образом:

    read( ФайловаяПеременная, СписокПеременных); readin( ФайловаяПеременная, СписокПеременных) ;

    где:

  • ФайловаяПеременная — переменная типа TextFile;
  • СписокПеременных — имена переменных, разделенные запятыми.


  • Чтение строк

    Чтение строк

    В программе строковая переменная может быть объявлена с указанием длины или без нее.

    Например:

    stroka1:string[10]; stroka2:string;

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

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

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

    Пусть, например, текстовый файл f reinds. txt содержит строки:

    Косичкина Маша Васильев Антон Цой Лариса

    В табл. 7.1 приведено несколько вариантов объявления переменных, инструкции чтения из файла freinds.txt и значения переменных после выполнения инструкций чтения.



    Диалоговое окно программы База данных "Погода"

    Рисунок 7.5. Диалоговое окно программы База данных "Погода"

    Диалоговое окно программы База данных

    Дата вводится в поле Edit1, температура — в поле Edit2. Текст программы приведен в листинге 7.3.



    Диалоговое окно программы записидобавления в файл

    Рисунок 7.1. Диалоговое окно программы записи-добавления в файл

    Диалоговое окно программы записидобавления в файл

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

    Имя файла нужно ввести во время работы в поле Editl. Можно задать предопределенное имя файла во время разработки формы приложения. Для этого надо присвоить значение, например test.txt, свойству Edit1.Text.



    которые до настоящего момента рассматривались

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



    Конец файла

    Конец файла

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

    Для определения конца файла можно воспользоваться функцией EOF (End of File — конец файла). У функции EOF один параметр — файловая переменная. Значение функции EOF равно False, если прочитанный элемент данных не является последним в файле, т. е. возможно дальнейшее чтение. Если прочитанный элемент данных является последним, то значение EOF равно True.

    Значение функции EOF можно проверить сразу после открытия файла. Если при этом оно окажется равным True, то это значит, что файл не содержит ни одного элемента данных, т. е. является пустым (размер такого файла равен нулю).

    В листинге 7.5 приведена процедура, которая выполняет поставленную задачу. Она читает строки из файла, имя которого ввел пользователь во время работы программы, и выводит эти строки в поле Memo. Окно программы приведено на Рисунок 7.6.



    Создание нового или

    Листинг 7.1. Создание нового или замещение существующего файла

    procedure TForm1.Button1Click(Sender: TObject);

    var

    f: TextFile; // файл

    fName: String[80]; // имя файла

    i: integer;
    begin

    fName := Editl.Text;

    AssignFile(f, fName);


    Rewrite(f);
    // открыть для перезаписи

    // запись в файл

    for i: =0 to Memol.Lines.Count do // строки нумеруются с нуля
    writeln(f, Memol.Lines[i]);


    CloseFile(f);
    // закрыть файл

    MessageDlg('Данные ЗАПИСАНЫ в файл ',mtlnformation,[mbOk],0);

    end;

    В листинге 7.2 приведена процедура, которая запускается нажатием командной кнопки Добавить. Она открывает файл, имя которого указано в поле Edit1, и добавляет в него содержимое поля Memol.



    Добавление в существующий файл

    Листинг 7.2. Добавление в существующий файл

    procedure TForm1.Button2Click(Sender: TObject);

    var

    f: TextFile; // файл

    fName: String[80];.// имя файла

    i: integer; begin

    fName := Edit1.Text;

    AssignFile(f, fName);


    Append(f);
    // открыть для добавления
    // запись в файл

    for i:=0 to Memo1.Lines.Count do // строки нумеруются с нуля
    writeln(f, Memo1.Lines[i]);


    CloseFile(f);
    // закрыть файл

    MessageDlg('Данные ДОБАВЛЕНЫ в файл ',mtInformation,[mbOk],0);

    end;

    Простая база данных (запись в файл)

    Листинг 7.3, Простая база данных (запись в файл)

    unit pogoda_;

    interface

    uses

    Windows, Messages, SysUtils, Variants, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    Edit1: TEdit; // дата

    Edit2: TEdit; // температура

    Button1: TButton; // кнопка Добавить

    Label1: TLabe1;

    Label2: TLabe1;

    procedure FormActivate(Sender: TObject);


    procedure ButtonlClick(Sender: TObject);


    procedure FormClose(Sender: TObject;
    var Action: TCloseAction);
    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    {$R *.dfm}

    const

    DBNAME = 'a:\pogoda. db';

    var

    db: TextFile; // файл — база данных

    procedure TForm1.FormActivate(Sender: TObject);

    begin

    AssignFile(db, DBNAME);
    . {$I-}

    Append(db);
    if IOResult = 0 then

    begin

    Edit1.Text := DateToStr(Date);
    // получить текущую дату
    Edit2.SetFocus; // курсор в поле Edit2

    end

    else begin

    Rewrite(db);
    if IOResult <>
    0 then begin

    // сделать недоступными поля ввода // и командную кнопку
    Edit1.Enabled := False; Edit2.Enabled := False;
    Buttonl.Enabled := False; ShowMessage('Ошибка создания '+DBNAME);

    end;
    end;
    end;

    // щелчок на кнопке Добавить

    procedure TForml.Button1Click(Sender: TObject);


    begin

    if (Length(edit1.text)=0) or (Length(edit2.text)=0)
    then ShowMessage('Ошибка ввода данных.'

    +#13+'Bce поля должны быть заполнены.')
    else writeln(db, editl.text,' ',edit2.text);

    end;

    // Событие OnClose возникает при закрытии формы

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);


    begin

    CloseFile(db);
    // закрыть файл БД
    end;

    end.

    Файл базы данных открывает процедура FormActivate, которая обрабатывает событие onActivate. Событие OnActivate возникает в момент активизации формы, поэтому процедура запускается автоматически, при активизации формы приложения. Если операция открытия файла завершается успешно, то в поле Edit1 записывается текущая дата. Информация о текущей дате возвращает функция Date. Для преобразования возвращаемого функцией Date значения (числа типа Double) в удобную для восприятия форму используется функция Dateiostr. После записи даты в поле Editi процедура обработки события onActivate с применением метода setFocus устанавливает курсор в поле ввода температуры. Если в процессе открытия или создания нового файла возникает ошибка, то процедура делает недоступной кнопку Добавить и выводит информационное сообщение.

    Процедура TForm1.Button1Click (процедура обработки события onclick) запускается нажатием кнопки Добавить (Button1). В результате введенная информация записывается в базу данных — файл pogoda.db. Перед выполнением записи программа проверяет, все ли поля формы заполнены, и, если не все, то выводит информационное сообщение.

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

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

    Обратите внимание, что список вывода инструкции writein состоит из трех элементов. После вывода в файл даты (Edit1.text) в файл записывается пробел, а затем— температура (edit2.txt). Если температуру записать в файл сразу после даты, то числа, соответствующие году и температуре, сольются в одну последовательность цифр.

    Закрывает базу данных процедура TFormi.Formciose, которая обрабатывает событие enclose, возникающее при закрытии формы приложения.

    После нескольких запусков программы файл pogoda.db может быть, например, таким:

    9.05.2001 10 10.05.2001 12 11.05.2001 10 12.05.2001 7

    Обработка ошибки открытия

    Листинг 7.4. Обработка ошибки открытия файла (фрагмент программы)

    var

    fname : string[80]; // имя файла

    f : TextFile; // файл

    res : integer; // код ошибки открытия файла (значение lOResult)

    answ : word; // ответ пользователя

    begin

    fname := 'a:\test.txt'; AssignFile (f, fname);

    repeat

    <$I-}

    Reset(f);
    // открыть файл для чтения

    {$!+}

    res:=IOResult;

    if res <>
    0

    then answ:=MessageDlg('Ошибка открытия '
    + fname+#13 +'Повторить попытку?',mtWarning,
    [mbYes, mbNo],0);
    until (res= 0) OR (answ = mrNo);


    if res <>
    0

    then exit; // завершение процедуры

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

    end;

    Чтение из файла

    Листинг 7.5. Чтение из файла

    unit rd_;

    interface

    uses

    Windows, Messages, SysUtils, Variants, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons;

    type

    TForm1 = class(TForm)

    Button2: TButton;

    Edit1: TEdit;

    Memo1: TMemo;

    Button1: TButton;

    procedure Button2Click(Sender: TObject);


    procedure ButtonlClick(Sender: TObject);
    private

    { Private declarations ) public

    { Public declarations } end;

    var

    Form1: TForml;

    implementation

    {$R *.dfm}

    // щелчок на кнопке Открыть

    procedure TForm1.Button1Click(Sender: TObject);


    var

    f: TextFile; // файл fName: String[80]; // имя файла
    buf: String[80]; // буфер для чтения из файла
    begin

    fName := Edit1.Text; AssignFile(f, fName);
    {$!-}

    Reset(f);
    // открыть для чтения {$I+}

    if IOResult <>
    0 then begin

    MessageDlgt'Ошибка доступа к файлу ' + fName,

    mtError,[mbOk],0);
    exit; end;

    // чтение из файла
    while not EOF(f) do begin

    readln(f, buf);
    // прочитать строку из файла
    Memo1.Lines.Add(buf);
    // добавить строку в поле Memo1
    end;

    CloseFile(f);
    // закрыть файл
    end;

    // щелчок на кнопке Сохранить — запись в файл

    procedure TForml.Button2Click(Sender: TObject);

    var

    f: TextFile; // файл
    fName: String[80]; // имя файла
    i: integer/; begin

    fName := Edit1.Text; AssignFile(f, fName);


    Rewrite(f);
    // открыть для перезаписи

    // запись в файл

    for i:=0 to Memo1.Lines.Count do // строки нумеруются с нуля
    writeln(f, Memo1.Lines[i]);


    CloseFile(f);
    // закрыть файл

    MessageDlg('Данные записаны в файл ',mtlnformation,[mbOk],0);

    end;

    end.

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

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

    Добавление очередной прочитанной из файла строки в поле Memo выполняется применением метода Add к свойству Lines.

    Назначение файла

    Назначение файла

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

    Имя файла задается вызовом процедуры AssignFiie, связывающей файловую переменную с конкретным файлом.

    Описание процедуры AssignFiie выглядит следующим образом:

    AssignFiie(var f, ИмяФайла: string)

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

    Ниже приведены примеры вызова процедуры AssignFiie:

    AssignFile(f, 'a:\result.txt');
    AssignFile(f, '\students\ivanov\korni.txt');
    fname:=('otchet.txt'); AssignFiie(f,fname);

    Объявление файла

    Объявление файла

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

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

    В общем виде объявление файла выглядит так: Имя:file of ТипЭлементов;

    Примеры:

    res: file of char; // файл символов

    koef: file of real; // файл вещественных чисел

    f: file of integer; // файл целых чисел

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

    Имя:TextFile;

    где:

  • имя — имя файловой переменной;
  • TextFile — обозначение- типа, показывающее, что Имя — это файловая переменная, представляющая текстовый файл.


  • Окно программы Чтение из файла

    Рисунок 7.6. Окно программы Чтение из файла


    Окно программы Чтение из файла





    Ошибки открытия файла

    Ошибки открытия файла

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

    При запуске программы из Delphi в случае ошибки во время открытия файла возникает исключение, и на экране появляется диалоговое окно с сообщением (Рисунок 7.2).



    Открытие файла для вывода

    Открытие файла для вывода

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

    Возможны следующие режимы открытия файла для записи в него данных:

  • перезапись (запись нового файла поверх существующего или создание нового файла);
  • добавление в существующий файл.
  • Для того чтобы открыть файл в режиме создания нового файла или замены существующего, необходимо вызвать процедуру Rewrite(f), где f — файловая переменная типа TextFile.

    Для того чтобы открыть файл в режиме добавления к уже существующим данным, находящимся в этом файле, нужно вызвать процедуру Append (f), где f — файловая переменная типа TextFile.

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



    Открытие файла

    Открытие файла

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

    Например, следующие инструкции открывают файл для ввода:

    AssignFile(f, 'c:\data.txt'); Reset(f);

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

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

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

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



    Пример программы

    Пример программы

    Следующая программа ведет простую базу данных. При каждом ее запуске на экране появляется диалоговое окно (Рисунок 7.5), в поля которого пользователь может ввести дату и температуру воздуха.



    Пример сообщения об ошибке открытия

    Рисунок 7.2. Пример сообщения об ошибке открытия файла (программа запущена из Delphi)

    Пример сообщения об ошибке открытия

    Если программа запускается из Windows, то окно с сообщением об ошибке выглядит иначе (Рисунок 7.3).



    Рисунок 7.3. Пример сообщения об ошибке открытия файла . (программа запущена из Windows)

    Пример сообщения об ошибке открытия

    Программа может взять на себя задачу контроля за результатом выполнения инструкции открытия файла. Сделать это можно, проверив значение функции IOResult (input-Output Result — результат ввода/вывода). Функция IOResuit возвращает 0, если операция ввода/вывода завершилась успешно; в противном случае — код ошибки (не ноль).

    Для того чтобы программа смогла проверить результат выполнения операции ввода/вывода, нужно разрешить ей это делать. Для этого надо перед инструкцией вызова процедуры открытия файла поместить директиву компилятору — строку {$I-}, которая запрещает автоматическую обработку ошибок ввода/вывода. Эта директива сообщает компилятору, что программа берет на себя контроль ошибок. После инструкции открытия файла следует поместить директиву {$I+}, восстанавливающую режим автоматической обработки ошибок ввода/вывода.

    На Рисунок 7.4 приведена блок-схема алгоритма открытия файла для добавления, обеспечивающего создание файла (и тем самым устраняющего ошибку, возникающую при попытке открыть несуществующий файл) в случае, если открываемого для добавления файла на диске еще нет.

    Примеры чтения строк из файла

    Таблица 7.1. Примеры чтения строк из файла

    Объявления Инструкция чтения переменных из файла

    Значение переменных после чтения из файла

    fam: string[15]

    Readin (f, fam, name)

    f am= ' Косичкина

    name: string[10]



    name= ' Маша

    fam, name: string;

    Readin (f, fam, name)

    fam= ' Косичкина Маша '





    name= ' '

    drug: string[80]

    Readin (f, drug)

    drug =' Косичкина Маша'



    Ввод из файла

    Ввод из файла

    Программа может вводить исходные данные не только с клавиатуры, но и из текстового файла. Для того чтобы воспользоваться этой возможностью, нужно объявить файловую переменную типа TextFiie, назначить ей при помощи инструкции AssignFile имя файла, из которого будут считываться данные, открыть файл для чтения (ввода) и прочитать (ввести) данные, используя инструкцию read или readln.

    Вывод в файл

    Вывод в файл

    Непосредственно вывод в текстовый файл осуществляется при помощи инструкции write или writeln. В общем виде эти инструкции записываются следующим образом:

    write (ФайловаяПеременная, СписокВывода) ;
    writeln (ФайловаяПеременная, СписокВывода);

    где:

  • ФайловаяПеременная — переменная, идентифицирующая файл, в который выполняется вывод;
  • СписокВывода -- разделенные запятыми имена переменных, значения которых надо вывести в файл. Помимо имен переменных в список вывода можно включать строковые константы.
  • Например, если переменная f является переменной типа TextFiie, то инструкция вывода значений переменных x1 и х2 в файл может быть такой:

    write(f, 'Корни уравнения', xl, х2);

    Различие между инструкциями write и writeln состоит в том, что инструкция writeln после вывода всех значений, указанных в списке вывода, записывает в файл символ "новая строка".

    Закрытие файла

    Закрытие файла

    Перед завершением работы программа должна закрыть все открытые файлы. Это делается вызовом процедуры close. Процедура close имеет один параметр — имя файловой переменной. Пример использования процедуры:

    Close(f).

    Основы языка Delphi

    Чтение записи из файла

    Чтение записи из файла

    Рассмотрим программу, демонстрирующую процесс чтения и обработки записей файла. Программа Чтение записей из файла, диалоговое окно которой представлено на Рисунок 8.4, а текст — в листинге 8.2, открывает файл, сформированный программой Добавление записи в файл, и, в зависимости от того, какой из переключателей все или выбрать — установлен, выводит список медалей, выигранных соответственно представителями всех стран или страны, название которой введено в поле Страна. Для вывода результата чтения из файла используется компонент Memol.

    В табл. 8.2 приведены значения свойств компонентов формы.

    Так как компонент Memol предназначен только для просмотра информации, то свойству Readonly (только чтение, просмотр) присвоено значение True. Свойство scroiiBars (полосы прокрутки) компонента Memo позволяет задавать отображаемые полосы прокрутки. По умолчанию свойству scroiiBars присвоено значение ssNone, т. е. полосы прокрутки не отображаются. В рассматриваемом примере выводится вертикальная полоса, поэтому свойству ScroiiBars присвоено значение ssVertical.



    Диалоговое окно программы Упорядоченный

    Рисунок 8.10. Диалоговое окно программы Упорядоченный динамический список 2

    Диалоговое окно программы Упорядоченный

    Следующая программа (ее текст приведен в листинге 8.5, а диалоговое окно — на Рисунок 8.10) формирует список, упорядоченный по полю Фамилия. Данные вводятся в поля редактирования (Edit1 и Edit2) и нажатием кнопки Добавить (Buttoni) добавляются в список таким образом, что список всегда упорядочен по полю Фамилия.



    Динамические переменные

    Динамические переменные

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

    Выделение памяти для динамической переменной осуществляется вызовом процедуры new. У процедуры new один параметр — указатель на переменную того типа, память для которой надо выделить. Например, если р является указателем на тип real, то в результате выполнения процедуры new(p); будет выделена память для переменной типа real (создана переменная типа real), и переменная-указатель р будет содержать адрес памяти, выделенной для этой переменной.

    У динамической переменной нет имени, поэтому обратиться к ней можно только при помощи указателя.

    Процедура, использующая динамические переменные, перед завершением своей работы должна освободить занимаемую этими переменными память или, как говорят программисты, уничтожить динамические переменные". Для освобождения памяти, занимаемой динамической переменной, используется процедура Dispose, которая имеет один параметр — указатель на динамическую переменную.

    Например, если р — указатель на динамическую переменную, память для которой выделена инструкцией new(p), то инструкция dispose (р) освобождает занимаемую динамической переменной память.

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



    Динамические структуры данных

    Динамические структуры данных

    До этого момента мы работали только с данными, имеющими статическую, неизменяемую во время исполнения программы, структуру. Во время работы программы могли изменяться только значения переменных, в то время как количество переменных всегда оставалось постоянным (отсюда и название — статические структуры). Это не всегда удобно.

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

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

    Добавление элемента в список

    Добавление элемента в список

    Добавление элемента в список выполняется путем корректировки указателей. Для того чтобы добавить элемент в упорядоченный список, нужно сначала найти элемент, после которого требуется вставить новый. Затем следует скорректировать указатели. Указатель нового элемента нужно установить на тот элемент, на который указывает элемент, после которого добавляется новый. Указатель элемента, после которого добавляется новый элемент, установить на этот новый элемент (Рисунок 8.9).



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

    Рисунок 8.9. Добавление элемента в упорядоченный список


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





    Добавление элементов в список

    Рисунок 8.7. Добавление элементов в список

    Добавление элементов в список

    Следующая программа (ее текст приведен в листинге 8.4) формирует список студентов, добавляя фамилии в начало списка. Данные вводятся в поля редактирования диалогового окна программы (Рисунок 8.8) и добавляются в список нажатием кнопки Добавить (suttoni).



    Графическое изображение списка

    Рисунок 8.6. Графическое изображение списка

    Графическое изображение списка

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

    Для того чтобы программа могла использовать список, надо определить тип компонентов списка и переменную-указатель на первый элемент списка. Ниже приведен пример объявления компонента списка студентов:

    type

    TPStudent = ^TStudent; // указатель на переменную типа TStudent

    // описание типа элемента списка
    TStudent = record

    surname: string[20]; // фамилия

    name: string[20];' // имя

    group: integer; // номер группы

    address: string[60]; // домашний адрес

    next: TPStudent; // указатель на следующий элемент списка
    end;

    var

    head: TPStudent; // указатель на первый элемент списка

    Добавлять данные можно в начало, в конец или в нужное место списка. Во всех этих случаях необходимо корректировать указатели. На Рисунок 8.7 изображен процесс добавления элементов в начало списка.

    После добавления второго элемента в список head указывает на этот элемент



    Инструкция with

    Инструкция with

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

    with Имя do

    begin

    ( инструкции программы } end;

    где:

  • имя — имя переменной-записи;
  • with — зарезервированное слово языка Delphi, означающее, что далее, до слова end, при обращении к полям записи имя, имя записи можно не указывать.
  • Например, если в программе объявлена запись

    student:record // информация о студенте

    f_name: string[30]; // фамилия
    l_name: string[20]; // имя
    address: string[50]; // адрес
    end;

    и данные о студенте находятся в полях Edit1, Edit2 и Edit3 диалогового окна, то вместо инструкций

    student.f_name := Editl.text;
    student.l_name := Edit2.text;
    student.address := Edit3.text;

    можно записать:

    with student do begin

    f_name := Edit1.text; f_name := Edit2.text; address := Edit3.text;
    end;

    Интервальный тип

    Интервальный тип

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

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

    Тип = НижняяГраница..ВерхняяГраница;

    где:

  • тип — имя объявляемого интервального типа данных;
  • НижняяГраница — наименьшее значение, которое может принимать переменная объявляемого типа;
  • верхняяГраница — наибольшее значение, которое может принимать переменная объявляемого типа.
  • Примеры:

    TIndex = 0 .. 100; TRusChar = 'А' .. 'я';

    В объявлении интервального типа можно использовать именованные константы. В следующем примере в объявлении интервального типа TIndex использована именованная константа HBOUND:

    const

    HBOUND=100;
    type

    TIndex=l..HBOUND;

    Интервальный тип удобно использовать при объявлении массивов, например, так:

    type

    TIndex =1 .. 100;
    var

    tab1 : array[TIndex] of integer; i:TIndex;

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

    type

    TMonth = (Jan, Feb, Mar, Apr, May, Jun,

    Jul, Aug, Sep, Oct, Nov, Dec);
    TSammer = Jun.. Aug;

    Добавление записей в файл

    Листинг 8.1. Добавление записей в файл

    unit аррrес_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls;

    type

    TForm1 = class(TForm) Label1: TLabel;
    Label2: TLabel; Label3: TLabel;

    Edit1: TEdit; // спортсмен

    ComboBoxl: TComboBox; // страна
    ComboBox2: TComboBox; // вид спорта
    RadioGroup1: TRadioGroup; // медаль
    Buttonl: TButton; // кнопка Добавить
    Labels: TLabel;

    Label4: TLabel;

    procedure FormActivate(Sender: TObject);


    procedure FormClose(Sender: TObject;
    var Action: TCloseAction)

    procedure ButtonlClick(Sender: TObject);

    private

    { Private declarations } public

    { Public declarations } end;

    // тип медали

    TKind = (GOLD, SILVER, BRONZE);


    // запись файла

    TMedal=record

    country: string[20]; // страна
    sport: string[20]; // вид спорта

    person: string[40]; // спортсмен
    kind: TKind; // медаль
    end;

    var

    Form1: TForm1;

    f: file of TMedal; // файл записей — база данных

    implementation

    {$R *.DFM}

    // активизация формы

    procedure TForm1.FormActivate(Sender: TObject);


    var

    resp : word; // ответ пользователя
    begin

    AssignFile(f, 'a:\medals.db');


    {$I-}

    Reset (f);
    // открыть файл

    Seek(f, FileSize(f));
    // указатель записи в конец файла

    {$I!+}

    if lOResult = 0

    then buttonl.enabled:=TRUE // теперь кнопка Добавить доступна
    else begin

    resp:=MessageDlg('Файл базы данных не найден.'
    + 'Создать новую БД?', mtlnformation,[mbYes,mbNo],0);

    if resp = mrYes then begin {$I-}

    rewrite(f);
    {$!+}
    if lOResult = 0

    then buttonl.enabled:=TRUE

    else ShowMessage('Ошибка создания файла БД.');

    end;
    end;
    end;

    // щелчок на кнопке Добавить

    procedure TForml.Button1Click(Sender: TObject);


    var

    medal: TMedal;
    begin

    with medal do begin

    country := ComboBox1.Text;
    sport := ComboBox2.Text;
    person := Edit1.Text;
    case RadioGroup1.Itemlndex of
    0: kind := GOLD;
    1: kind := SILVER;
    2: kind := BRONZE;
    end;
    end;

    write(f,medal);
    // записать содержимое полей записи в файл
    end;

    // завершение работы программы

    procedure TForm1.FormClose(Sender: TObject;
    var
    Action: TCloseAction);

    begin

    CloseFile(f);
    // закрыть файл
    end;

    end.

    В представленной программе процедура TForm1.FormActivate открывает файл базы данных для добавления. Здесь следует обратить внимание на то, как это реализовано. Процедуру AppendFile, которая открывает файл для добавления в конец, использовать нельзя, т. к. файл не является текстовым. Поэтому файл сначала открывается процедурой Rewrite в режиме перезаписи, а затем процедура Seek устанавливает указатель чтения/записи в конец файла. Параметром процедуры seek является функция Fiiesize, значение которой равно размеру файла (в байтах).

    Процедура TForm1.Button1Click, которая запускается нажатием кнопки Добавить (Buttoni), выполняет непосредственное добавление записи в файл. Поля country и sport добавляемой записи заполняются из свойства Text комбинированных списков Страна (comboBoxi) и Вид спорта (ComboBox2).

    Поле person формируемой записи заполняется из поля ввода Спортсмен (компонент Editi), а содержимое поля medal определяется выбранной кнопкой компонента RadioGroupl.

    Процедура TForm1. FormClose закрывает файл базы данных поскольку тип TMedal используется двумя процедурами (TForm1.FormActivate и TForm1.Button1Сlick), то его описание помещено в раздел type модуля формы. Объявление файловой переменной f по этой же причине помещено в раздел объявления переменных модуля формы.

    В приведенном варианте программы предполагается, что списки стран и названий видов спорта формируются при помощи редактора списка строк во время разработки формы. Вместе с тем, список можно сформировать во время разработки программы. Для этого надо к свойству items применить метод Add. Например, список стран может быть сформирован при помощи следующих инструкций (их нужно поместить в процедуру Tform1.FormActivate):

    Form1.ComboBox1.Item.Add('Россия');

    Form1.ComboBox1.Item.Add('Австрия');

    Form1.ComboBox1.Item.Add('Германия');

    Form1.ComboBox1.Item.Add('Франция');

    Чтение записей из файла

    Листинг 8.2. Чтение записей из файла

    unit rdrec_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    RadioButton1: TRadioButton; // переключатель Все
    RadioButton2: TRadioButton; // переключатель Выбрать

    // текст Страна

    Button1: TButton;

    GroupBox1: TGroupBox;

    Label1: TLabe1;

    procedure Button1Click(Sender: TObject);


    procedure RadioButton2Click(Sender: TObject);


    procedure RadioButton1Click(Sender: TObject);


    ComboBox1: TComboBox; // комбинированный список

    // для ввода названия страны

    Memol: TMemo; // поле вывода записей, удовлетворяющих

    // условию запроса

    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.Button1Click(Sender: TObject) ;
    type

    // тип медали

    TKind = (GOLD,SILVER,BRONZE);


    // запись файла

    TMedal = record

    country:string[20]; sport:string[20];
    person:string[40]; kind:TKind;
    end;
    var

    f: file of TMedal; // файл записей
    rec: TMedal; // запись, прочитанная из файла
    n: integer; // кол-во записей, удовлетворяющих запросу
    st: string[80];
    begin

    AssignFile(f,'a:\medals.db');


    {$I-}

    Reset (f);
    // открыть файл для чтения

    {$I-}

    if IOResult <>
    0 then begin

    ShowMessage('Ошибка открытия файла БД.');

    Exit;
    end;

    // обработка БД

    if RadioButton2.Checked then

    Memo1.Lines.Add('*** ' + ComboBox1.Text + ' ***');
    n := 0;

    Memol.Clear; // очистить список поля Memo
    while not EOF(f) do begin

    read(f, rec);
    // прочитать запись
    if RadioButton1.Checked or

    (rec.country = ComboBoxl.Text) then begin

    n := n + 1;

    st := rec.person+ ', ' + rec.sport;

    if RadioButtonl.Checked then

    st := st + ', '+ rec.country; case rec.kind of

    GOLD: st := st+ ', золото';
    SILVER:st := st+ ', серебро';
    BRONZE:st := st+ ', бронза';
    end;

    Memo1.Lines.Add(st);
    end;
    end;

    CloseFile(f);
    if n = 0 then

    ShowMessage('В БД нет запрашиваемой информации.');

    end;

    // переключатель Выбрать

    procedure TForm1.RadioButton2Click(Sender: TObject);


    begin

    Label1.Enabled := True;

    ComboBox1.Enabled := True; // теперь поле Страна доступно

    ComboBox1.SetFocus; // курсор в поле Страна

    end;

    // переключатель Все

    procedure TForm1.RadioButton1Click(Sender: TObject);


    begin

    Label1.Enabled := False;

    ComboBox1.Enabled := False; // теперь поле Страна не доступно
    end;

    end.

    Процедура TForm1.Button1Click открывает файл и последовательно считывает находящиеся в нем записи. Содержимое записи добавляется в поле Memol, если прочитанная запись удовлетворяет условию запроса, т. е. содержимое поля country совпадает с названием страны, введенным пользователем в поле редактирования компонента ComboBox1, или если выбран переключатель RadioButton1.

    Информация в поле Memo добавляется инструкцией Memo1.Lines.Add(st), которая является инструкцией применения метода Add (Добавить) к компоненту Memo1.

    Примечание

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

    Создание использование

    Листинг 8.3. Создание, использование и уничтожение динамических переменных

    procedure TForm1.Button1Click(Sender: TObject);
    var

    p1,p2,p3: Integer; // указатели на переменные типа integer

    begin

    // создадим динамические переменные типа integer
    // (выделим память для динамических переменных)
    New(p1);

    New(p2);

    New(p3);


    р1^ := 5;

    р2^ := 3;

    р3^ := р1^ + р2^;

    ShowMessage('Сумма чисел равна ' + IntToStr(р3^));


    // уничтожим динамические переменные

    // (освободим память, занимаемую динамическими переменными)

    Dispose(p1);


    Dispose(р2);


    Dispose(р3);

    end;


    Добавление элемента

    Листинг 8.4. Добавление элемента в начало динамического списка

    unit dlist1_; interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    Label1: TLabel;

    Label2: TLabel;

    Label3: TLabel;

    Edit1: TEdit; // фамилия

    Edit2: TEdit; // имя

    Button1: TButton; // кнопка Добавить

    Button2: TButton; // кнопка Показать

    procedure ButtonlClick(Sender: TObject);


    procedure Button2Click(Sender: TObject);

    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM)

    type

    TPStudent=^TStudent; // указатель на тип TStudent

    TStudent = record

    f_name:string[20]; // фамилия

    l_name: string[20]; // имя

    next: TPStudent; // следующий элемент списка
    end;

    var

    head: TPStudent; // начало (голова) списка

    // добавить элемент в начало списка

    procedure TForml.Button1Click(Sender: TObject);


    var

    curr: TPStudent; // новый элемент списка
    begin

    new(curr);
    // выделить память для элемента списка

    curr^.f_name := Edit1.Text;

    curr^.1_пате := Edit2.Text;

    // добавление в начало списка
    curr^.next := head; head := curr;

    // очистить поля ввода
    Edit1.text:=''; Edit2.text: = " ;
    end;

    // вывести список

    procedure TForml.Button2Click(Sender: TObject);

    var

    curr: TPStudent; // текущий элемент списка
    n:integer; // длина (кол-во элементов) списка
    st:string; // строковое представление списка
    begin n := 0; st := '';

    curr := head; // указатель на первый элемент списка
    while curr <>
    NIL do begin

    n := n + 1;

    st := st + curr^.f_name + ' ' + curr^.1_name
    +#13; curr := curr^.next;
    // указатель на следующий элемент end;

    if n <>
    0

    then ShowMessage('Список:' + #13 + st)

    else ShowMessage('В списке нет элементов.');


    end;
    end.

    Добавление элемента в список выполняет процедура TForm1.Button1Click, которая создает динамическую переменную-запись, присваивает ее полям значения, соответствующие содержимому полей ввода диалогового окна, и корректирует значение указателя head.

    Вывод списка выполняет процедура TForm1.Button2Click, которая запускается нажатием кнопки Показать. Для доступа к элементам списка используется указатель curr. Сначала он содержит адрес первого элемента списка. После того как первый элемент списка будет обработан, указателю curr присваивается значение поля next той записи, на которую указывает curr. В результате этого переменная curr содержит адрес второго элемента списка. Таким образом, указатель перемещается по списку. Процесс повторяется до тех пор, пока значение поля next текущего элемента списка (элемента, адрес которого содержит переменная curr) не окажется равно NIL.

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

    Листинг 8.5. Добавление элементов в упорядоченный список

    unit dlist2_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm)

    Label1: TLabel;

    Label2: TLabel;

    Button1: TButton;

    Button2: TButton;

    Label3: TLabel;

    Edit1: TEdit;

    Edit2: TEdit;

    procedure ButtonlClick(Sender: TObject);


    procedure Button2Click(Sender: TObject);


    procedure FormActivate(Sender: TObject);

    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    ($R *.DFM}

    type

    TPStudent=ATStudent; //указатель на тип TStudent

    TStudent = record

    f_name:string[20]; // фамилия

    l_name:string[20]; // имя

    next: TPStudent; // следующий элемент списка
    end;

    var

    head: TPStudent; // начало (голова) списка

    // добавить элемент в список

    procedure TForm1.Button1Click(Sender: TObject);


    var

    node: TPStudent; // новый узел списка

    curr: TPStudent; // текущий узел списка

    pre: TPStudent; // предыдущий, относительно curr, узел
    begin

    new(node);
    // создание нового элемента списка

    node^.f_name:=Edit1.Text; // фамилия

    node^.l_name:=Edit2.Text; // имя

    // добавление узла в список

    // сначала найдем в списке подходящее место для узла

    curr:=head;

    pre:=NIL;

    { Внимание!

    Если приведенное ниже условие заменить

    на (node. f_name>
    curr". f__name) and (currONIL) ,

    то при добавлении первого узла возникает ошибка времени

    выполнения, т. к. curr = NIL и, следовательно,

    переменной curr. *name нет!

    В используемом варианте условия ошибка не возникает, т. к.

    сначала проверяется условие (curr о NIL), значение которого

    FALSE, и второе условие в этом случае не проверяется.

    }

    while (curr о NIL) and (node.f_name >
    curr^.f_name) do

    begin

    // введенное значение больше текущего pre:= curr;

    curr:=curr^.next; // к следующему узлу
    end;

    if pre = NIL then

    begin

    // новый узел в начало списка
    node^. next: =head; head:=node;
    end
    else

    begin

    // новый узел после pre, перед
    curr node^.next:=рre^.next;
    рrе^.next:=node;
    end;

    Edit1.text:='';
    Edit2.text:='';
    Edit1.SetFocus;
    end;

    // отобразить список

    procedure TForm1.Button2Click(Sender: TObject);


    var

    curr: TPStudent; // текущий элемент списка
    n:integer; // длина (кол-во элементов) списка

    at:string; // строковое представление списка
    begin
    n:=0;
    st: = '';
    curr:=head;
    while curr <>
    NIL
    do
    begin n:=n+l;

    st:=st+curr^.f_name+' '+currA.l_name+#13;
    curr:=curr^.next;
    end; if n <>
    0

    then ShowMessage('Список: '+ЦЗ+st)
    else ShowMessage('В списке нет элементов.');

    end;

    // начало работы программы

    procedure TForm1.FormActivate(Sender: TObject);


    begin

    head:=NIL; // список пустой
    end;
    end.

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



    Удаление узла из списка

    Листинг 8.6. Удаление узла из списка

    unit dlist2_;
    interface
    uses
    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs,
    StdCtrls;
    type
    TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Button1: TButton;
    Button2: TButton;
    Label3: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);

    procedure FormActivate(Sender: TObject);

    private
    { Private declarations }
    public
    { Public declarations }
    end;
    var
    Form1: TForm1;
    implementation
    {$R *.DFM}
    type
    TPStudent=^TStudent; //указатель на тип TStudent
    TStudent = record
    f_name:string[20]; // фамилия
    l_name:string[20]; // имя
    next: TPStudent; // следующий элемент списка
    end;
    var
    head: TPStudent; // начало (голова) списка
    procedure TForm1.Button1Click(Sender: TObject);

    var
    node: TPStudent; // новый узел списка
    curr: TPStudent; // текущий узел списка
    pre: TPStudent; // предыдущий, относительно curr, узел
    begin
    new(node);
    // создание нового элемента списка
    node^.f_name:=Edit1.Text; // фамилия
    node^.l_name:=Edit2.Text; // имя
    // добавление узла в список
    // сначала найдем подходящее место в списке для узла
    curr:=head;
    pre:=NIL;
    { Внимание!
    если приведенное ниже условие заменить
    на (node.f_name>
    curr^.f_name)and(curr<>
    NIL)
    то при добавлении первого узла возникает ошибка времени
    выполнения, так как curr = NIL и, следовательно,
    переменной curr.^name нет!
    В используемом варианте условия ошибка не возникает, так как
    сначала проверяется условие (curr <>
    NIL), значение которого
    FALSE и второе условие в этом случае не проверяется.
    }
    while (curr <>
    NIL)and(node.f_name >
    curr^.f_name) do
    begin
    // введенное значение больше текущего
    pre:= curr;
    curr:=curr^.next; // к следующему узлу
    end;
    if
    pre = NIL
    then
    begin

    // новый узел в начало списка
    node^.next:=head;
    head:=node;
    end
    else
    begin

    // новый узел после pre, перед curr
    node^.next:=pre^.next;
    pre^.next:=node;
    end;
    Edit1.text:='';
    Edit2.text:='';
    Edit1.SetFocus;
    end;
    procedure TForm1.Button2Click(Sender: TObject);

    var
    curr: TPStudent; // текущий элемент списка
    n:integer; // длина (кол-во элементов) списка
    st:string; // строковое представление списка
    begin
    n:=0;
    st:='';
    curr:=head;
    while curr <>
    NIL do
    begin
    n:=n+1;
    st:=st+curr^.f_name+' '+curr^.l_name+#13;
    curr:=curr^.next;
    end;
    if n <>
    0
    then ShowMessage('Список:'+#13+st)
    else ShowMessage('В списке нет элементов.');

    end;
    procedure TForm1.FormActivate(Sender: TObject);

    begin
    head:=NIL;
    end;
    end.

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

    Объявление записи

    Объявление записи

    Как любой тип, создаваемый программистом, тип "запись" должен быть объявлен в разделе type. В общем виде объявление типа "запись" выглядит так:

    Имя = record

    Поле_1 : Тип_1; Поле_2 : Тип_2; Поле_К : Тип_К; end;

    где:

  • Имя — имя типа "запись";
  • record — зарезервированное слово языка Delphi, означающее, что далее следует объявление компонентов (полей) записи;
  • поле_i и тил_i — имя и тип i-го компонента (поля) записи, где i=1, ..., k;
  • end — зарезервированное слово языка Delphi, означающее, что список полей закончен.
  • Примеры объявлений:

    type

    TPerson = record

    f_name: string[20];

    l_name: string[20];

    day: integer;

    month: integer;

    year: integer;

    address: string[50]; end;

    TDate = record

    day: integer; month: integer; year: integer;
    end;

    После объявления типа записи можно объявить переменную-запись (или просто запись), например:

    var

    student : TPerson; birthday : TDate;

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

    ShowMessage('Имя: ', student.f_name + #13 + 'Адрес: ', student.address);

    выводит на экран содержимое полей f_name (имя) и address (адрес) переменной-записи student.

    Иногда тип переменной-записи объявляют непосредственно в разделе объявления переменных. В этом случае тип записи указывается сразу за именем переменной, через двоеточие. Например, запись student может быть объявлена в разделе var следующим образом:

    student: record

    f_name:string[20];

    l_name:string[20];

    day:integer;

    month:integer;

    year:integer;

    address:string[50];
    end;

    Окно программы Чтение записей из файла

    Рисунок 8.4. Окно программы Чтение записей из файла


    Окно программы Чтение записей из файла





    Окно программы Динамический список

    Рисунок 8.13. Окно программы Динамический список


    Окно программы Динамический список


    Рисунок 8.8. Окно программы Динамический список 1

    Окно программы Динамический список


    Окно программы Добавление записи в файл

    Рисунок 8.1. Окно программы Добавление записи в файл

    Окно программы Добавление записи в файл

    Для ввода фамилии спортсмена применяется поле редактирования (компонент Edit). Для ввода названия вида спорта и страны используются компоненты ComboBox (комбинированный список).

    Компонент ComboBox, значок которого находится на вкладке Standard (Рисунок 8.2), дает возможность ввести данные либо непосредственно в поле ввода-редактирования, либо путем выбора из списка, который появляется в результате щелчка на кнопке раскрывающегося списка.



    Перечисляемый тип

    Перечисляемый тип

    Определить перечисляемый тип — это значит перечислить все значения, которые может принимать переменная, относящаяся к данному типу.

    В общем виде объявление перечисляемого типа выглядит так:

    Тип =( Значение1, Значение2, ... Значение i)

    где:

  • тип — имя перечисляемого типа данных;
  • Значение i — символьная константа, определяющая одно из значений, которое может принимать переменная типа Тип.
  • Примеры:

    TDayOfWeek = (MON,TUE,WED,THU,FRI,SAT,SUN);
    TColor = (Red,Yellow,Green);

    Примечание

    Согласно принятому в Delphi соглашению, имена типов должны начинаться с буквы Т (от слова Туре — тип).

    После объявления типа можно объявить переменную, относящуюся к этому типу, например:

    type

    TDayOfWeek = (MON,TUE,WED,THU, FRI,SAT,SUN) ;
    var

    ThisDay, LastDay: TDayOfWeek;

    Помимо указания значений, которые может принимать переменная, описание типа задает, как значения соотносятся друг с другом. Считается, что самый левый элемент списка значений является минимальным, а самый правый — максимальным. Для элементов типа DayOfWeek справедливо:

    MON < TUE < WED < THU < FRI < SAT < SUN

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

    if (Day = SAT) OR (Day = SUN) then
    begin

    { действия, если день — суббота или воскресенье }
    end;

    Приведенную инструкцию можно записать и так:

    if Day > FRI then begin

    { действия, если день — суббота или воскресенье }
    end;

    Очевидно, что программа, написанная с использованием объявленного программистом типа, более наглядна, легче читается и, следовательно, уменьшается вероятность появления ошибки.

    Во время компиляции Delphi проверяет соответствие типа переменной типу выражения, которое присваивается переменной. Если тип выражения не может быть приведен к типу переменной, то выводится сообщение об ошибке.

    Например, в фрагменте программы

    type

    TDayOfWeek = (MON, TUE, WED, THU, FRI, SAT, SUN) ;

    ThisDay: TDayOfWeek; begin

    ThisDay:=1;

    if ThisDay = 6 then begin

    { блок инструкций } end;

    инструкция ThisDay:= i; ошибочна, т. к. переменная ThisDay принадлежит к определенному программистом перечисляемому типу TDayOfWeek, а константа, значение которой ей присваивается, принадлежит к целому типу (integer). В условии инструкции if тоже ошибка.

    Можно утверждать, что объявление перечисляемого типа — это сокращенная форма записи объявления именованных констант. Например, приведенное выше объявление типа TDayOfWeek равносильно следующему объявлению:

    const

    MON=0; TUE=1; WED=2; THU=3; FRI=4; SAT=5; SUN=6;

    Переменнаяуказатель

    Рисунок 8.5. Переменная-указатель

    Переменнаяуказатель

    Указатель, как и любая другая переменная программы, должен быть объявлен в разделе объявления переменных. В общем виде объявление указателя выглядит следующим образом:

    Имя: ^ Тил;

    где:

  • имя — имя переменной-указателя;
  • Тип — тип переменной, на которую указывает переменная-указатель;
  • значок ^ показывает, что объявляемая переменная является указателем.

    Приведем примеры объявления указателей:

    p1: ^integer; р2: ^real;

    В приведенном примере переменная p1 — это указатель на переменную типа integer, a p2 — указатель на переменную типа real.

    Тип переменной, на которую ссылается указатель, называют типом указателя. Например, если в программе объявлен указатель р: ^integer, то говорят: ^р — указатель целого типа" или "р — это указатель на целое".

    В начале работы программы переменная-указатель "ни на что не указывает". В этом случае говорят, что значение указателя равно NIL. Зарезервированное слово NIL соответствует значению указателя, который ни на что не указывает.

    Идентификатор NIL можно использовать в инструкциях присваивания и в условиях. Например, если переменные pi и р2 объявлены как указатели, то инструкция

    p1 := NIL;

    устанавливает значение переменной, а инструкция if р2 = NIL then ShowMessage('Указатель р2 не инициализирован!');

    проверяет, инициализирован ли указатель р2.

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

    р := @n;

    Помимо адреса переменной, указателю можно присвоить значение другого указателя при условии, что они являются указателями на переменную одного типа. Например, если переменные pi и р2 являются указателями типа integer, то в результате выполнения инструкции

    p2 := p1;

    переменные pi и р2 указывают на одну и ту же переменную.

    Указатель можно использовать для доступа к переменной, адрес которой содержит указатель. Например, если р указывает на переменную 1, то в результате выполнения инструкции

    р^ : = 5;

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


    Пример упорядоченного списка сформированного программой

    Рисунок 8.11. Пример упорядоченного списка, сформированного программой

    Пример упорядоченного списка сформированного программой

    Вывод списка выполняет процедура TForml.Button2Сlick, которая запускается нажатием кнопки Показать. После запуска программы и ввода нескольких фамилий, например, в такой последовательности: Иванов, Яковлев, Алексеев, петров, список выглядит так, как показано на Рисунок 8.11.

    Списки

    Списки

    Указатели и динамические переменные позволяют создавать сложные динамические структуры данных, такие как списки и деревья.

    Список можно изобразить графически (Рисунок 8.6).



    Свойства компонента ComboBox

    Таблица 8.1. Свойства компонента ComboBox

    Свойство

    Определяет

    Name

    Имя компонента. Используется для доступа к свойствам компонента

    Text

    Текст, находящийся в поле ввода-редактирования

    Items

    Элементы раскрывающегося списка

    DropDownCount

    Количество отображаемых элементов в раскрытом списке

    Left

    Расстояние от левой границы компонента до левой границы формы

    Top

    Расстояние от верхней границы компонента до верхней границы формы

    Height

    Высоту компонента (поля ввода-редактирования)

    Width

    Ширину компонента

    Font

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

    ParentFont

    Признак наследования свойств шрифта родительской формы

    Список, который появляется в результате щелчка на кнопке раскрытия списка, может быть сформирован как в процессе разработки формы приложения, так и во время работы программы. Чтобы сформировать список во время разработки формы, нужно в окне Object Inspector выбрать свойство Items, щелкнуть на кнопке активизации редактора списка строк (кнопка с тремя точками) и ввести элементы списка (Рисунок 8.3).



    Значения свойств компонентов

    Таблица 8.2. Значения свойств компонентов

    Свойство

    Значение

    RadioButton1 . Checked

    True

    Label1 .Enabled

    False

    ComboBox1 . Enabled

    False

    Memo1 . Readonly

    True

    Memo1. ScroiiBars

    ssVertical

    Для ввода названия страны используется компонент ComboBox1, что позволяет задавать имя не только прямым вводом названия, но и выбором из списка. Список стран нужно сформировать во время создания формы путем присвоения значения свойству items.

    Чтобы сразу после запуска программы список выбора страны был недоступен (т. к. выбран переключатель все группы Показать), свойству Enabled компонентов ComboBox1 и Label1 во время создания формы нужно присвоить значение False.

    Список ввода-выбора названия страны (ComboBox1) становится доступным в результате выбора во время работы программы переключателя выбрать. Процедура обработки события Onclick на переключателе RadioButton2 делает доступным поле ComboBox1.



    Удаление элемента из списка

    Рисунок 8.12. Удаление элемента из списка

    Удаление элемента из списка

    Поскольку узел является динамической переменной, то после исключения узла из списка занимаемая им память должна быть освобождена. Освобождение динамической памяти, или, как иногда говорят, "уничтожение переменной", выполняется вызовом процедуры dispose. У процедуры dispose один параметр — указатель на динамическую переменную. Память, занимаемая этой динамической переменной, должна быть освобождена. Например, в программе

    var

    р: ^integer;
    begin

    new(p);

    { инструкции программы } dispose(p);
    end

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

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

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

    Удаление узла из списка выполняет процедура TForm1.Button3Click, которая запускается нажатием кнопки Удалить (Buttons). Текст процедуры приведен в листинге 8.6.



    Указатели

    Указатели

    Обычно переменная хранит некоторые данные. Однако помимо обычных, существуют переменные, которые ссылаются на другие переменные. Такие переменные называются указателями. Указатель — это переменная, значением которой является адрес другой переменной или структуры данных. Графически указатель может быть изображен так, как на Рисунок 8.5.



    Упорядоченный список

    Упорядоченный список

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


    Ввод и вывод записей в файл

    Ввод и вывод записей в файл

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

    type

    ТРеrson = record

    f_riame: string [20] ;

    l_name: string[20];

    address: string[50]; end; var

    f: file of TPerson;

    объявляют файл, компонентами которого являются записи типа TPerson.

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


    Рисунок 8.3. Ввод списка для компонента ComboBox2 во время создания формы приложения

    <title>(.*)</title>

    Полный текст программы приведен в листинге 8.1.



    Запись

    Запись

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

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

    Итак, запись — это структура данных, состоящая из отдельных именованных компонентов разного типа, называемых полями.

    Значок компонента ComboBox В табл

    Рисунок 8.2. Значок компонента ComboBox В табл. 8.1 перечислены свойства компонента ComboBox.


    Значок компонента ComboBox В табл





    Основы языка Delphi

    Диалоговое окно программы Полиморфизм

    Рисунок 9.1. Диалоговое окно программы Полиморфизм


    Диалоговое окно программы Полиморфизм





    Директивы protected и private

    Директивы protected и private

    Помимо объявления элементов класса (полей, методов, свойств) описание класса, как правило, содержит директивы protected (защищенный) и private (закрытый), которые устанавливают степень видимости элементов класса в программе.

    Элементы класса, объявленные в секции protected, доступны только в порожденных от него классах. Область видимости элементов класса этой секции не ограничивается модулем, в котором находится описание класса. Обычно в секцию protected помещают описание методов класса.

    Элементы класса, объявленные в секции private, видимы только внутри модуля. Эти элементы не доступны за пределами модуля, даже в производных классах. Обычно в секцию private помещают описание полей класса, а методы, обеспечивающие доступ к этим полям, помещают в секцию protected.

    Ниже приведено описание класса TPerson, в которое включены директивы управления доступом.

    TPerson = class private

    FName: TName; // значение свойства Name
    FAddress: TAddress; // значение свойства Address
    protected

    Constructor Create(Name:TName);
    Function GetName: TName;
    Function GetAddress: TAddress;
    Procedure SetAddress(NewAddress:TAddress);
    Property Name: TName

    read GetName;
    Property Address: TAddress

    read GetAddress
    write SetAddress;
    end;

    Примечание

    Иногда нужно полностью скрыть элементы класса. В этом случае определение класса следует поместить в отдельный модуль, а в программу, которая использует объекты этого класса, поместить ссылку на модуль.

    Исторически сложилось так, что программирование

    Глава 9. Введение в объектно-ориентированное программирование

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

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

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



    Инкапсуляция и свойства объекта

    Инкапсуляция и свойства объекта

    Под инкапсуляцией понимается скрытие полей объекта с целью обеспечения доступа к ним только посредством методов класса.

    В языке Delphi ограничение доступа к полям объекта реализуется при помощи свойств объекта. Свойство объекта характеризуется полем, сохраняющим значение свойства, и двумя методами, обеспечивающими доступ к полю свойства. Метод установки значения свойства называется методом записи свойства (write), а метод получения значения свойства — методом чтения свойства (read).

    В описании класса перед именем свойства записывают слово property (свойство). После имени свойства указывается его тип, затем — имена методов, обеспечивающих доступ к значению свойства. После слова read указывается имя метода, обеспечивающего чтение свойства, после слова write — имя метода, отвечающего за запись свойства.

    Ниже приведен пример описания класса TPerson, содержащего два свойства: Name И Address.

    type

    TName = string[15]; TAddress = string[35];

    TPerson = class // класс
    private

    FName: TName; // значение свойства Name

    FAddress: TAddress; // значение свойства Address
    Constructor Create(Name:Tname);
    Procedure Show;
    Function GetName: TName;
    Function GetAddress: TAddress;
    Procedure SetAddress(NewAddress:TAddress);
    public

    Property Name: Tname // свойство Name

    read GetName; // доступно только для чтения
    Property Address: TAddress // свойство Address

    read GetAddress // доступно для чтения
    write SetAddress; // и записи
    end;

    В программе для установки значения свойства не нужно записывать инструкцию применения к объекту метода установки значения свойства, а надо записать обычную инструкцию присваивания значения свойству. Например, чтобы присвоить значение свойству Address объекта student, достаточно записать

    student.Address := 'С.Петербург,
    ул.Садовая 21, кв.3';

    Компилятор перетранслирует приведенную инструкцию присваивания значения свойству в инструкцию вызова метода

    student.SetAddress('С.Петербург,
    ул.Садовая 21, кв.3');

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

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

    Оформление данных объекта как свойства позволяет ограничить доступ к полям, хранящим значения свойств объекта: например, можно разрешить только чтение. Для того чтобы инструкции программы не могли изменить значение свойства, в описании свойства надо указать лишь имя метода чтения. Попытка присвоить значение свойству, предназначенному только для чтения, вызывает ошибку времени компиляции. В приведенном выше описании класса TPerson свойство Name доступно только для чтения, а свойство Address — для чтения и записи.

    Установить значение свойства, защищенного от записи, можно во время инициализации объекта. Ниже приведены методы класса TPerson, обеспечивающие создание объекта класса TPerson и доступ к его свойствам.

    // конструктор объекта TPerson
    Constructor TPerson.Create(Name:TName);
    begin

    FName:=Name; end;

    // метод получения значения свойства Name

    Function TPerson.GetName;

    begin

    Result:=FName; end;

    // метод получения значения свойства Address

    function TPerson.GetAddress;

    begin

    Result:=FAddress; end;

    // метод изменения значения свойства Address
    Procedure TPerson.SetAddress(NewAddress:TAddress);
    begin

    if FAddress =' '

    then FAddress := NewAddress;
    end;

    Приведенный конструктор объекта TPerson создает объект и устанавливает значение поля FName, определяющего значение свойства Name.

    Инструкции программы, обеспечивающие создание объекта класса трегзоп и установку его свойства, могут быть, например, такими:

    student := TPerson.Create('Иванов');
    student.Address := 'ул. Садовая, д.3, кв.25';

    Класс

    Класс

    Классический язык Pascal позволяет программисту определять свои собственные сложные типы данных — записи (records). Язык Delphi, поддерживая концепцию объектно-ориентированного программирования, дает возможность определять классы. Класс — это сложная структура, включающая, помимо описания данных, описание процедур и функций, которые могут быть выполнены над представителем класса — объектом.

    Вот пример объявления простого класса:

    TPerson = class
    private

    fname: string[15]; faddress: string[35];
    public

    procedure Show;
    end;

    Данные класса называются полями, процедуры и функции — методами.

    В Приведенном Примере TPerson — это имя класса, fname и faddress - имена полей, show — имя метода.

    Примечание

    Согласно принятому в Delphi соглашению, имена полей должны начинаться с буквы f (от слова field — поле).

    Описание класса помещают в программе в раздел описания типов (type).

    Классы и объекты Delphi

    Классы и объекты Delphi

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

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

    type

    TForm1 = class(TForm)
    private

    { Private declarations }
    public

    { Public declarations }
    end;
    var

    Form1: Tform1

    Это описание класса исходной, пустой формы приложения и объявление объекта — формы приложения.

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

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

    Демонстрация полиморфизма

    Листинг 9.1. Демонстрация полиморфизма

    unit polimor_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;

    type

    TForm1 = class(TForm) Edit1: TEdit;
    Edit2: TEdit;
    GroupBoxl: TGroupBox;
    RadioButton1: TRadioButton;
    RadioButton2: TRadioButton;
    Label1: TLabel;
    Label2: TLabel;
    Button1: TButton;

    Button2: TButton;

    procedure ButtonlClick(Sender: TObject);


    procedure Button2Click(Sender: TObject);


    private

    { Private declarations }
    public

    { Public declarations }
    end;
    type

    // базовый класс

    TPerson = class

    fName: string; // имя
    constructor Create(name:string);

    function info:string; virtual;

    end;

    // класс Студент TStud = class(TPerson)

    fGr:integer; // номер группы

    constructor Create(name:string;gr:integer);


    function info:string;
    override;
    end;

    // класс Преподаватель

    TProf = class (TPerson)

    fdep:string; // название кафедры
    constructor Create(name:string;dep:string);

    function info:string;
    override;

    end;

    const

    SZL = 10; // размер списка

    var

    Forml: TForm1;

    List: array[l..SZL] of TPerson; // список

    n:integer =0; // кол-во людей в списке

    implementation

    {$R *.DFM}

    constructor TPerson.Create(name:string);
    begin

    fName := name; end;

    constructor TStud.Create(name:string;gr:integer);
    begin

    inherited create(name);
    // вызвать конструктор базового класса

    fGr := gr; end;

    constructor TProf.create(name:string; dep:string);

    begin

    inherited create(name);
    // вызвать конструктор базового класса

    fDep := dep; end;

    function TPerson.Info:string;
    begin

    result := fname; end;

    function TStud.Info:string;
    begin

    result := fname + ' rp.' + IntToStr(fGr);
    end;

    function TProf.Info:string;
    begin

    result := fname + ' каф.' + fDep;
    end;

    // щелчок на кнопке Добавить

    procedure TForml.ButtonlClick(Sender: TObject);

    begin

    if n < SZL then begin

    // добавить объект в список
    n:=n+l;
    if Radiobuttonl.Checked

    then // создадим объект TStud

    List[n]:=TStud.Create(Edit1.Text,StrToInt(Edit2.Text))
    else // создать объект TProf

    List[n]:=TProf.Create(Edit1.Text,Edit2.Text);
    // очистить поля ввода
    Edit1.Text := '' ; Edit2.Text := '';

    Edit1.SetFocus; // курсор в поле Фамилия
    end

    else ShowMessage('Список заполнен!');

    end;

    // щелчок на кнопке Список

    procedure TForm1.Button2Click(Sender: TObject);


    var

    i:integer; // индекс

    st:string; // список begin

    for i:=1 to SZL do

    if list[i] <>
    NIL then st:=st + list[i].info + 113;

    ShowMessage('Cпиcoк'+#13+st);
    end;

    end.

    Процедура TForml.Buttoniciick, которая запускается нажатием кнопки Добавить (Buttonl), создает объект iist[n] класса TStud или TProf. Класс создаваемого объекта определяется состоянием переключателя RadioButton. Установка переключателя в положение студент (RadioButtoni) определяет класс TStud, а в положение преподаватель (RadioButton2) — класс TProf.

    Процедура TForm1.Button2Сlick, которая запускается нажатием кнопки Список (Button2), применяя метод info к каждому объекту списка (элементу массива), формирует строку, представляющую собой весь список.

    Метод

    Метод

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

    professor. Show;

    вызывает применение метода show к объекту professor. Фактически инструкция применения метода к объекту — это специфический способ записи инструкции вызова процедуры.

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

    Ниже приведен пример определения метода show класса TPerson

    // метод Show класса TPerson procedure TPerson.Show;
    begin

    ShowMessage( 'Имя:' + fname + #13
    + 'Адрес:' + faddress );
    end;

    Примечание

    В инструкциях метода доступ к полям объекта осуществляется без указания имени объекта.

    Наследование

    Наследование

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

    В объявлении класса-потомка указывается класс родителя. Например, класс TEmployee (сотрудник) может быть порожден от рассмотренного выше класса TPerson путем добавления поля FDepartment (отдел). Объявление класса TEmplioyee в этом случае может выглядеть так:

    TEmployee = class(TPerson)

    FDepartment: integer; // номер отдела

    constructor Create(Name:TName; Dep:integer);
    end;

    Заключенное в скобки имя класса TPerson показывает, что класс TEmployee является производным от класса TPerson. В свою очередь, класс TPerson является базовым для класса TEmployee.

    Класс TEmpioyee должен иметь свой собственный конструктор, обеспечивающий инициализацию класса-родителя и своих полей. Вот пример реализации конструктора класса TEmployee:

    constructor TEmpioyee.Create(Name:Tname;Dep:integer);
    begin

    inherited Create(Name);

    FDepartment:=Dep;
    end;

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

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

    engineer := TEmployee.Create('Сидоров',413);
    engineer.address := 'ул.Блохина, д.8, кв.10';

    Первая инструкция создает объект типа TEmployee, вторая — устанавливает значение свойства, которое относится к родительскому классу.

    Объект

    Объект

    Объекты как представители класса объявляются в программе в разделе var, например:

    var

    student: TPerson; professor: TPerson;

    Примчание

    В Delphi объект — это динамическая структура. Переменная-объект содержит не данные, а ссылку на данные объекта. Поэтому программист должен позаботиться о выделении памяти для этих данных.

    Выделение памяти осуществляется при помощи специального метода класса — конструктора, которому обычно присваивают имя Create (создать). Для того чтобы подчеркнуть особую роль и поведение конструктора, в описании класса вместо слова procedure используется слово constructor.

    Ниже приведено описание класса TPerson, в состав которого введен конструктор:

    TPerson = class private

    fname: string [ 15 ];
    faddress: string[35];
    constructor Cireate; // конструктор
    public

    procedure show; // метол
    end;

    Выделение памяти для данных объекта происходит путем присваивания значения результата применения метода-конструктора к типу (классу) объекта. Например, после выполнения инструкции

    professor := TPerson.Create;

    выделяется необходимая память для данных объекта professor.

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

    constructor TPerson.Create;
    begin

    fname := '';

    faddress := '';
    end;

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

    После объявления и инициализации объект можно использовать, например, установить значение поля объекта. Доступ к полю объекта осуществляется указанием имени объекта и имени поля, которые отделяются друг от друга точкой. Хотя объект является ссылкой, правило доступа к данным с помощью ссылки, согласно которому после имени переменной, являющейся ссылкой, надо ставить значок ^, на объекты не распространяется.

    Например, для доступа к полю fname объекта professor вместо professor*.fname надо писать

    professor.fname

    Очевидно, что такой способ доступа к полям объекта более естественен.

    Если в программе какой-либо объект больше не используется, то можно освободить память, занимаемую полями данного объекта. Для выполнения этого действия используют метод-деструктор Free. Например, для того, чтобы освободить память, занимаемую полями объекта professor, достаточно записать

    professor.Free;

    Полиморфизм и виртуальные методы

    Полиморфизм и виртуальные методы

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

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

    tуре

    // базовый класс TPerson = class

    fname: string; // имя

    constructor Create(name:string);

    function info: string;
    virtual;
    end;

    // производный от TPerson TStud = class(TPerson)

    fgr:integer; // номер учебной труппы

    constructor Create(name:string;gr:integer);

    function info: string; override; end;

    // производный от TPerson TProf = class(TPerson)

    fdep:string; // название кафедры

    constructor Create(name:string;dep:string);

    function info: string;
    override;
    end;

    В каждом из этих классов определен метод info. В базовом классе при помощи директивы virtual метод info объявлен виртуальным. Объявление метода виртуальным дает возможность дочернему классу произвести замену виртуального метода своим собственным. В каждом дочернем классе определен свой метод info, который замещает соответствующий метод родительского класса (метод порожденного класса, замещающий виртуальный метод родительского класса, помечается директивой override).

    Ниже приведено определение метода info для каждого класса.

    function TPerson.info:string;
    begin

    result := '';
    end;

    function TStud.info:string;
    begin

    result := fname + ' гp.' + IntTostr(fgr);
    end;

    function TProf.info:string;
    begin

    result := fname + ' каф.' + fdep;
    end;

    Так как оба класса порождены от одного и того же базового, объявить список студентов и преподавателей можно так (здесь следует вспомнить, что объект — это указатель):

    list: array[l..SZL] of TPerson;

    Объявить подобным образом список можно потому, что язык Delphi позволяет указателю на родительский класс присвоить значение указателя на дочерний класс. Поэтому элементами массива list могут быть как объекты класса TStud, так и объекты класса TProf.

    Вывести список студентов и преподавателей можно применением метода info к элементам массива. Например, так:

    st := '';

    for i:=l to SZL do // SZL - размер массива-списка
    if list[i] о NIL

    then st := st + list[i].Info
    + #13; ShowMessage (st);

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

    Следующая программа, используя рассмотренные выше объявления классов TPerson, TStud и TProf, формирует и выводит список студентов и преподавателей. Текст программы приведен в листинге 9.1, а диалоговое окно — на Рисунок 9.1.



    Основы языка Delphi

    Битовые образы

    Битовые образы

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

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

    Например, если в программе объявлена переменная pic типа TBitMap, то после выполнения инструкции

    pic.LoadFromFiie('е:\images\aplane.bmp')

    битовый образ pic будет содержать изображение самолета.

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

    Image1.Canvas.Draw(x,у, bm)

    выводит картинку битового образа bm на поверхность компонента image 1 (параметры х и у определяют положение левого верхнего угла картинки на поверхности компонента).

    Если перед применением метода Draw свойству Transparent объекта TBitMap присвоить значение True, то фрагменты рисунка, окрашенные цветом, совпадающим с цветом левого нижнего угла картинки, не будут выве-

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

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



    Дуга

    Дуга

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

    Объект.Canvas.Arc(x1,y1,х2,у2,х3,у3,х4,у4)

    где:

  • x1, y1, х2, у2 — параметры, определяющие эллипс (окружность), частью которого является вычерчиваемая дуга;
  • х3, у3 — параметры, определяющие начальную точку дуги; П х4, у4 — параметры, определяющие конечную точку дуги.
  • Начальная (конечная) точка — это точка пересечения границы эллипса и прямой, проведенной из центра эллипса в точку с координатами х3 и у3 (х4, у4). Дуга вычерчивается против часовой стрелки от начальной точки к конечной (Рисунок 10.7).

    Цвет, толщина и стиль линии, которой вычерчивается дуга, определяются значениями свойства Реп поверхности (canvas), на которую выполняется вывод.



    Форма приложения Координатная сетка

    Рисунок 10.4. Форма приложения Координатная сетка


    Форма приложения Координатная сетка





    Форма программы Движущаяся окружность

    Рисунок 10.15. Форма программы Движущаяся окружность


    Форма программы Движущаяся окружность





    Форма программы Самолет

    Рисунок 10.18. Форма программы Самолет

    Форма программы Самолет

    Для хранения битовых образов (картинок) фона и самолета, а также копии области фона, перекрываемой изображением самолета, используются объекты типа TBitMap, которые создаются динамически процедурой FormActivate. Эта же процедура загружает из файлов картинки фона (factory.bmp) и самолета (aplane.bmp), а также сохраняет область фона, на которую первый раз будет накладываться картинка.

    Сохранение копии фона выполняется при помощи метода CopyRect, который позволяет выполнить копирование прямоугольного фрагмента одного битового образа в другой. Объект, к которому применяется метод CopyRect, является приемником копии битового образа. В качестве параметров методу передаются координаты и размер области, куда должно быть выполнено копирование, поверхность, откуда должно быть выполнено копирование, а также положение и размер копируемой области. Информация о положении и размере копируемой в буфер области фона, на которую будет наложено изображение самолета и которая впоследствии должна быть восстановлена из буфера, находится в структуре BackRct типа TRect. Для заполнения этой структуры используется функция Bounds.

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

    Форма программы

    Рисунок 10.20. Форма программы

    Форма программы

    Тистинг 10.12. Мультик (использование метода CopRect)

    unit multik ;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs,

    ExtCtrls, StdCtrls;

    type

    TForm1 = class(TForm)

    Timer1: TTimer;

    procedure FormActivate(Sender: TObject);

    procedure Timer1Timer(Sender: TObject);
    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1l: TForm1;

    implementation

    ($R *.DFM}

    const

    FILMFILE = 'film2.bmp'; // фильм — bmp-файл
    N_KADR=12; // кадров в фильме (для данного файла)

    var

    Film: TBitMap; // фильм — все кадры

    WKadr,HKadr: integer; // ширина и высота кадра

    CKadr: integer; // номер текущего кадра

    RectKadr: TRect; // положение и размер кадра в фильме

    Rect1 : Trect; // координаты и размер области отображения фильма

    procedure TForm1.FormActivate(Sender: TObject);
    begin

    Film := TBitMap.Create;
    Film.LoadFromFile(FILMFILE);
    WKadr := Round(Film.Width/N_Kadr);
    HKadr := Film.Height;

    Rect1 := Bounds(10,10,WKadr,HKadr);
    Ckadr:=0;

    Form1.Timerl.Interval := 150; // период обновления кадров — 0.15 с
    Form1.Timerl.Enabled:=True; // запустить таймер
    end;

    // отрисовка кадра procedure DrawKadr;
    begin

    // определим положение текущего кадра в фильме
    RectKadr:=Bounds(WKadr*CKadr,0,WKadr,HKadr);

    // вывод кадра из фильма

    Form1.Canvas.CopyRect(Rect1,Film*.Canvas,RectKadr);

    // подготовимся к выводу следующего кадра
    CKadr := CKadr+1;
    if CKadr = N_KADR then CKadr:=0;:

    end;

    // обработка сигнала от таймера

    procedure TForm1.Timer1Timer(Sender: TObject);

    begin

    DrawKadr;
    end;

    end.

    Программа состоит из трех процедур. Процедура TForm1. FormActivate создает объект Film и загружает в него фильм — BMP-файл, в котором находятся кадры фильма. Затем, используя информацию о размере загруженного битового образа, процедура устанавливает значения характеристик кадра: высоту и ширину.

    После этого создается объект Kadr (типа TBitMap), предназначенный для хранения текущего кадра. Следует обратить внимание, что после создания объекта Kadr принудительно устанавливаются значения свойств width и Height. Если этого не сделать, то созданный объект будет существовать, однако память для хранения битового образа не будет выделена. В конце своей работы процедура TForml. FormActivate устанавливает номер текущего кадра и запускает таймер.

    Основную работу в программе выполняет процедура DrawKadr, которая выделяет из фильма очередной кадр и выводит его в форму. Выделение кадра и его отрисовку путем копирования фрагмента картинки с одной поверхности на другую выполняет метод copyRect (Рисунок 10.21), которому в качестве параметров передаются координаты области, куда нужно копировать, поверхность и положение области, откуда нужно копировать. Положение фрагмента в фильме, т. е. координата х левого верхнего угла, определяется умножением ширины кадра на номер текущего кадра. Запускает процедуру DrawKadr процедура TForm1.Timer1Timer, обрабатывающая событие OnTiner.



    График построенный процедурой GrOfFunc

    Рисунок 10.10. График, построенный процедурой GrOfFunc

    График построенный процедурой GrOfFunc

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

    Примечание

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

    Холст

    Холст

    Как было сказано ранее, поверхности, на которую программа может выводить графику, соответствует свойство Canvas. В свою очередь, свойство canvas — это объект типа TCanvas. Методы этого типа обеспечивают вывод графических примитивов (точек, линий, окружностей, прямоугольников и т. д.), а свойства позволяют задать характеристики выводимых графических примитивов: цвет, толщину и стиль линий; цвет и вид заполнения областей; характеристики шрифта при выводе текстовой информации.

    Методы вывода графических примитивов рассматривают свойство Canvas как некоторый абстрактный холст, на котором они могут рисовать (canvas переводится как "поверхность", "холст для рисования"). Холст состоит из отдельных точек — пикселов. Положение пиксела характеризуется его горизонтальной (X) и вертикальной (Y) координатами. Левый верхний пиксел имеет координаты (0, 0). Координаты возрастают сверху вниз и слева направо (Рисунок 10.1). Значения координат правой нижней точки холста зависят от размера холста.



    Delphi позволяет программисту разрабатывать программы,

    Глава 10. Графические возможности Delphi

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

    Программа выводит графику на поверхность объекта (формы или компонента Image). Поверхности объекта соответствует свойство canvas. Для того чтобы вывести на поверхность объекта графический элемент (прямую линию, окружность, прямоугольник и т. д.), необходимо применить к свойству canvas этого объекта соответствующий метод. Например, инструкция Form1.Canvas.Rectangle (10,10,100,100) вычерчивает в окне программы прямоугольник.



    Инструкция Canvas1. CopyRect

    Рисунок 10.21. Инструкция Canvas1. CopyRect (Rect1, Canvas2, Rect2) копирует в область Rectl поверхности Canvasl область Rect2 с поверхности Canvas2

    Инструкция Canvas1. CopyRect


    Использование битовых образов

    Использование битовых образов

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

    Эффект перемещения картинки может быть создан путем периодической перерисовки картинки с некоторым смещением относительно ее прежнего положения. При этом предполагается, что перед выводом картинки в новой точке сначала удаляется предыдущее изображение. Удаление картинки может быть выполнено путем перерисовки всей фоновой картинки или только той ее части, которая перекрыта битовым образом движущегося объекта.

    В рассматриваемой программе используется второй подход. Картинка выводится применением метода Draw к свойству canvas компонента Image, a стирается путем копирования (метод copyRect) нужной части фона из буфера на поверхность компонента Image.

    Форма программы приведена на Рисунок 10.18, а текст — в листинге 10.10.

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



    Кадры мультика

    Рисунок 10.19. Кадры мультика


    Кадры мультика





    Карандаш и кисть

    Карандаш и кисть

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

    Карандашу и кисти, используемым для вывода графики на холсте, соответствуют свойства Реn (карандаш) и Brush (кисть), которые представляют собой объекты типа треп и TBrush, соответственно. Значения свойств этих объектов определяют вид выводимых графических элементов.

    Карандаш

    Карандаш

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



    Кисть

    Кисть

    Кисть (canvas.Brush) используется методами, обеспечивающими вычерчивание замкнутых областей, например геометрических фигур, для заливки (закрашивания) этих областей. Кисть, как объект, обладает двумя свойствами, перечисленными в табл. 10.5.



    Координаты области вывода текста

    Рисунок 10.3. Координаты области вывода текста

    Координаты области вывода текста

    Шрифт, который используется для вывода текста, определяется значением свойства Font соответствующего объекта canvas. Свойство Font представляет собой объект типа TFont. В табл. 10.7 перечислены свойства объекта TFont, позволяющие задать характеристики шрифта, используемого методами TextOut и TextRect для вывода текста.



    Координаты точек холста

    Рисунок 10.1. Координаты точек холста

    Координаты точек холста

    Размер холста можно получить, обратившись к свойствам Height и width области иллюстрации (image) или к свойствам формы: ClientHeight и Clientwidth.

    Линия

    Линия

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

    Компонент.Canvas.LineTo(x,у)

    Метод LinеТо вычерчивает прямую линию от текущей позиции карандаша в точку с координатами, указанными при вызове метода.

    Начальную точку линии можно задать, переместив карандаш в нужную точку графической поверхности. Сделать это можно при помощи метода MoveTo, указав в качестве параметров координаты нового положения карандаша.

    Вид линии (цвет, толщина и стиль) определяется значениями свойств объекта Реп графической поверхности, на которой вычерчивается линия.

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



    Стили заполнения областей

    Листинг 10.1. Стили заполнения областей

    unit brustyle_; interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, ExtCtrls;

    type

    TForm1 = class(TForm)

    procedure FormPaint(Sender: TObject);

    private

    { Private declarations}
    public

    { Public declarations )
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    // перерисовка формы

    procedure TForm1.FormPaint(Sender: TObject);


    const

    bsName: array[1..8] of string =

    ('bsSolid','bsClear','bsHorizontal',
    'bsVertical','bsFDiagonal','bsBDiagonal',
    'bsCross','bsDiagCross');

    var

    x,y: integer; // координаты левого верхнего угла прямоугольника

    w,h: integer; // ширина и высота прямоугольника

    bs: TBrushStyle;// стиль заполнения области

    k: integer; // номер стиля заполнения

    i,j: integer;
    begin

    w:=40; h:=40; // размер области(прямоугольника)

    у:=20;

    for i:=l to 2 do

    begin

    х:=10;

    for j:=1 to 4 do

    begin

    k:=j+(i-1)*4; // номер стиля заполнения
    case k of

    1: bs = bsSolid;

    2: bs = bsClear;

    3: bs = bsHorizontal;

    4: bs = bsVertical;

    5: bs = bsFDiagonal;

    6: bs = bsBDiagonal;

    7: bs = bsCross;

    8: bs = bsDiagCross; end;

    // вывод прямоугольника

    Canvas.Brush.Color := clGreen;
    // цвет закрашивания — зеленый
    Canvas.Brush.Style := bs;
    // стиль закрашивания
    Canvas . Rectangle (x, y, x+w, y-t-h) ;

    // вывод названия стиля
    Canvas.Brush.Style := bsClear;

    Canvas.TextOut(x, y-15, bsName[k]);

    // вывод названия стиля
    x := x+w+30;
    end;

    у := y+h+30;
    end;
    end;

    end.

    Летящий самолет

    Листинг 10.10. Летящий самолет

    unit anim_;

    interface

    uses

    Windows, Messages, SysUtils,
    Classes, Graphics, Controls,
    Forms, Dialogs, ExtCtrls, StdCtrls, Buttons;

    type

    TForm1 = class(TForm)

    Timer1: TTimer;

    Image1: Tlmage;

    procedure FormActivate(Sender: TObject);


    procedure Timer1Timer(Sender: TObject);


    procedure FormClose(Sender: TObject;
    var Action: TCloseAction);
    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    var

    Back, bitmap, Buf : TBitMap; // фон, картинка, буфер
    BackRct : TRect; // область фона, которая должна быть

    // восстановлена из буфера
    BufRet: Trect; // область буфера, которая используется для

    // восстановления фона

    х,у:integer; // текущее положение картинки
    W,H: integer; // размеры картинки

    procedure TForm1.FormActivate(Sender: TObject);

    begin

    // создать три объекта — битовых образа
    Back := TBitmap.Create; // фон
    bitmap := TBitmap.Create; // картинка
    Buf := TBitmap.Create; // буфер

    // загрузить и вывести фон
    Back.LoadFromFile('factory.bmp');

    Form1.Image1.canvas.Draw(0,0,Back);


    // загрузить картинку, которая будет двигаться

    bitmap.LoadFromFile('aplane.bmp');


    // определим "прозрачный" цвет

    bitmap.Transparent := True;

    bitmap.TransParentColor := bitmap.canvas.pixels[1,1];

    // создать буфер для сохранения копии области фона,

    // на которую накладывается картинка

    W:= bitmap.Width;

    Н:= bitmap.Height;

    Buf.Width:= W;

    Buf.Height:=H;

    Buf.Palette:=Back.Palette;
    // Чтобы обеспечить соответствие палитр //

    Buf.Canvas.CopyMode:=cmSrcCopy;

    // определим область буфера, которая
    // будет использоваться

    // для восстановления фона
    BufRct:=Bounds(0,0,W,H);


    // начальное положение картинки
    х := -W; у := 20;

    // определим сохраняемую область фона
    BackRct:=Bounds(x,y,W,H);
    // и сохраним ее

    Buf.Canvas.CopyRect(BufRet,Back.Canvas,BackRct);

    end;

    // обработка сигнала таймера

    procedure TForm1.Timer1Timer(Sender: TObject);


    begin

    // восстановлением фона (из буфера) удалим рисунок

    Forml.image1.canvas.Draw(x,у,Buf);


    x:=x+2;

    if x>
    fоrm1.Image1.Width then x:=-W;

    // определим сохраняемую область фона

    BackRct:=Bounds(x,у,W,H);


    // сохраним ее копию

    Buf.Canvas.CopyRect(BufRct,Back.Canvas,BackRct);


    // выведем рисунок

    Forml.image1.canvas.Draw(x,y,bitmap);

    end;

    // завершение работы программы

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);


    begin

    // освободим память, выделенную

    // для хранения битовых образов

    Back.Free;

    bitmap.Free;

    Buf.Free;
    end;
    end.



    Пример загрузки картинок из ресурса

    Листинг 10.11. Пример загрузки картинок из ресурса

    unit aplanel_;

    {$R images.res} // включить файл ресурсов interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs,
    ExtCtrls, StdCtrls, Buttons;

    type

    TForm1 = class(TForm)

    Timer1: TTimer;

    Image1: ТImage;

    procedure FormActivate(Sender: TObject);


    procedure Timer1Timer(Sender: TObject);


    procedure FormClose(Sender: TObject;
    var Action: TCloseAction);
    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    Back, bitmap, Buf : TBitMap;
    // фон, картинка, буфер

    BackRct, BufRet: TRect;
    // область фона, картинки, буфера

    х,у:integer;
    // координаты левого верхнего угла картинки

    W,H: integer; // размеры картинки

    implementation

    {$R *.DFM}

    procedure TForm1.FormActivate(Sender: TObject);

    begin

    Back := TBitmap.Create; // фон

    bitmap := TBitmap.Create; // картинка

    Buf := TBitmap.Create; // буфер

    // загрузить из ресурса фон

    Back.LoadFromResourceName(HInstance,'FACTORY');


    Forml.Image1.canvas.Draw(0,0,Back);


    // загрузить из ресурса картинку, которая будет двигаться
    bitmap.LoadFromResourceName(HInstance,'APLANE');

    bitmap.Transparent := True;
    bitmap.TransParentColor := bitmap.canvas.pixels[1,1];

    // создать буфер для сохранения копии области фона, на которую

    // накладывается картинка

    W:= bitmap.Width;

    Н:= bitmap.Height;

    Buf.Width:= W;

    Buf.Height:=H;

    Buf.Palette:=Back.Palette; // Чтобы обеспечить соответствие палитр !!

    Buf.Canvas.CopyMode:=cmSrcCopy;

    BufRct:=Bounds(0,0,W,H);


    x:=-W; y:=20;

    // определим сохраняемую область фона
    BackRct:=Bounds(x,y,W,H);
    // и сохраним ее

    Buf.Canvas.CopyRect(BufRet,Back.Canvas, BackRct);

    end;

    procedure TForm1.Timer1Timer(Sender: TObject);

    begin

    // восстановлением фона (из буфера) удалим рисунок Form1.image1.canvas.Draw(x,y, Buf);


    x:=x+2;

    if x>
    form1.Image1.Width then x:=-W;

    // определим сохраняемую область фона

    BackRct:=Bounds(x,у,W,H);


    // сохраним ее копию

    Buf.Canvas.CopyRect(BufRct,Back.Canvas,BackRct);


    // выведем рисунок

    Form1.image1.canvas.Draw(x,y,bitmap);

    end;

    procedure TForm1.FormClose(Sender: TObject;
    var Action: TCloseAction);

    begin

    Back.Free;

    bitmap.Free ;

    Buf.Free;
    end;

    end.

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

    Оси координат и оцифрованная сетка

    Листинг 10.2. Оси координат и оцифрованная сетка

    unit grid_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;
    type

    TForm1 = class(TForm)

    procedure FormPaint(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1; implementation

    {$R *.DFM}

    procedure TForm1.FormPaint(Sender: TObject);


    var

    x0,y0:integer; // координаты начала координатных осей

    dx,dy:integer; // шаг координатной сетки (в пикселах)

    h,w:integer; // высота и ширина области вывода координатной сетки

    х,у:integer;

    lx,ly:real; // метки (оцифровка) линий сетки по X и Y

    dlx,dly:real; // шаг меток (оцифровки) линий сетки по X и Y

    cross:integer; // счетчик неоцифрованных линий сетки

    dcross:integer;// количество неоцифрованных линий между оцифрованными

    begin

    х0:=30; у0:=220; // оси начинаются в точке (40,250)
    dx:=40; dy:=40; // шар координатной сетки 40 пикселов
    dcross:=1; // помечать линии сетки X: 1 — каждую;

    // 2 — через одну;

    // 3 — через две;

    dlx:=0.5; // шаг меток оси X

    dly:=1.0; // шаг меток оси Y, метками будут: 1, 2, 3 и т. д.

    h:=200; w:=300;

    with forml.Canvas do begin

    cross:=dcross;

    MoveTo(x0,v0);
    LineTo(x0,y0-h);
    // ось X

    MoveTo(x0,y0);
    LineTo(x0+w, y0);
    // ось Y

    // засечки, сетка и оцифровка по оси X

    x:=x0+dx;

    lx:=dlx;

    repeat

    MoveTo(x,y0-3);
    LineTo(x,yO+3);
    // засечка

    cross:=cross-l;

    if cross = 0 then // оцифровка

    begin

    TextOut(x-8,y0+5,FloatToStr(lx));


    cross:=dcross ; end;

    Pen.Style:=psDot;

    MoveTo(x,y0-3);
    LineTo(x,y0-h);
    // линия сетки
    Pen.Style:=psSolid;
    lx:=lx+dlx;
    x:=x+dx;
    until (x>
    x0+w);


    // засечки, сетка и оцифровка по оси Y

    y:=y0-dy;

    ly:=dly;

    repeat

    MoveTo(х0-3,у);
    LineTo(х0+3,у);
    // засечка

    TextOut(х0-20,у,FloatToStr(1у));
    // оцифровка

    Pen.Style:=psDot;

    MoveTo(х0+3,у);
    LineTo(x0+w,у);
    // линия сетки

    Pen.Style:=psSolid;

    y:=y-dy;

    ly:=ly+dly; until (y
    end;
    end;

    end.

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

    График функции (использование метода Polyline)

    Листинг 10.3. График функции (использование метода Polyline)

    procedure TForml.Button1Click(Sender: TObject);

    var

    gr: array[1..50] of TPoint; // график — ломаная линия
    x0,y0: integer; // координаты точки начала координат
    dx,dy: integer; // шаг координатной сетки по осям X и Y
    i: integer; begin

    х0 := 10; у0 := 200; dx :=5; dy := 5;

    // заполним массив gr
    for i:=l to 50 do begin

    gr[i].x := x0 + (i-l)*dx;

    gr[i].y := y0 - Data[i]*dy;
    end;

    // строим график
    with forml.Canvas do begin

    MoveTo(x0,y0);
    LineTo(x0,10);
    // ось Y

    MoveTo(x0,y0);
    LineTo(200,y0);
    // ось X

    Polyline(gr);
    // график

    end;
    end;

    Метод Polyline можно использовать для вычерчивания замкнутых контуров. Для этого надо, чтобы первый и последний элементы массива содержали координаты одной и той же точки. В качестве примера использования метода Polybine для вычерчивания замкнутого контура в листинге 10.4 приведена программа, которая на поверхности диалогового окна, в точке нажатия кнопки мыши, вычерчивает контур пятиконечной звезды (Рисунок 10.5). Цвет, которым вычерчивается звезда, зависит от того, какая из кнопок мыши была нажата. Процедура обработки нажатия кнопки мыши (событие MouseDown) вызывает процедуру рисования звезды starLine и передает ей в качестве параметра координаты точки, в которой была нажата кнопка. Звезду вычерчивает процедура starLine, которая в качестве параметров получает координаты центра звезды и холст, на котором звезда должна быть выведена. Сначала вычисляются координаты концов и впадин звезды, которые записываются в массив р. Затем этот массив передается в качестве параметра методу Polyline. При вычислении координат лучей и впадин звезды используются функции sin и cos. Так как аргумент этих функций должен быть выражен в радианах, то значение угла в градусах домножается на величину pi/18о, где pi — это стандартная именованная константа равная числу л.



    Вычерчивание замкнутого

    Листинг 10.4. Вычерчивание замкнутого контура (звезды) в точке нажатия кнопки мыши

    unit Stars_; interface

    uses

    Windows, Messages, SysUtils, Variants, Classes,
    Graphics, Controls, Forms, Dialogs, StdCtrls;
    type

    TForm1 = class(TForm)

    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;

    Shift: TShiftState; X, Y: Integer);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Forml: TForml;

    implementation

    f$R *.dfm}

    // вычерчивает звезду

    procedure StarLine(x0,y0,r: integer; Canvas: TCanvas);

    // x0,y0 — координаты центра звезды

    //r — радиус заезды var

    р : array [1.. 11] of TPoint;
    // массив координат лучей и впадин
    a: integer; // угол между осью ОХ и прямой, соединяющей

    // центр звезды и конец луча или впадину i: integer;

    begin

    а := 18; // строим от правого гор. луча
    for i:=l to 10 do begin

    if (i mod 2=0) then begin // впадина

    p[i].x := x0+Round(r/2*cos(a*pi/180) ) ;
    p[i] .y:=y0-Round(r/2*sin(a*pi/180) ) ;
    end
    else

    begin // луч

    [i] .x:=x0+Round(r*cos (a*pi/180) ) ;
    [i] .y:=y0-Round(r*sin(a*pi/180) ) ;
    end;

    a := a+36;
    end;
    p[ll].X := p[l].X; // чтобы замкнуть контур звезды

    Canvas. Polyline (р) ; // начертить звезду
    end;

    // нажатие кнопки мыши

    procedure TForm1 . FormMouseDown { Sender : TObject; Button: TMouseButton;

    Shift: TShiftState; X, Y: Integer);

    begin

    if Button = mbLeft // нажата левая кнопка?
    then Form1. Canvas . Pen . Color : = clRed
    else Form1. Canvas. Pen. Color := clGreen;
    StarLine(x, y, 30, Forml. Canvas );

    end;
    end.



    График функции

    Листинг 10.5. График функции

    unit grfunc_;

    interface

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs;

    type

    TForm1 = class(TForm)

    procedure FormPaint(Sender: TObject);

    procedure FormResize(Sender: TObject);

    private

    { Private declarations }
    public

    {Public declarations }
    end;

    var

    Forml: TForml;

    implementation

    {$R *.DFM}

    // Функция, график которой надо построить
    Function f(x:real):real;
    begin

    f:=2*Sin(x)*exp(x/5) ;
    end;

    // строит график функции

    procedure GrOfFunc;

    var

    x1,x2:real; // границы изменения аргумента функции
    y1,y2:real; // границы изменения значения функции
    х:real; // аргумент функции
    у:real; // значение функции в точке х
    dx:real; // приращение аргумента

    l,b:integer; // левый нижний угол области вывода графика
    w,h:integer; // ширина и высота области вывода графика
    mx,my:real; // масштаб по осям X и Y
    х0,у0:integer; // точка — начало координат

    begin

    // область вывода графика

    l:=10; // X — координата левого верхнего угла

    b:=Forml.ClientHeight-20;
    //У — координата левого верхнего угла

    h:=Forml.ClientHeight-40; // высота

    w:=Forml.Width-40; // ширина

    x1:=0; // нижняя граница диапазона аргумента

    х2:=25; // верхняя граница диапазона аргумента
    dx:=0.01; // шаг аргумента

    // найдем максимальное и минимальное значения

    // функции на отрезке [x1,x2]

    y1:=f(xl);
    // минимум

    y2:=f(xl);
    //максимум

    x:=x1;

    repeat

    У := f (х);


    if у < yl then yl:=y;

    if у >
    у2 then
    y2:=y;

    х:=x+dx; until (x >
    = х2);


    // вычислим масштаб

    my:=h/abs(y2-yl);
    // масштаб по оси Y

    mx:=w/abs(x2-xl);
    // масштаб по оси X

    х0:=1;

    у0:=b-Abs(Round(y1*my)) ;

    with form1.Canvas do

    begin

    // оси

    MoveTo(l,b);
    LineTo(l,b-h);


    MoveTo(x0,y0);
    LineTo(x0+w,y0);


    TextOut(l+5,b-h,FloatToStrF(y2,ffGeneral,6,3));


    TextOut(l+5,b,FloatToStrF(yl,ffGeneral,6,3));


    // построение графика

    x:=xl; repeat

    y:=f(x);


    Pixels[x0+Round(x*mx),y0-Round(y*my)]:=clRed;
    x:=x+dx;

    until (x >
    = x2);

    end;
    end;

    procedure TForm1.FormPaint(Sender: TObject);

    begin

    GrOfFunc; end;

    // изменился размер окна программы
    procedure TForm1.FormResize(Sender: TObject);

    begin

    // очистить форму

    forml.Canvas.FillRect(Rect(0,0,ClientWidth,
    ClientHeight));


    // построить график

    GrOfFunc;
    end;

    end.

    Основную работу выполняет процедура GrOfFunc, которая сначала вычисляет максимальное (у2) и минимальное (yl) значения функции на отрезке [x1l,x2]. Затем, используя информацию о ширине (Forml.Clientwidth -40) и высоте (Form1.ClientHeight - 40) области вывода графика, вычисляет масштаб по осям X (mх) иY(mу).

    Высота и ширина области вывода графика определяется размерами рабочей (клиентской) области формы, т. е. без учета области заголовка и границ. После вычисления масштаба процедура вычисляет координату у горизонтальной оси (уо) и вычерчивает координатные оси графика. Затем выполняется непосредственное построение графика (Рисунок 10.10).

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



    Слайдпроектор

    Листинг 10.6. Слайд-проектор

    unit shpic_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms,

    Dialogs, ExtCtrls, StdCtrls, Menu

    type

    TForm1 = class(TForm) Image1: ТImage;
    Button1: TButton;

    procedure FormActivate(Sender: TObject);

    procedure ButtonlClick(Sender: TObject);


    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    aSearchRec : TSearchRec;

    aPath : String; // каталог, в котором находятся иллюстрации

    aFile : String; // файл иллюстрации

    iw,ih: integer; // первоначальный размер компонента Image

    implementation

    $R *.DFM}

    // изменение размера области вывода иллюстрации

    // пропорционально размеру иллюстрации
    Procedure Scalelmage;
    var

    pw, ph : integer; // размер иллюстрации
    scaleX, scaleY : real; // масштаб по Х и Y
    scale : real; // общий масштаб
    begin

    // иллюстрация уже загружена

    // получим ее размеры

    pw := Form1.Image1.Picture.Width;

    ph := Form1.Image1.Picture.Height;

    if pw >
    iw // ширина иллюстрации больше ширины компонента Image

    then scaleX := iw/pw // нужно масштабировать
    else scaleX := 1;

    if ph >
    ih // высота иллюстрации больше высоты компонента
    then scaleY := ih/ph // нужно масштабировать
    else scaleY := 1;

    // выберем наименьший коэффициент
    if scaleX < scaleY

    then scale := scaleX

    else scale := scaleY;

    // изменим размер области вывода иллюстрации

    Form1.Image1.Height := Round(Form1.Image1.Picture.Height*scale)
    Form1.Image1.Width := Round(Form1.Image1.Picture.Width*scale);

    // т. к. Strech = True и размер области пропорционален
    // размеру картинки, то картинка масштабируется без искажений
    end;

    // вывести первую иллюстрацию

    procedure FirstPicture;

    var

    r : integer; // результат поиска файла
    begin

    aPath := 'f:\temp\';

    r := FindFirst(aPath+'*.bmp',faAnyFile,aSearchRec);


    if г = 0 then

    begin // в указанном каталоге есть bmp-файл
    aFile := aPath + aSearchRec.Name;

    Form1.Image1.Picture.LoadFromFile(aFile);
    // загрузить

    // иллюстрацию

    Scalelmage; //-установить размер компонента
    Image r := FindNext(aSearchRec);
    // найти следующий файл
    if r = 0 then // еще есть файлы иллюстраций

    Forml.Button1.Enabled := True;
    end;
    end;

    // вывести следующую иллюстрацию
    Procedure NextPicture();


    var

    r : integer;
    begin

    aFile := aPath + aSearchRec.Name;

    Forml.Image1.Picture.LoadFromFile(aFile);


    Scalelmage;

    // подготовим вывод следующей иллюстрации

    r := FindNext(aSearchRec);
    // найти следующий файл

    if r<>
    0

    then // больше нет иллюстраций

    Forml.Buttonl.Enabled := False;
    end;

    procedure TForml.FormActivate(Sender: TObject);

    begin

    Image1.AutoSize := False; // запрет автоизменения размера компонента
    Image1.Stretch := True; // разрешим масштабирование
    // запомним первоначальный размер области вывода иллюстрации
    iw := Imagel.Width;
    in := imagel.Height;

    Button1.Enabled := False; // сделаем недоступной кнопку Дальше
    FirstPicture; // вывести первую иллюстрацию
    end;

    //щелчок на кнопке Дальше

    procedure TForm1.Button1Click(Sender: TObject);

    begin

    NextPicture;
    end;

    end.

    Программа выполняет масштабирование выводимых иллюстраций без искажения, чего нельзя добиться простым присвоением значения True свойству strech. Загрузку и вывод первой и остальных иллюстраций выполняют соответственно процедуры FirstPicture и NextPicture. Процедура FrirstPicture использует функцию FindFirst для того, чтобы получить имя первого BMP-файла. В качестве параметров функции FindFirst передаются:

  • имя каталога, в котором должны находиться иллюстрации;
  • структура asearchRec, поле Name которой, в случае успеха, будет содержать имя файла, удовлетворяющего критерию поиска;
  • маска файла иллюстрации.
  • Если в указанном при вызове функции FindFirst каталоге есть хотя бы один BMP-файл, значение функции будет равно нулю. В этом случае метод LoadFromFiie загружает файл иллюстрации, после чего вызывается функция scaieimage, которая устанавливает размер компонента пропорционально размеру иллюстрации. Размер загруженной иллюстрации можно получить, обратившись к свойствам Form1.Image1.Picture.Width и Form1.Шmage1.Picture.Height, значения которых не зависят от размера компонента Image.

    Использование битовых образов

    Листинг 10.7. Использование битовых образов

    unit aplanes_; interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs;

    type

    TForml = class(TForm)

    procedure FormPaint(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Forml: TForm1;

    sky,aplane: TBitMap; // битовые образы: небо и самолет

    implementation

    ($R *.DFM}

    procedure TForm1.FormPaint(Sender: TObject);

    begin

    // создать битовые образы
    sky := TBitMap.Create;
    aplane := TBitMap.Create;

    // загрузить картинки

    sky.LoadFromFile('sky.bmp');

    aplane.LoadFromFile('aplane.bmp') ;

    Form1.Canvas.Draw(0,0,sky);
    // отрисовка фона

    Form1.Canvas.Draw(20,20,aplane);
    // отрисовка левого самолета

    aplane.Transparent:=True;

    // теперь элементы рисунка, цвет которых совпадает с цветом
    // левой нижней точки битового образа, не отрисовываются Form1.Canvas.Draw(120,20,aplane);

    // отрисовка правого самолета

    // освободить память sky.free; aplane.free;
    end;

    end.

    После запуска программы в окне приложения (Рисунок 10.14) появляется изображение летящих на фоне неба самолетов. Фон и изображение самолета -битовые образы, загружаемые из файлов. Белое поле вокруг левого самолета показывает истинный размер картинки битового образа aplane. Белое поле вокруг правого самолета отсутствует, т. к. перед его выводом свойству Transparent битового образа было присвоено значение True.



    Движущаяся окружность

    Листинг 10.8. Движущаяся окружность

    unit mcircle_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms,
    Dialogs, ExtCtrls, StdCtrls;

    type

    TForm1 = class(TForm) Timer1: TTimer;

    procedure Timer1Timer(Sender: TObject};
    procedure FormActivate(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    implementation

    {$R *.DFM}

    var

    Form1: TForml;

    x,y: byte; // координаты центра окружности

    dx: byte; // приращение координаты x при движении окружности

    // стирает и рисует окружность на новом месте

    procedure Ris;

    begin

    // стереть окружность

    form1.Canvas.Pen.Color:=form1.Color;

    form1.Canvas.Ellipse(x,y,x+10,y+10);


    x:=x+dx;

    // нарисовать окружность на новом месте

    form1.Canvas.Pen.Color:=clBlack;

    form1.Canvas.Ellipse(x,y, x+10, y+10) ;
    end;

    // сигнал от таймера

    procedure TForm1.Timer1Timer(Sender: TObject);

    begin Ris; end;

    procedure TForm1.FormActivate(Sender: TObject);

    begin

    x:=0;

    y:=10;

    dx:=5;

    timer1.Interval:=50;
    // период возникновения события OnTimer —0.5 сек

    form1.canvas.brush.color:=forml.color;
    end;

    end.

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

    Для обеспечения периодического вызова процедуры Ris в форму программы добавлен невизуальный компонент Timer (таймер), значок которого находится на вкладке System палитры компонентов (Рисунок 10.16). Свойства компонента Timer, перечислены в табл. 10.9.



    Кораблик

    Листинг 10.9. Кораблик

    unit ship_;

    interface

    uses

    Windows, Messages, SysUtils, Classes,
    Graphics, Controls, Forms, Dialogs,
    StdCtrls, ExtCtrls;

    type

    TForm1 = class(TForm)

    Timer1: TTimer;

    procedure Timer1Timer(Sender: TObject);


    procedure FormActivate(Sender: TObject);

    private

    { Private declarations } public

    { Public declarations } end;

    var

    Form1: TForm1;

    x,y: integer; // координаты корабля (базовой точки)

    implementation

    {$R *.DFM}

    // вычерчивает кораблик

    procedure Titanik(x,y: integer; // координаты базовой точки

    color: TColor);
    // цвет корабля
    const dx = 5; dy = 5;
    var

    buf: TColor;
    begin

    with form1.canvas do begin

    buf:=pen.Color; // сохраним текущий цвет
    pen.Color:=color;
    // установим нужный цвет
    // рисуем . . .

    // корпус MoveTo(x,y);


    LineTo(x,y-2*dy) ;
    LineTo (x+10*dx, y-2*dy) ;
    LineTo (x+ll*dx, y-3*dy) ;
    LineTo (x+17*dx,y-3*dy) ;
    LineTo (x+14*dx, y) ;
    LineTo (x,y) ;

    // надстройка
    MoveTo(x+3*dx,y-2*dy) ;
    LineTo (x+4*dx, y-3*dy) ;
    LineTo (x+4*dx, y-4*dy) ;
    LineTo (x+13*dx,y-4*dy) ;
    LineTo (x+13*dx, y-3*dy) ;
    MoveTo(x+5*dx,y-3*dy) ;
    LineTo (x+9*dx, y-3*dy) ;

    // капитанский мостик

    Rectangle (x+8*dx, y-4*dy, x+ll*dx, y-5*dy)

    // труба

    Rectangle (x+7*dx, y-4*dy, x+8*dx, y-7*dy) ;

    // иллюминаторы

    Ellipse (x+ll*dx,y-2*dy,x+12*dx,y-l*dy) ;

    Ellipse (x+13*dx, y-2*dy, x+14*dx, y-l*dy) ;

    // мачта

    MoveTo(.x+10*dx,y-5*dy) ; LineTo(x+10*dx,y-10*dy);


    // оснастка

    MoveTo(x+17*dx,y-3*dy);

    LineTo(x+10*dx,y-10*dy);

    LineTo(x,y-2*dy);


    pen.Color:=buf; // восстановим старый цвет карандаша
    end;
    end;

    // обработка сигнала таймера

    procedure TForm1.Timer1Timer(Sender: TObject);

    begin

    Titanik(x,y,form1.color);
    // стереть рисунок
    if x < Form1.ClientWidth
    then x := x+5
    else begin // новый рейс x := 0;

    у := Random(50) + 100;
    end;

    Titanik(x,у,clWhite);
    // нарисовать в новой точке end;

    procedure TForml.FormActivate(Sender: TObject);

    begin

    x:=0; y:=100;

    Form1.Color:=clNavy;

    Timerl.Interval := 50; // сигнал таймера каждые 50 миллисекунд
    end;

    end.

    Отрисовку и стирание изображения кораблика выполняет процедура Titanik, которая получает в качестве параметров координаты базовой точки и цвет, которым надо вычертить изображение кораблика. Если при вызове процедуры цвет отличается от цвета фона формы, то процедура рисует кораблик, а если совпадает — то "стирает". В процедуре Titanik объявлены константы dx и dy, определяющие шаг (в пикселах), используемый при вычислении координат точек изображения. Меняя значения этих констант, можно проводить масштабирование изображения.

    Ломаная линия

    Ломаная линия

    Метод polyline вычерчивает ломаную линию. В качестве параметра метод получает массив типа TPoint. Каждый элемент массива представляет собой запись, поля х и у которой содержат координаты точки перегиба ломаной. Метод Polyline вычерчивает ломаную линию, последовательно соединяя прямыми точки, координаты которых находятся в массиве: первую со второй, вторую с третьей, третью с четвертой и т. д.

    В качестве примера использования метода Polyline в листинге 10.3 приведена процедура, которая выводит график изменения некоторой величины. Предполагается, что исходные данные находятся в доступном процедуре массиве Data (тип Integer).



    Метод базовой точки

    Метод базовой точки

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

    1. Выбирается некоторая точка изображения, которая принимается за базовую.

    2. Координаты остальных точек отсчитываются от базовой точки.

    3. Если координаты точек изображения отсчитывать от базовой в относительных единицах, а не в пикселах, то обеспечивается возможность масштабирования изображения.

    На Рисунок 10.17 приведено изображение кораблика. Базовой точкой является точка с координатами (X0 Y0). Координаты остальных точек отсчитываются именно от этой точки.



    Метод RoundRec вычерчивает прямоугольник

    Рисунок 10.8. Метод RoundRec вычерчивает прямоугольник со скругленными углами

    Метод RoundRec вычерчивает прямоугольник

    Вид линии контура (цвет, ширина и стиль) определяется значениями свойства Реп, а цвет и стиль заливки области внутри прямоугольника — значениями свойства Brush поверхности (canvas), на которой прямоугольник вычерчивается.

    Есть еще два метода, которые вычерчивают прямоугольник, используя в качестве инструмента только кисть (Brush). Метод FillRect вычерчивает закрашенный прямоугольник, а метод FrameRect — только контур. У каждого из этих методов лишь один параметр — структура типа TRect. Поля структуры TRect содержат координаты прямоугольной области, они могут быть заполнены при помощи функции Rect.

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

    procedure TForm1.Button1Click(Sender: TObject);
    var

    r1, r2: TRect; // координаты углов прямоугольников

    begin

    // заполнение полей структуры

    // зададим координаты углов прямоугольников

    r1 := Rect(20,20,60,40);

    r2 := Rect(10,10,40,50);

    with fоrm1.Canvas do begin

    Brush.Color := clRed;

    FillRect(r1); // закрашенный прямоугольник
    Brush.Color := clGreen;

    FrameRect(r2}; // только граница прямоугольника
    end;
    end;

    Методы вычерчивания графических примитивов

    Методы вычерчивания графических примитивов

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

    Вычерчивание графических примитивов на поверхности компонента (формы или области вывода иллюстрации) осуществляется применением соответствующих методов к свойству Canvas этого компонента.


    Многоугольник

    Многоугольник

    Метод Polygon вычерчивает многоугольник. В качестве параметра метод получает массив типа TPoint. Каждый элемент массива представляет собой запись, поля (х,у) которой содержат координаты одной вершины многоугольника. Метод Polygon вычерчивает многоугольник, последовательно соединяя прямыми линиями точки, координаты которых находятся в массиве: первую со второй, вторую с третьей, третью с четвертой и т. д. Затем соединяются последняя и первая точки.

    Цвет и стиль границы многоугольника определяются значениями свойства Реп, а цвет и стиль заливки области, ограниченной линией границы, — значениями свойства Brush, причем область закрашивается с использованием текущего цвета и стиля кисти.

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

    procedure TForm1.Button2Click(Sender: TObject);
    var

    pol: array[1..3] of TPoint; // координаты точек треугольника
    begin

    pol[1].x := 10;

    polf1].y := 50;

    pol[2].x := 40;
    pol[2].y := 10;
    pol[3].х := 70;
    pol[3].у := 50;
    Form1.Canvas.Polygon(pol);
    end;

    Мультипликация

    Мультипликация

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

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

    Следующая простая программа, текст которой приведен в листинге 10.8, а вид формы — на Рисунок 10.15, демонстрирует движение окружности от левой к правой границе окна программы.



    Окно Picture Editor

    Рисунок 10.12. Окно Picture Editor


    Окно Picture Editor





    Окно программы Стили заполнения областей

    Рисунок 10.2. Окно программы Стили заполнения областей


    Окно программы Стили заполнения областей





    Окружность и эллипс

    Окружность и эллипс

    Метод Ellipse вычерчивает эллипс или окружность, в зависимости от значений параметров. Инструкция вызова метода в общем виде выглядит следующим образом:

    Объект.Canvas.Ellipse(x1,y1, х2,у2]

    где:

  • объект — имя объекта (компонента), на поверхности которого выполняется вычерчивание;
  • x1, y1, х2, у2 — координаты прямоугольника, внутри которого вычерчивается эллипс или, если прямоугольник является квадратом, окружность (Рисунок 10.6).


  • Определение координат изображения относительно базовой точки

    Рисунок 10.17. Определение координат изображения относительно базовой точки

    Определение координат изображения относительно базовой точки

    В листинге 10.9 приведен текст программы, которая выводит на экран изображение перемещающегося кораблика.



    Подключение файла ресурсов

    Подключение файла ресурсов

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

    В общем виде эта директива выглядит следующим образом:

    {$R ФайлРесурсов}

    где ФайлРесурсов — имя файла ресурсов. Например, директива может выглядеть так:

    {$R images.res}

    Директиву включения файла ресурсов в файл исполняемой программы обычно помещают в начале текста модуля.

    Примечание

    Если имена файла модуля программы и файла ресурсов совпадают, то вместо имени файла ресурсов можно поставить "*". В этом случае директива включения файла ресурсов в файл исполняемой программы выглядит так:

    {$R *.res}

    Загрузить картинку из ресурса в переменную типа TBitMap можно при помощи метода LoadFromResourceName, который имеет два параметра: идентификатор программы и имя ресурса. В качестве идентификатора программы используется глобальная переменная Hinstance. Имя ресурса должно быть представлено в виде строковой константы.

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

    Pic.LoadFromResourceName(Hinstance,'FACTORY') ;

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



    Прямоугольник

    Прямоугольник

    Прямоугольник вычерчивается методом Rectangle, инструкция вызова которого в общем виде выглядит следующим образом:

    Объект.Canvas.Rectangle(x1, y1,x2, y2)

    где:

  • объект — имя объекта (компонента), на поверхности которого выполняется вычерчивание;
  • x1, y1 и х2, у2 — координаты левого верхнего и правого нижнего углов прямоугольника.
  • Метод RoundRec тоже вычерчивает прямоугольник, но со скругленными углами. Инструкция вызова метода RoundRec выглядит так:

    Объект.Canvas.RoundRec(x1,y1,х2, у2, х3, у3)
    где:

  • x1, y1, х2, у2 -- параметры, определяющие положение углов прямоугольника, в который вписывается прямоугольник со скругленными углами;
  • х3 и у3 — размер эллипса, одна четверть которого используется для вычерчивания скругленного угла (Рисунок 10.8).


  • Просмотр "мультика"

    Просмотр "мультика"

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

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

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

    Вывести кадр на поверхность формы можно применением метода copyRect к свойству canvas этой формы. Метод CopyRect копирует прямоугольную область одной графической поверхности на другую.

    Инструкция применения метода CopyRect в общем виде выглядит так:

    Canvas1.CopyRect(Область1, Canvas2, 06ласть2)

    где:

  • canvas1 — графическая поверхность, на которую выполняется копирование;
  • Canvas2 — графическая поверхность, с которой выполняется копирование;
  • параметр Область2 —- задает положение и размер копируемой прямоугольной области, а параметр областьi — положение копии на поверхности Canvas1.
  • В качестве параметров область! и область2 используются структуры типа TRect, поля которых определяют положение и размер области.

    Заполнить поля структуры TRect можно при помощи функции Bounds, инструкция обращения к которой в общем виде выглядит так:

    Bounds(x,у,Width,Height)

    где:

  • х и у — координаты левого верхнего угла области;
  • width и Height — ширина и высота области.
  • Следующая программа, текст которой приведен в листинге 10.12, выводит в диалоговое окно простой мультик — дельфийскую колонну, вокруг которой "летает" некоторый объект. На Рисунок 10.19 приведены кадры этого мультика (содержимое файла film.bmp).

    Диалоговое окно программы приведено на Рисунок 10.20, оно содержит один единственный компонент — таймер.



    Сектор

    Сектор

    Метод pie вычерчивает сектор эллипса или круга. Инструкция вызова метода в общем виде выглядит следующим образом:

    Объект. Canvas.Pie(x1,y1,x2,y2,х3,у3,х4,у4)

    где:

  • x1, y1, х2, у2 — параметры, определяющие эллипс (окружность), частью которого является сектор;
  • х3, у3, х4, у4 — параметры, определяющие координаты конечных точек прямых, являющихся границами сектора.
  • Начальные точки прямых совпадают с центром эллипса (окружности). Сектор вырезается против часовой стрелки от прямой, заданной точкой с координатами (хЗ, уз), к прямой, заданной точкой с координатами (х4, у4) (Рисунок 10.9).



    Слайдпроектор

    Рисунок 10.13. Слайд-проектор


    Слайдпроектор





    Создание файла ресурсов

    Создание файла ресурсов

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

    Файл ресурсов можно создать при помощи утилиты Image Editor (Редактор изображений), которая запускается выбором команды Image Editor меню Tools.

    Для того чтобы создать новый файл ресурсов, надо из меню File выбрать команду New, а затем в появившемся подменю — команду Resource File (Файл ресурсов)

    В результате открывается окно нового файла ресурсов, а в строке меню окна Image Editor появляется новый пункт — Resource.

    Для того чтобы в этот файл добавить новый ресурс, необходимо выбрать команду New меню Resource и из открывшегося списка — тип ресурса. В данном случае следует выбрать Bitmap (битовый образ). После выбора Bitmap открывается диалоговое окно Bitmap Properties (Свойства битового образа), используя которое можно установить размер (в пикселах) и количество цветов создаваемой картинки.

    Нажатие кнопки ОК в диалоговом окне Bitmap Properties вызывает появление элемента Bitmap1 в иерархическом списке Contents. Этот элемент соответствует новому ресурсу, добавленному в файл .

    Bitmap1 — это автоматически созданное имя ресурса, которое может быть изменено выбором команды Rename меню Resource и вводом нужного имени. После изменения имени Bitmap1 можно приступить к созданию битового образа. Для этого необходимо выбрать команду Edit меню Resource, в результате чего открывается окно графического редактора.

    Графический редактор Image Editor предоставляет программисту стандартный для подобных редакторов набор инструментов, используя которые можно нарисовать нужную картинку. Если во время работы надо изменить масштаб отображения картинки, то для увеличения масштаба следует выбрать команду Zoom In меню View, а для уменьшения — команду Zoom Out. Увидеть картинку в реальном масштабе можно, выбрав команду Actual Size меню View.

    Если нужная картинка уже существует в виде отдельного файла, то ее можно через буфер обмена (clipboard) поместить в битовый образ файла ресурсов. Делается это следующим образом.

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

    2. Далее нужно переключиться в Image Editor, выбрать ресурс, в который надо поместить находящуюся в буфере картинку, и установить значения характеристик ресурса в соответствии с характеристиками картинки, находящейся в буфере. Значения характеристик ресурса вводятся в поля диалогового окна Bitmap Properties, которое открывается выбором команды Image Properties меню Bitmap. После установки характеристик ресурса можно вставить картинку в ресурс, выбрав команду Past меню Edit.

    3. После добавления всех нужных ресурсов файл ресурса следует сохранить в том каталоге, где находится программа, для которой этот файл создается. Сохраняется файл ресурса обычным образом, т. е. выбором команды Save меню File. Image Editor присваивает файлу ресурсов расширение res.

    Свойства объекта треп (карандаш)

    Таблица 10.1. Свойства объекта треп (карандаш)

    Свойство

    Определяет

    Color

    Цвет линии

    Width

    Толщину линии

    Style

    Вид линии

    Mode

    Режим отображения

    Свойство Color задает цвет линии, вычерчиваемой карандашом. В табл. 10.2 перечислены именованные константы (тип TCoior), которые можно использовать в качестве значения свойства color.



    Значение свойства Color определяет цвет линии

    Таблица 10.2. Значение свойства Color определяет цвет линии

    Константа

    Цвет

    Константа

    Цвет

    clBlack

    Черный

    clSilver

    Серебристый

    clMaroon

    Каштановый

    clRed

    Красный

    clGreen

    Зеленый

    clLime

    Салатный

    clOlive

    Оливковый

    clBlue

    Синий

    clNavy

    Темно-синий

    clFuchsia

    Ярко-розовый

    clPurple

    Розовый

    clAqua

    Бирюзовый

    clTeal

    Зелено-голубой

    clWhite

    Белый

    clGray

    Серый





    Свойство width задает толщину линии (в пикселах). Например, инструкция Canvas. Pen. width: =2 устанавливает толщину линии в 2 пиксела.

    Свойство style определяет вид (стиль) линии, которая может быть непрерывной или прерывистой, состоящей из штрихов различной длины. В табл. 10.3 перечислены именованные константы, позволяющие задать стиль линии. Толщина пунктирной линии не может быть больше 1. Если значение свойства Pen.width больше единицы, то пунктирная линия будет выведена как сплошная.



    Значение свойства Реn туре определяет вид линии

    Таблица 10.3. Значение свойства Реn. туре определяет вид линии

    Константа

    Вид линии

    psSolid

    Сплошная линия

    psDash

    Пунктирная линия, длинные штрихи

    psDot

    Пунктирная линия, короткие штрихи

    psDashDot

    Пунктирная линия, чередование длинного и короткого штрихов

    psDashDotDot

    Пунктирная линия, чередование одного длинного и двух коротких штрихов

    psClear

    Линия не отображается (используется, если не надо изображать границу области, например, прямоугольника)

    Свойство Mode определяет, как будет формироваться цвет точек линии в зависимости от цвета точек холста, через которые эта линия прочерчивается. По умолчанию вся линия вычерчивается цветом, определяемым значением свойства Pen.Color.

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

    В табл. 10.4 перечислены некоторые константы, которые можно использовать в качестве значения свойства Pen.Mode.



    Значение свойства Реп Mode влияет на цвет линии

    Таблица 10.4. Значение свойства Реп. Mode влияет на цвет линии

    Константа

    Цвет линии

    pmBlack

    Черный, не зависит от значения свойства Pen. Color

    pmWhite

    Белый, не зависит от значения свойства Pen. Color

    pmCopy

    Цвет линии определяется значением свойства Pen . Color

    pmNotCopy

    Цвет линии является инверсным по отношению к значению свойства Pen. Color

    pmNot

    Цвет точки линии определяется как инверсный по отношению к цвету точки холста, в которую выводится точка линии



    Свойства объекта TBrush (кисть)

    Таблица 10.5. Свойства объекта TBrush (кисть)

    Свойство

    Определяет

    Color
    Style

    Цвет закрашивания замкнутой области
    Стиль (тип) заполнения области

    Область внутри контура может быть закрашена или заштрихована. В первом случае область полностью перекрывает фон, а во втором — сквозь незаштрихованные участки области будет виден фон.

    В качестве значения свойства Color можно использовать любую из констант типа TColor (см. список констант для свойства Pen.color в табл. 10.2).

    Константы, позволяющие задать стиль заполнения области, приведены в табл. 10.6.



    Значения свойства

    Таблица 10.6. Значения свойства Brush, style определяют тип закрашивания

    Константа

    Тип заполнения (заливки) области

    bsSolid

    Сплошная заливка

    bsClear

    Область не закрашивается

    bsHorizontal

    Горизонтальная штриховка

    bsVertical

    Вертикальная штриховка

    bsFDiagonal

    Диагональная штриховка с наклоном линий вперед

    bsBDiagonal

    Диагональная штриховка с наклоном линий назад

    bsCross

    Горизонтально-вертикальная штриховка, в клетку

    bsDiagCross

    Диагональная штриховка, в клетку

    В качестве примера в листинге 10.1 приведена программа Стили заполнения областей, которая в окно (Рисунок 10.2) выводит восемь прямоугольников, закрашенных черным цветом с использованием разных стилей.



    Свойства объекта TFont

    Таблица 10.7. Свойства объекта TFont

    Свойство

    Определяет

    Name
    Size

    Style

    Используемый шрифт. В качестве значения следует использовать название шрифта, например Arial

    Размер шрифта в пунктах (points). Пункт— это единица измерения размера шрифта, используемая в полиграфии. Один пункт равен 1/72 дюйма

    Стиль начертания символов. Может быть: нормальным, полужирным, курсивным, подчеркнутым, перечеркнутым. Стиль задается при помощи следующих констант: fsBold (полужирный), fsltalic (курсив), f sUnderline (подчеркнутый), f sStrikeOut (перечеркнутый).

    Свойство

    Определяет

    style

    Color

    Свойство style является множеством, что позволяет комбинировать необходимые стили. Например, инструкция программы, устанавливающая стиль "полужирный курсив", выглядит так:

    Объект. Canvas . Font : = [fsBold, fs Italic]

    Цвет символов. В качестве значения можно использовать константу типа Tcolor

    Внимание!

    Область вывода текста закрашивается текущим цветом кисти. Поэтому перед выводом текста свойству Brush.Color нужно присвоить значение bsClear или задать цвет кисти, совпадающий с цветом поверхности, на которую выводится текст.

    Следующий фрагмент программы демонстрирует использование функции Textout для вывода текста на поверхность формы:

    with Form1.Canvas do begin

    // установить характеристики шрифта
    Font.Name := 'Tahoma';
    Font.Size := 20;

    Font.Style := [fsltalic, fsBold] ;

    Brush.Style := bsClear; // область вывода текста не закраши-

    TextOut(0, 10, 'Borland Delphi 7');
    end;

    После вывода текста методом Textout указатель вывода (карандаш) перемещается в правый верхний угол области вывода текста.

    Иногда требуется вывести какой-либо текст после сообщения, длина которого во время разработки программы неизвестна. Например, это может быть слово "руб." после значения числа, записанного прописью. В этом случае необходимо знать координаты правой границы уже выведенного текста. Координаты правой границы текста, выведенного методом Textout, можно получить, обратившись к свойству PenPos.

    Следующий фрагмент программы демонстрирует возможность вывода строки текста при помощи двух инструкций Textout.

    with Form1.Canvas do begin

    TextOut(0, 10, 'Borland ') ;
    TextOut(PenPos.X, PenPos.Y, 'Delphi 7');
    end;

    Свойства компонента image

    Таблица 10.8. Свойства компонента image

    Свойство

    Определяет

    Picture Width, Height

    AutoSize
    Strech

    Visible

    Иллюстрацию, которая отображается в поле компонента

    Размер компонента. Если размер компонента меньше размера иллюстрации, и значение свойств AutoSize и strech равно False, то отображается часть иллюстрации

    Признак автоматического изменения размера компонента в соответствии с реальным размером иллюстрации

    Признак автоматического масштабирования иллюстрации в соответствии с реальным размером компонента. Чтобы было выполнено масштабирование, значение свойства AutoSize должно быть False

    Отображается ли компонент, и, соответственно, иллюстрация, на поверхности формы

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

    Во время разработки формы иллюстрация задается установкой значения свойства picture путем выбора файла иллюстрации в стандартном диалоговом окне, которое появляется в результате щелчка на командной кнопке Load окна Picture Editor (Рисунок 10.12). Чтобы запустить Image Editor, нужно в окне Object Inspector выбрать свойство Picture и щелкнуть на кнопке с тремя точками.

    Если размер иллюстрации больше размера компонента, то свойству strech нужно присвоить значение True и установить значения свойств width и Height пропорционально реальным размерам иллюстрации.

    Чтобы вывести иллюстрацию в поле компонента image во время работы программы, нужно применить метод LoadFromFile к свойству Picture, указав в качестве параметра имя файла иллюстрации. Например, инструкция

    Form1.Image1.Picture.LoadFromFile('e:\temp\bart.bmp')

    загружает иллюстрацию из файла bart.bmp и выводит ее в поле вывода иллюстрации (imagel).

    Метод LoadFromFile позволяет отображать иллюстрации различных графических форматов: BMP, WMF, JPEG (файлы с расширением jpg).

    Следующая программа, ее текст приведен в листинге 10.6, использует компонент image для просмотра иллюстраций, которые находятся в указанном пользователем каталоге. Диалоговое окно программы приведено на Рисунок 10.13.



    Свойства компонента Timer

    Таблица 10.9. Свойства компонента Timer

    Свойство

    Определяет

    Name Interval
    Enabled

    Имя компонента. Используется для доступа к компоненту Период генерации события OnTimer. Задается в миллисекундах

    Разрешение работы. Разрешает (значение True) или запрещает (значение False) генерацию события OnTimer

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

    Компонент Timer генерирует событие OnTimer. Период возникновения события OnTimer измеряется в миллисекундах и определяется значением свойства Interval. Следует обратить внимание на свойство Enabled. Оно дает возможность программе "запустить" или "остановить" таймер. Если значение свойства Enabled равно False, то событие OnTimer не возникает.

    Событие onTimer в рассматриваемой программе обрабатывается процедурой TimeriTimer, которая, в свою очередь, вызывает процедуру Ris. Таким образом, в программе реализован механизм периодического вызова процедуры
    Ris.

    Примечание

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

    Точка

    Точка

    Поверхности, на которую программа может осуществлять вывод графики, соответствует объект Canvas. Свойство pixels, представляющее собой двумерный массив типа TColor, содержит информацию о цвете каждой точки графической поверхности. Используя свойство Pixels, можно задать тре-

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

    Form1.Canvas.Pixels[10,10]:=clRed

    окрашивает точку поверхности формы в красный цвет.

    Размерность массива pixels определяется размером графической поверхности. Размер графической поверхности формы (рабочей области, которую также называют клиентской) задается значениями свойств ciientwidth и ClientHeight, а размер графической поверхности компонента image — значениями свойств width и Height. Левой верхней точке рабочей области формы соответствует элемент pixels [0,0], а правой нижней -Pixels[Ciientwidth - 1,ClientHeight - 1].

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

    Например, если некоторая функция f(x) может принимать значения от нуля до 1000, и для вывода ее графика используется область формы высотой в 250 пикселов, то масштаб оси Y вычисляется по формуле: т = 250/1000. Таким образом, значению f(x) = 70 будет соответствовать точка с координатой Y =233. Значение координаты Y вычислено по формуле

    Y= h -f(x) х т = 250 - 70х(250/1000),
    где h - высота области построения графика.

    Обратите внимание на то, что точное значение выражения 250 - 70х(250/1000) равно 232,5. Но т. к. индексом свойства pixels, которое используется для вывода точки на поверхность Canvas, может быть только целое значение, то число 232,5 округляется к ближайшему целому, которым является число 233.

    Следующая программа, текст которой приведен в листинге 10.5, используя свойство pixels, выводит график функции у = 2 sin(jc) e*/5. Для построения графика используется вся доступная область формы, причем если во время работы программы пользователь изменит размер окна, то график будет выведен заново с учетом реальных размеров окна.



    Влияние значение свойства Transparent на вывод изображения

    Рисунок 10.14. Влияние значение свойства Transparent на вывод изображения


    Влияние значение свойства Transparent на вывод изображения




    Вывод иллюстраций

    Вывод иллюстраций

    Наиболее просто вывести иллюстрацию, которая находится в файле с расширением bmp, jpg или ico, можно при помощи компонента image, значок которого находится на вкладке Additional палитры (Рисунок 10.11).



    Вывод текста

    Вывод текста

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

    Объект.Canvas.TextOut(x, у, Текст)

    где:

  • объект — имя объекта, на поверхность которого выводится текст;
  • х, у — координаты точки графической поверхности, от которой выполняется вывод текста (Рисунок 10.3);
  • Текст — переменная или константа символьного типа, значение которой определяет выводимый методом текст.


  • Загрузка битового образа из ресурса программы

    Загрузка битового образа из ресурса программы

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

    Значения параметров метода Arc

    Рисунок 10.7. Значения параметров метода Arc определяют дугу как часть эллипса (окружности)


    Значения параметров метода Arc




    Значения параметров метода Ellipse

    Рисунок 10.6. Значения параметров метода Ellipse определяют вид геометрической фигуры

    Значения параметров метода Ellipse

    Цвет, толщина и стиль линии эллипса определяются значениями свойства Реп, а цвет и стиль заливки области внутри эллипса — значениями свойства Brush поверхности (canvas), на которую выполняется вывод.

    Значения параметров метода Pie

    Рисунок 10.9. Значения параметров метода Pie определяют сектор как часть эллипса (окружности)


    Значения параметров метода Pie




    Значок компонента Image

    Рисунок 10.11. Значок компонента Image

    Значок компонента Image

    В табл. 10.8 перечислены основные свойства компонента image.



    Значок компонента Timer

    Рисунок 10.16. Значок компонента Timer


    Значок компонента Timer





    Звезда

    Рисунок 10.5. Звезда

    Звезда

    Примечание

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


    Основы языка Delphi

    Диалоговое окно программы Фунтыкилограммы

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


    Диалоговое окно программы Фунтыкилограммы





    Диалоговое окно программы Звукозапись

    Рисунок 11.8. Диалоговое окно программы Звукозапись

    Диалоговое окно программы Звукозапись

    Источником звука для программы Звукозапись может быть микрофон, аудио-CD или любое другое подключенное к линейному входу звуковой платы компьютера устройство, например аудиомагнитофон. Кроме того, возможно микширование (смешение) звуков различных источников.

    Создается WAV-файл следующим образом. Сначала нужно определить источник (или источники) звука. Чтобы это сделать, надо открыть Регулятор громкости (для этого надо щелкнуть на находящемся на панели задач изображении динамика и из появившегося меню выбрать команду Регулятор громкости) и из меню Параметры выбрать команду Свойства. Затем в появившемся окне Свойства (Рисунок 11.9) выбрать переключатель Запись и в списке Отображаемые регуляторы громкости установить флажки, соответствующие тем устройствам, сигнал с которых нужно записать. После щелчка на кнопке ОК на экране появляется окно Уровень записи (Рисунок 11.10), используя которое, можно управлять уровнем сигнала (громкостью) каждого источника звука в общем звуке и величиной общего, суммарного сигнала, поступающего на вход программы Звукозапись. Величина сигнала задается перемещением движков соответствующих регуляторов. Следует обратить внимание на то, что движки регуляторов группы Уровень доступны только во время процесса записи звука. На этом подготовительные действия заканчиваются. Теперь можно приступить непосредственно к записи звука.



    Диалоговое окно Sound

    Рисунок 11.18. Диалоговое окно Sound


    Диалоговое окно Sound





    Диалоговое окно Свойства

    Рисунок 11.9. Диалоговое окно Свойства


    Диалоговое окно Свойства





    Диалоговое окно Уровень записи

    Рисунок 11.10. Диалоговое окно Уровень записи позволяет управлять записываемым сигналом

    Диалоговое окно Уровень записи

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

    Во время записи в диалоговых окнах можно наблюдать изменение сигнала на выходе микшера (индикатор Громкость диалогового окна Уровень) и на входе программы записи. На Рисунок 11.11 в качестве примера приведен вид диалогового окна Звукозапись во время записи звука.



    Диалоговое окно Звукозапись во время записи

    Рисунок 11.11. Диалоговое окно Звукозапись во время записи

    Диалоговое окно Звукозапись во время записи

    Для остановки процесса записи следует щелкнуть на кнопке Стоп.

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

    Существует несколько форматов звуковых файлов. В частности, возможно сохранение звука с различным качеством как стерео, так и моно. Здесь следует понимать, что чем выше качество записи, тем больше места на диске компьютера требуется для хранения соответствующего WAV-файла. Считается, что для речи приемлемым является формат "22050 Гц, 8 бит, моно", а музыки - "44100 Гц, 16 бит, моно" или "44100 Гц, 16 бит, стерео".

    Форма и диалоговое окно программы Использование MediaPlayer

    Рисунок 11.12. Форма и диалоговое окно программы Использование MediaPlayer


    Форма и диалоговое окно программы Использование MediaPlayer





    Форма программы Просмотр анимации

    Рисунок 11.3. Форма программы Просмотр анимации


    Форма программы Просмотр анимации





    Форма программы Звуки Microsoft Windows

    Рисунок 11.6. Форма программы Звуки Microsoft Windows

    Форма программы Звуки Microsoft Windows

    Значения измененных свойств компонента MediaPlayerl приведены в табл. 11.6, значения остальных свойств оставлены без изменения.



    Характеристики ролика отображаются в окне Movie Properties

    Рисунок 11.16. Характеристики ролика отображаются в окне Movie Properties

    Характеристики ролика отображаются в окне Movie Properties

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

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

    Чтобы создать следующий кадр, нужно из меню Insert выбрать команду Keyframe. В результате в текущий слой будет добавлен кадр, в который будет скопировано содержимое предыдущего кадра (так как в большинстве случаев следующий кадр создается путем изменения предыдущего). Теперь можно нарисовать второй кадр. Аналогичным образом создаются остальные кадры анимации.

    Иногда не нужно, чтобы новый кадр содержал изображение предыдущего, в этом случае вместо команды Keyframe нужно воспользоваться командой Blank Keyframe.

    Если некоторое изображение должно оставаться статичным в течение времени, кратного выводу нескольких кадров, то вместо того, чтобы вставлять в слой несколько одинаковых кадров (Keyframe), нужно сделать кадр статичным. Если кадр, изображение которого должно быть статичным, является последним кадром ролика, то в окне Timeline нужно выделить кадр, до которого изображение должно оставаться статичным, и из меню Insert выбрать команду Frame. Если кадр, изображение которого должно быть статичным, не является последним, то нужно выделить этот кадр и несколько раз из меню Insert выбрать команду Frame.

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

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

    Чтобы выводимая анимация сопровождалась звуком, нужно сначала сделать доступным соответствующий звуковой файл. Для этого надо из меню File выбрать команду Import и добавить в проект звуковой файл (Рисунок 11.17).



    Импорт звукового файла

    Рисунок 11.17. Импорт звукового файла

    Импорт звукового файла

    Затем в окне Timeline нужно выделить кадр, при отображении которого должно начаться воспроизведение звукового фрагмента, используя диалоговое окно Sound (Рисунок 11.18), выбрать звуковой фрагмент и задать, если нужно, параметры его воспроизведения. Количество повторов нужно ввести в поле Loops, эффект, используемый при воспроизведении, можно выбрать из списка Effect.

    В качестве примера на Рисунок 11.19 приведен вид окна Timeline в конце работы над анимацией. Анимация состоит из двух слоев. Слой Layer 2 содержит фон. Детали фона появляются постепенно, в течение 9 кадров. После этого фон не меняется, поэтому 9 кадр является статичным. Слой Layer 1 содержит слой основного действия, которое начинается после того, как будет выведен фон. Вывод анимации заканчивается стандартным звуком TADA (его длительность равна одной секунде). Начало воспроизведения звука совпадает с выводом последнего (49-го, если считать от начала ролика) кадра основного действия, поэтому этот кадр сделан статичным в течение вывода следующих 12 кадров (скорость вывода анимации — 12 кадров в секунду). Сделано это для того, чтобы процесс вывода анимации завершился одновременно с окончанием звукового сигнала.



    Эскиз Дельфийского храма

    Рисунок 11.13. Эскиз Дельфийского храма


    Эскиз Дельфийского храма





    Кадры анимации процесса рисования Дельфийского храма

    Рисунок 11.14. Кадры анимации процесса рисования Дельфийского храма

    Кадры анимации процесса рисования Дельфийского храма

    Для решения поставленной задачи можно воспользоваться популярной программой Macromedia Flash 5.

    В Macromedia Flash анимация, которую так же довольно часто называют роликом (Movie), состоит из слоев. В простейшем случае ролик представляет собой один единственный слой (Layer). Слой — это последовательность кадров (Frame), которые в процессе воспроизведения анимации выводятся последовательно, один за другим. Если ролик состоит из нескольких слоев, то кадры анимации получаются путем наложения кадров одного слоя на кадры другого. Например, один слой может содержать изображение фона, на котором разворачивается действие, а другой — изображение персонажей. Возможность формирования изображения путем наложения слоев существенно облегчает процесс создания анимации. Таким образом, чтобы создать анимацию, нужно распределить изображение по слоям и для каждого слоя создать кадры.

    После запуска Macromedia Flash на фоне главного окна программы появляется окно Move1 (Рисунок 11.15), которое используется для создания анимации. В верхней части окна, которая называется Timeline, отражена структура анимации, в нижней части, которая называется рабочей областью, находится изображение текущего кадра выбранного слоя. После запуска Macromedia Flash анимация состоит из одного слоя (Layer 1), который в свою очередь представляет один пустой (чистый) кадр.



    Компонент Animate

    Компонент Animate

    Компонент Animate, значок которого находится на вкладке Win32 (Рисунок 11.1), позволяет воспроизводить простую анимацию, кадры которой находятся в AVI-файле.



    Компонент MediaPlayer

    Компонент MediaPlayer

    Компонент MediaPlayer, значок которого находится на вкладке System (Рисунок 11.4), позволяет воспроизводить видеоролики, звук и сопровождаемую звуком анимацию.

    Рисунок 11.5. Компонент MediaPlayer


    Компонент MediaPlayer


    Использование компонента Animate

    Листинг 11.1. Использование компонента Animate

    unit ShowAVI_; interface

    uses

    Windows, Messages, SysUtils,
    Classes, Graphics, Controls,
    Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls;

    type

    TForm1 = class(TForm)

    Animate1: TAnimate; // компонент Animate

    Button1: TButton; // кнопка Пуск-Стоп

    Button2: TButton; // следующий кадр

    Button3: TButton; // предыдущий кадр

    RadioButton1: TRadioButton; // просмотр всей анимации

    RadioButton2: TRadioButton; // покадровый просмотр

    procedure Button1Click(Sender: TObject);

    procedure Button2Click(Sender: TObject);


    procedure Button3Click(Sender: TObject);

    procedure RadioButton1Click(Sender: TObject);

    procedure RadioButton2Click(Sender: TObject);


    private

    { Private declarations } public

    { Public declarations ) end;

    var

    Form1: TForm1; // форма

    CFrame: integer; // номер отображаемого кадра

    // в режиме покадрового просмотра
    implementation {$R *.DFM}

    // к следующему кадру

    procedure TForm1.Button2Click(Sender: TObject);


    begin

    if CFrame = 1 then Button2.Enabled := True;
    if CFrame < Animate1.FrameCount then begin

    CFrame := CFrame + 1;

    // вывести кадр

    Animate1.StartFrame := CFrame;

    Animate1.StopFrame := CFrame;

    Animate1.Active := True;

    if CFrame = Animatel.FrameCount // текущий кадр — последний

    then Button2.Enabled:=False;
    end;
    end;

    // к предыдущему кадру

    procedure TForm1.Button3Click(Sender: TObject);


    begin

    if CFrame = Animate1.FrameCount

    then Button2.Enabled := True;
    if CFrame >
    1 then begin

    CFrame := CFrame — 1;

    // вывести кадр

    Animate1.StartFrame := CFrame;

    Animate1.StopFrame := CFrame;

    Animate1.Active := True;

    if CFrame = 1 // текущий кадр — первый

    then Form1.Button3.Enabled := False;
    end;
    end;

    // активизация режима просмотра всей анимации
    procedure TForml.RadioButtonlClick(Sender: TObject);

    begin

    Buttonl.Enabled:=True; //доступна кнопка Пуск

    // сделать недоступными кнопки покадрового просмотра

    Form1.Button3.Enabled:=False ;

    Form1.Button2.Enabled:=False;
    end;

    // активизация режима покадрового просмотра

    procedure TForm1.RadioButton2Click(Sender: TObject);


    begin

    Button2.Enabled:=True; // кнопка Следующий кадр доступна
    Buttons.Enabled:=False; // кнопка Предыдущий кадр недоступна

    // сделать недоступной кнопку Пуск — вывод всей анимации
    Buttonl.Enabled:=False; end;

    // пуск и остановка просмотра анимации
    procedure TForm1.ButtonlClick(Sender: TObject);

    begin

    if Animate1.Active = False // в данный момент анимация не выводится

    then begin

    Animate1.StartFrame:=l; // вывод с первого

    Animate1.StopFrame:=Animate1.FrameCount; // по последний кадр

    Animate1.Active:=True;

    Button1.caption:='Стоп';

    RadioButton2.Enabled:=False;
    end

    else // анимация отображается
    begin

    Animate1.Active:=False; // остановить отображение

    Button1.caption:='Пуск';

    RadioButton2.Enabled:=True;
    end;
    end;

    end.

    Компонент Animate позволяет программисту использовать в своих программах стандартные анимации Windows. Вид анимации определяется значением свойства СommonAVI. Значение свойства задается при помощи именованной константы. В табл. 11.3 приведены некоторые значения констант, вид анимации и описание процесса, для иллюстрации которого используется эти анимации.



    Программа Звуки Microsoft Windows

    Листинг 11.2. Программа Звуки Microsoft Windows

    unit WinSound_; interface

    uses

    Windows, Messages, SysUtils,
    Classes, Graphics, Controls, Forms,

    Dialogs, StdCtrls, MPlayer;

    type

    TForm1 = class(TForm)

    MediaPlayerl: TMediaPlayer; // медиаплеер

    Label1: TLabel; // информационное сообщение

    ListBox1: TListBox; // список WAV-файлов

    Label2: TLabel; // выбранный из списка файл

    procedure FormActivate(Sender: TObject);


    procedure ListBoxlClick(Sender: TObject);


    procedure MediaPlayerlClick(Sender: TObject; Button: TMPBtnType;

    var DoDefault: Boolean);
    private

    { Private declarations } public

    { Public declarations } end;

    const

    SOUNDPATCH='с:\winnt\media\'; // положение звуковых файлов
    var

    Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.FormActivate(Sender: TObject);

    var

    SearchRec: TSearchRec; // структура, содержащая информацию о файле,

    // удовлетворяющем условию поиска
    begin

    Form1.MediaPlayer1.Play ;

    // сформируем список WAV-файлов, находящихся

    // в каталоге c:\winnt\media

    if FindFirst(SOUNDPATCH+'*.wav', faAnyFile, SearchRec) =0 then

    begin

    // в каталоге есть файл с расширением WAV

    // добавим имя этого файла в список

    Form1.ListBox1.Items.Add(SearchRec.Name) ;

    // пока в каталоге есть другие файлы с расширением WAV

    while (FindNext(SearchRec) = 0) do

    Form1.ListBox1.Items.Add(SearchRec.Name);

    end;
    end;

    // щелчок на элементе списка

    procedure TForm1.ListBoxlClick(Sender: TObject);


    begin

    // вывести в поле метки Label2 имя выбранного файла

    Label2.Caption:=ListBox1.Items[ListBox1.itemlndex];
    end;

    // щелчок на кнопке компонента Media Player

    procedure TForm1.MediaPlayerlClick(Sender: TObject; Button: TMPBtnType;

    var DoDefault: Boolean);
    begin

    if (Button = btPlay) and (Label2.Caption <>
    '') then

    begin

    // нажата кнопка Play
    with MediaPlayerl do begin

    FileName:=SOUNDPATCH+Label2.Caption; // имя выбранного файла
    Open; // открыть и проиграть звуковой файл
    end;
    end;
    end;

    end.

    Воспроизведение звука сразу после запуска программы активизирует процедура обработки события onFormActivate путем применением метода Play к компоненту MediaPlayerl (действие этого метода аналогично щелчку на кнопке Воспроизведение). Эта же процедура формирует список WAV-файлов, находящихся в каталоге C:\Winnt\Media. Для формирования списка используются функции FindFirst и FindNext, которые, соответственно, выполняют поиск первого и следующего (по отношению к последнему, найденному функцией FindFirst или FindNext) файла, удовлетворяющего указанному при вызове функций критерию. Обеим функциям в качестве параметров передаются маска WAV-файла (критерий поиска) и переменная -структура searchRec, поле Name которой в случае успешного поиска будет содержать имя файла, удовлетворяющего критерию поиска.

    Щелчок на элементе списка обрабатывается процедурой TForm1.ListBox1Click, которая выводит в поле метки Label2 имя файла, выбранного пользователем (во время работы программы свойство ItemIndex содержит номер элемента списка на котором выполнен щелчок).

    В результате щелчка на одной из кнопок компонента MediaPiayeri активизируется процедура TForm1.MediaPiayer1Сlick, которая проверяет, какая из кнопок компонента была нажата. Если нажата кнопка Воспроизведение (btPlay), то в свойство FileName компонента MediaPiayeri записывается имя выбранного пользователем файла, затем метод open загружает этот файл и активизирует процесс его воспроизведения.

    Наличие у компонента MediaPiayer свойства visible позволяет скрыть компонент от пользователя и при этом применять его для воспроизведения звука без участия пользователя. Например, следующая программа пересчитывает вес из фунтов в килограммы и сопровождает выдачу результата звуковым сигналом. В случае, если пользователь забудет ввести исходные данные или введет их неверно, программа выведет сообщение об ошибке, также сопровождаемое звуковым сигналом. Вид диалогового окна программы во время ее разработки приведен на Рисунок 11.7, значения свойств компонента MediaPlaer в табл. 11.7. Текст модуля программы приведен в листинге 11.3.



    Использование компонента

    Листинг 11.3. Использование компонента MediaPlayer для вывода звука

    unit FuntToKg1_; interface

    uses

    Windows, Messages, SysUtils,
    Classes, Graphics, Controls,
    Forms, Dialogs, StdCtrls, MPlayer;

    type

    TForm1 = class(TForm)

    Edit1: TEdit; // поле ввода веса в фунтах

    Button1: TButton; // кнопка Пересчет

    Label2: TLabel; // поле вывода результата

    Label1: TLabel; // поле информационного сообщения

    MediaPlayer1: TMediaPlayer; // медиаплеер

    procedure Button1Click(Sender: TObject);

    private

    { Private declarations }
    public

    { Public declarations }
    end;

    var

    Form1: TForm1;

    implementation

    {$R *.DFM)

    // щелчок на кнопке Пересчет

    procedure TForm1.ButtonlClick(Sender: TObject);


    var

    f: real; // вес в фунтах k: real; // вес в килограммах
    begin

    form1.Label2.Caption: =' ';

    try // возможна ошибка, если в поле

    // Edit1 будет не число
    f:=StrToFloat(Edit1.Text);


    Forml.MediaPlayer1.Play;
    // звуковой сигнал k:=f*0.4095;
    Label2.caption:=Editl.text+' ф. - это ' +

    FloatToStrF(k,ffGeneral,4,2}+' кг. ';
    except

    on EConvertError do // ошибка преобразования
    begin

    // определим и проиграем звук "Ошибка"

    Form1.MediaPlayer1.FileName:=
    'c:\windows\media\chord.wav';
    Form1.MediaPlayer1.Open;

    Form1.MediaPlayer1.Play; // звуковой сигнал
    ShowMessage('Ошибка! Вес следует ввести числом.');

    form1.Edit1.SetFocus; // курсор в поле ввода
    // восстановим звук

    Forml.MediaPlayer1.FileName:=
    'c:\windows\media\ding.wav';
    Forml.MediaPlayer1.Open;
    end;
    end;
    end;
    end.

    Воспроизведение анимации сопровождаемой звуком

    Листинг 11.4. Воспроизведение анимации, сопровождаемой звуком

    uses

    Windows, Messages, SysUtils,
    Classes, Graphics, Controls,
    Forms, Dialogs, MPlayer, StdCtrls, ExtCtrls;

    type

    TForm1 = class(TForm)

    Label1: TLabel; // информационное сообщение

    Panel1: TPanel; // панель, на которую выводится анимация

    Button1: TButton; // кнопка OK

    MediaPlayer1: TMediaPlayer; // универсальный проигрыватель

    procedure ButtonlClick(Sender: TObject);


    procedure FormCreate(Sender: TObject);

    private

    { Private declarations ) public

    { Public declarations } end;

    var

    Form1: TForm1 ;

    implementation

    ($R *.DFM}

    procedure TForm1.ButtonlClick(Sender: TObject);

    begin

    MediaPlayer1.Play; // воспроизведение анимации

    end;

    procedure TForm1.FormCreate(Sender: TObject);

    begin

    // зададим размер области вывода анимации
    // на поверхности формы

    MediaPlayer1.DisplayRect:=Rect(0,0,60,60);

    end;

    end.

    Процесс воспроизведения анимации активизируется применением метода Play, что эквивалентно нажатию кнопки Play в случае, если кнопки компонента MediaPlayer доступны пользователю.

    На вкладке Сводка отражается информация об AVIфайле

    Рисунок 11.2. На вкладке Сводка отражается информация об AVI-файле


    На вкладке Сводка отражается информация об AVIфайле





    Окно Export Windows AVI

    Рисунок 11.20. Окно Export Windows AVI

    Окно Export Windows AVI

    Если установлен переключатель Compress video, то после щелчка на кнопке ОК появится диалоговое окно, в котором можно будет выбрать один из стандартных методов сжатия видео. При выборе видео и звукового формата нужно учитывать, что чем более высокие требования будут предъявлены к качеству записи звука и изображения, тем больше места на диске займет AVI-файл. Здесь следует иметь в виду, что завышенные требования не всегда оправданы.

    Окно Movie в начале работы над новой анимацией

    Рисунок 11.15. Окно Movie в начале работы над новой анимацией

    Окно Movie в начале работы над новой анимацией

    Перед тем как приступить непосредственно к созданию кадров анимации, нужно задать общие характеристики анимации (ролика): размер кадров и скорость их воспроизведения. Характеристики вводятся в поля диалогового окна Movie Properties (Рисунок 11.16), которое появляется в результате выбора из меню Modify команды Movie. В поле Frame Rate нужно ввести скорость воспроизведения ролика, которая измеряется в кадрах в секунду (fps — frame per second, кадров в секунду), в поля Width и Height — ширину и высоту кадров. В этом же окне можно выбрать фон кадров (список Background Color).



    Пример анимации

    Рисунок 11.19. Пример анимации

    Пример анимации

    После того как ролик будет готов, его надо сохранить. Делается это обычным образом, то есть выбором из меню File команды Save.

    Для преобразования файла из формата Macromedia Flash в AVI-формат нужно из меню File выбрать команду Export Movie и задать имя файла. Затем в появившемся диалоговом окне Export Windows AVI (Рисунок 11.20) нужно задать размер кадра (поля Width и Height), из списка Video Format выбрать формат, в котором будет записана видеочасть ролика, а из поля Sound Format — формат звука.



    Просмотр видеороликов и анимации

    Просмотр видеороликов и анимации

    Помимо воспроизведения звука, компонент MediaPiayer позволяет просматривать видеоролики и мультипликации, представленные как AVI-файлы (AVI — это сокращение от Audio Video Interleave, что переводится как чередование звука и видео, т. е. AVI-файл содержит как звуковую, так и видеоинформацию) .

    Процесс использования компонента MediaPiaer для посмотра содержимого AVI-файла рассмотрим на примере программы, которая в результате щелчка на командной кнопке воспроизводит на поверхности формы простую сопровождаемую звуковым эффектом мультипликацию — вращающееся по часовой стрелке слово Delphi (файл delphi.avi, содержащий этот мультик, находится на прилагаемом к книге диске).

    Вид диалогового окна программы приведен на Рисунок 11.12, а значения свойств компонента MediaPlayerl — В табл. 11.8.



    Создание анимации

    Создание анимации

    Процесс создания файла анимации (AVI-файла) рассмотрим на примере. Пусть надо создать анимацию, которая воспроизводит процесс рисования эскиза Дельфийского храма (окончательный вид рисунка представлен на Рисунок 11.13, несколько кадров анимации — на Рисунок 11.14).



    Свойство

    Свойство

    Значение

    FileName

    bart.avi

    Active

    False

    Transparent

    True

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

    Кнопка Button1 используется как для инициализации процесса воспроизведения анимации, так и для его приостановки. Процесс непрерывного воспроизведения анимации инициирует процедура обработки события Onclick на кнопке Пуск, которая присваивает значение True свойству Active. Эта же процедура заменяет текст на кнопке Button1 с Пуск на Стоп. Режим воспроизведения анимации выбирается при помощи переключателей Ra-dioButton1 и RadioButton2. Процедуры обработки события Onclick на этих переключателях изменением значения свойства Enabled блокируют или, наоборот, делают доступными кнопки управления: активизации воспроизведения анимации (Buttoni), перехода к следующему (Button2) и предыдущему (Buttons) кадру. Во время непрерывного воспроизведения анимации процедура обработки события OnCkick на кнопке Стоп (Buttoni) присваивает значение False свойству Active и тем самым останавливает процесс воспроизведения анимации.



    Свойства компонента Animate

    Таблица 11.1. Свойства компонента Animate

    Свойство

    Определяет

    Name

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

    FileName

    Имя AVI-файла в котором находится анимация, отображаемая при помощи компонента

    StartFrame

    Номер кадра, с которого начинается отображение анимации

    stopFrame

    Номер кадра, на котором заканчивается отображение анимации

    Activate

    Признак активизации процесса отображения кадров анимации

    Color

    Цвет фона компонента (цвет "экрана"), на котором воспроизводится анимация

    Transparent

    Режим использования "прозрачного" цвета при отображении анимации

    Repetitions

    Количество повторов отображения анимации

    Следует еще раз обратить внимание, что компонент Animate предназначен для воспроизведения AVI-файлов, которые содержат только анимацию. При попытке присвоить записать в свойство FileName имя файла, который содержит звук, Delphi выводит сообщение о невозможности открытия указанного файла (Cannot open AVI). Чтобы увидеть, что находиться в AVI-файле: анимация и звук или только анимация, нужно из Windows раскрыть нужную папку, выделить AVI-файл и из контекстного меню выбрать команду Свойства. В результате этого откроется окно Свойства, на вкладке Сводка (Рисунок 11.2) которого будет выведена подробная информация о содержимом выбранного файла.

    Следующая программа, текст которой приведен в листинге 11.1, демонстрирует использование компонента Animate для отображения в диалоговом окне программы анимации. Вид формы программы приведен на Рисунок 11.3, а значения свойств компонента Animatel — в таблице 11.2.



    Значения свойств компонента

    Таблица 11.2. Значения свойств компонента Animate1



    Значение свойства comonAVi определяет анимацию

    Таблица 11.3. Значение свойства comonAVi определяет анимацию

    Значение

    Анимация

    Процесс

    aviCopyFiles
    Значение свойства comonAVi определяет анимацию
    Копирование файлов
    AviDeleteFile
    Значение свойства comonAVi определяет анимацию
    Удаление файла
    aviRecycleFile
    Значение свойства comonAVi определяет анимацию
    Удаление файла в корзину


    Кнопки компонента MediaPlayer

    Таблица 11.4. Кнопки компонента MediaPlayer

    Кнопка

    Обозначение

    Действие

    Воспроизведение

    btPlay

    Воспроизведение звука или видео

    Пауза

    btPause

    Приостановка воспроизведения

    Стоп

    btStop

    Остановка воспроизведения

    Следующий

    btNext

    Переход к следующему кадру

    Предыдущий

    btPrev

    Переход к предыдущему кадру

    Шаг

    btStep

    Переход к следующему звуковому фрагменту, например, к следующей песне на CD

    Назад

    btBack

    Переход к предыдущему звуковому фрагменту, например, к предыдущей песне на CD

    Запись

    btRecord

    Запись

    Открыть/Закрыть

    btEject

    Открытие или закрытие CD-дисковода компьютера



    Свойства компонента MediaPiayer

    Таблица 11.5. Свойства компонента MediaPiayer

    Свойство

    Описание

    Name DeviceType

    FileName AutoOpen Display

    VisibleButtons

    Имя компонента. Используется для доступа к свойствам компонента и управлением работой плеера

    Тип устройства. Определяет конкретное устройство, которое представляет собой компонент MediaPiayer. Тип устройства задается именованной константой: dtAutoSelect — тип устройства определяется автоматически; dtVaweAudio — проигрыватель звука; dtAVivideo — видеопроигрыватель; dtCDAudio — CD-проигрыватель

    Имя файла, в котором находится воспроизводимый звуковой фрагмент или видеоролик

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

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

    Составное свойство. Определяет видимые кнопки компонента. Позволяет сделать невидимыми некоторые кнопки



    Значения свойств компонента

    Таблица 11.6. Значения свойств компонента MediaPlayer1

    Компонент

    Значение

    DeviceType

    DtAutoSelect

    FileName

    C:\Winnt\Media\3вук Microsoft.wav

    AutoOpen

    True

    VisibleButtons . btNext

    False

    VisibleButtons .btPrev

    False

    VisibleButtons . btStep

    False

    VisibleButtons . btBack

    False

    VisibleButtons . btRecord

    False

    VisibleButtons .btEject

    False





    Значения свойств компонента

    Таблица 11.7. Значения свойств компонента MediaPiayer1

    Свойство

    Значение

    Name DeviceType

    FileName

    MediaPiayer1

    dtAutoSelect с : \winnt\media\ding . wav

    Свойство

    Значение

    AutoOpen

    Visible

    True

    False





    Создается форма приложения обычным образом.

    Таблица 11.8. Значения свойств компонента MediaPlayer1

    Свойство

    Значение

    Name

    MediaPlayer1

    FileName

    delphi.avi

    DeviceType

    dtAVIVideo

    AutoOpen

    True

    Display

    Panel1

    Visible

    False

    Создается форма приложения обычным образом. Компонент Paneii используется в качестве экрана, на который осуществляется вывод анимации, и его имя принимается в качестве значения свойства Display компонента MediaPlayeri. Поэтому сначала к форме лучше добавить компонент Panel и затем — MediaPlayer. Такой порядок создания формы позволяет установить значение свойства Display путем выбора из списка.

    Следует особо обратить внимание на то, что размер области вывода анимации на панели определяется не значениями свойств width и Height панели (хотя их значения должны быть как минимум такими же, как ширина и высота анимации). Размер области определяется значением свойства

    DisplayRect компонента MediaPlayer. Свойство DisplayRect ВО время разработки программы недоступно (его значение не выводится в окне Object Inspector). Поэтому значение свойства DisplayRect устанавливается во время работы программы в результате выполнения инструкции

    MediaPlayer1.DisplayReet:=Rect(0,0,60,60).

    Замечание

    Чтобы получить информацию о размере кадров AVI-файла, надо, используя возможности Windows, открыть папку, в которой находится этот файл, щелкнуть правой кнопкой мыши на имени файла, выбрать команду Свойства и в появившемся диалоговом окне — вкладку Сводка, в которой выводится подробная информация о файле, в том числе и размер кадров.

    Текст программы приведен в листинге 11.4.



    Воспроизведение звука

    Воспроизведение звука

    Звуковые фрагменты находятся в файлах с расширением WAV. Например, в каталоге C:\Winnt\Media можно найти файлы со стандартными звуками Windows.

    Следующая программа (вид ее диалогового окна приведен на Рисунок 11.6, а текст - в листинге 11.2) демонстрирует использование компонента ediaPiayer для воспроизведения звуковых фрагментов, находящихся в WAV-файлах.

    Помимо компонента MediaPiayer на форме находится компонент ListBox и два компонента Label, первый из которых используется для вывода информационного сообщения, второй — для отображения имени WAV-файла, выбранного пользователем из списка.

    Работает программа следующим образом. После появления диалогового окна воспроизводится "Звук Microsoft", затем пользователь может из списка выбрать любой из находящихся в каталоге C:\Windows\Media звуковых файлов и после щелчка на кнопке Воспроизведение услышать, что находится в этом файле.



    Запись звука

    Запись звука

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

    Наиболее просто получить представление нужного звукового фрагмента в виде WAV-файла можно при помощи входящей в состав Windows программы Звукозапись. Программа Звукозапись, вид ее диалогового окна приведен на Рисунок 11.8, запускается из главного меню Windows при помощи команды Пуск | Программы | Стандартные | Развлечения | Звукозапись.



    Значок компонента Animate

    Рисунок 11.1. Значок компонента Animate

    Значок компонента Animate

    Примечайте
    Хотя анимация, находящаяся в AVI-файле может сопровождаться звуковыми эффектами (так ли это — можно проверить, например, при помощи стандартной программы Проигрыватель Windows Media), компонент Animate обеспечивает воспроизведение только изображения. Для полноценного воспроизведения сопровождаемой звуком анимации следует использовать компонент меdiaPlayer.

    Компонент Animate добавляется к форме обычным образом. После добавления компонента к форме следует установить значения его свойств. Свойства компонента Animate перечислены в табл. 11.1.



    Значок компонента MediaPlayer

    Рисунок 11.4. Значок компонента MediaPlayer

    Значок компонента MediaPlayer

    В результате добавления к форме компонента MediaPlayer на форме появляется группа кнопок (Рисунок 11.5), подобных тем, которые можно видеть на обычном аудио- или видеоплеере. Назначение этих кнопок пояснено в табл. 11.4. Свойства компонента MediaPlayer приведены в табл. 11.5.



    Основы языка Delphi

    Безусловный переход

    Безусловный переход

    Инструкция GoTo

    GoTo Метка;

    Инструкция осуществляет переход к инструкции, перед которой стоит метка. Метка должна быть объявлена в разделе label.


    Циклы

    Циклы

    Инструкция for

    Вариант 1 (с увеличением счетчика):

    for Счетчик:=НачальноеЗначение to КонечноеЗначение do begin

    { здесь инструкции } end;

    Инструкции между begin и end выполняется (КонечноеЗначение - НачальноеЗначение) + 1 раз.

    ЕСЛИ НачальноеЗначение > КонечноеЗначение, ТО инструкции между begin И

    end не выполняются.

    Примечание

    Если между begin и end находится только одна инструкция, то слова begin и end можно не писать.

    Вариант 2 (с уменьшением счетчика)'.

    for Счетчик:=НачальноеЗначение downto КонечноеЗначение do begin

    { здесь инструкции } end;

    Инструкции между begin и end выполняется (НачальноеЗначение - КонечноеЗначение) + 1 раз.

    Если НачальноеЗначение < КонечноеЗначение, то инструкции между begin и end не выполняются.

    Примечание

    Если между begin и end находится только одна инструкция, то слова begin и end можно не писать.

    Инструкции выбора

    Инструкции выбора

    Инструкция if

    Вариант 1: if-then-else. if Условие then

    begin

    { Инструкции, которые выполняются, ) { если условие истинно. } end else

    begin

    { Инструкции, которые выполняются, } { если условие ложно } end ;

    Вариант 2. if-then.

    if Условие then

    begin

    { Инструкции, которые выполняются, } { если условие истинно. } end;

    Примечание

    Если между begin и end находится только одна инструкция, то слова begin и end можно не писать.

    Инструкция case

    Инструкция case

    Вариант 1:

    case Выражение of

    Список1_Констант: begin

    . { инструкции } end; Список2_Констант: begin

    { инструкции } end;

    СписокJ_Констант: begin

    { инструкции } end; end;

    Вариант 2.

    case Выражение of

    Список1_Констант: begin

    { инструкции } end;

    Список2_Констант: begin

    { инструкции } end; СписокJ_Констант: begin

    { инструкции J} end; else

    begin

    { инструкции } end; end;

    Инструкции между begin и end выполняются, если значение выражения, записанного после case, совпадает с константой из соответствующего списка. Если это не так, то выполняются инструкции, находящиеся после else, между begin И end.

    Примечание

    Если между begin и end находится только одна инструкция, то слова begin и end можно не писать.

    Инструкция repeat

    Инструкция repeat

    repeat

    { инструкции } until Условие;

    Сначала выполняются инструкции цикла, которые расположены между repeat и until. Затем вычисляется значение выражения Условие, и если оно равно False, то инструкции цикла выполняются еще раз. И так до тех пор, пока значение выражения Условие не станет равным True.

    Инструкция while

    Инструкция while

    while Условие do begin

    { инструкции ) end;

    Сначала проверяется Условие, если оно истинно, то выполняются инструкции между begin и end. Затем снова проверяется Условие. Если оно выполняется, то инструкции цикла выполняются еще раз. И так до тех пор, пока Условие не станет ложным.

    Примечание

    Если между begin и end находится только одна инструкция, то слова begin и end можно не писать.

    Массив

    Массив

  • Объявление одномерного массива:
  • ИмяМассива: array [НижнийИндекс...ВерхнийИндекс] of ТипЭлементов;

  • Объявление двумерного массива:
  • ИмяМассива: array [НижнийИндекс1..ВерхнийИндекс1,

    НижнийИндекс2..ВерхнийИкдекс2] of ТипЭлементов;


    Объявление функции

    Объявление функции

    function ИмяФункции(var Параметр1: Тип 1; var Параметр2: Тип2;

    var ПараметрJ: TиnJ ) : Тип; const

    { описание констант } var

    / описание переменных } begin

    { инструкции функции }

    Result:=Значение; end;

    Примечание

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


    Объявление процедуры

    Объявление процедуры

    procedure ИмяПроцедуры(var Параметр1: Тип1;

    var Параметр2: Тип2;

    var ПараметрJ: TипJ } ; const

    { описание констант }

    var

    { описание переменных } begin

    { инструкции процедуры } end;

    Примечание

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

    Основные типы данных

    Основные типы данных

    К основным типам данных языка Delphi относятся: П целые числа (integer); П дробные числа (real); П символы (char);

  • строки (string);
  • логический тип (boolean).
  • Целые числа и числа с плавающей точкой могут быть представлены в различных форматах (табл. П1.1 и П2.2).



    Стандартные функции и процедуры

    Стандартные функции и процедуры

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



    Строки

    Строки

  • Объявление переменной-строки длиной 255 символов:
  • Имя:string;

  • Объявление переменной-строки указанной длины:
  • Имя:string [ ДлинаСтроки ].

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

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

    Модуль состоит из последовательности разделов. Каждый раздел начинается ключевым словом и продолжается до начала следующего раздела.

    unit ИмяМодуля;

    interface // раздел интерфейса

    { Здесь находятся описания процедур и функций модуля, коч-орые могут использоваться другими модулями. )

    const // раздел объявления констант

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

    type // раздел объявления типов

    { Здесь находятся объявления глобальных типов модуля,

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

    var // раздел объявления переменных

    { Здесь находятся объявления глобальных переменных модуля, которые могут использоваться процедурами и функциями модуля }

    implementation // раздел реализации

    { Здесь находятся описания (текст) процедур и функций модуля)
    end.

    П1 1 Целые числа

    Таблица П1.1. Целые числа

    Формат

    Диапазон

    Shortint

    -128.. 127

    Integer

    -32 768.. 32 767

    Longint

    -2 147 483 648.. 2 147 483 647

    Byte

    0..255

    Word

    0..65535



    П1 2 Числа с плавающей точкой

    Таблица П1.2. Числа с плавающей точкой

    Формат

    Диапазон

    Кол-во значащих цифр

    Real

    2,9e-39.. 1,7e38

    11-12

    Single

    1,5e-45.. 3,4e38

    7-8

    Double

    5,0e-324.. 1,7e308

    15-16

    Extended

    3,4e-4932.. 1,1e4932

    19-20



    П1 3 Математические функции

    Таблица П1.3. Математические функции

    Функция

    Описание

    Abs (Выражение)

    Абсолютное значение аргумента (целый или вещественный тип)

    Sqr (Выражение)

    Квадрат аргумента (целый или вещественный тип)

    Sqrt( Выражение: real) :real

    Квадратный корень аргумента

    Sin (Выражение: real) : real

    Синус

    Cos (Выражение: real) : real

    Косинус

    Arctant Выражение: real) : real

    Арктангенс

    Exp( Выражение: real) :real

    Экспонента

    Ln ( Выражение : real ) : real

    Натуральный логарифм

    В табл. П1.4 приведены описания преобразований языка Delphi.



    П1 4 Преобразования

    Таблица П1.4. Преобразования

    Преобразование

    Описание

    Int( Выражение: real) :real

    Целая часть

    Trunc (Выражение: real) : longint

    Целая часть

    Round (Выражение: real) : longint

    Округление к ближайшему целому

    IntToStr (Выражение)



    Преобразование числового выражения цело-
    го типа в строку

    FloatToStr (Выражение)

    Преобразование вещественного числа в его изображение

    FloatToStrF ( Выражение, Формат, Точность, КоличествоЦифр)

    Преобразование вещественного числа в его изображение с возможностью выбора способа изображения

    StxToInt ( Строка : string)

    Преобразование строки, изображающей целое или вещественное число, в число

    StrToFloat ( Строка : string)

    Преобразование строки, изображающей вещественное число, в число

    В табл. 1.5 приведены описания функций работы со строками и символами.



    П1 7 Работа со строками и символами

    Таблица П1.7. Работа со строками и символами

    Строковая функция

    Описание

    Concat( Строка1: string, ... , Строкам: string) : string

    Copy ( Строка : string , НомерСимвола : integer, Длина: integer) : string

    Delete (var Строка :srting, НомерСимвола : integer, Сколько : integer)

    Length (Строка: string) : integer Pos (Строка: string, Подстрока: string) :byte Chr ( КодСимвола : byte )

    Объединение нескольких строк в одну

    Выделение подстроки
    Удаление части строки

    Длина строки Позиция подстроки в строке Символ с указанным кодом



    Запись

    Запись

    Вариант 1. Объявление записи в разделе переменных: Запись: record Поле1:Тип1; Поле2: Тип2;

    ПолеJ: TиnJ; end;

    Вариант 2. Сначала объявляется тип-запись, затем — переменная-запись:

    type

    ТипЗапись = record Поле1: Тип1; Поле 2:Тип2;

    ПолеК: ТипК; end;

    var

    За пись: ТипЗапись;

    Зарезервированные слова и директивы

    Зарезервированные слова и директивы

    Зарезервированные слова:

    and

    File

    not

    then

    array

    For

    object

    to

    asm

    function

    of

    type

    begin

    Goto

    or

    unit

    case

    If

    packed

    until

    const

    implementation

    procedure

    uses

    constructor

    In

    program

    var

    destructor

    inherited

    record

    while

    div

    inline

    repeat

    with

    do

    intenface

    set

    xor

    downto

    Label

    shl



    else

    Mod

    shr



    end

    Nil

    string



    Директивы:

    absolute
    assembler
    external

    Far
    forward
    interrupt

    near
    private
    public

    virtual



    Основы языка Delphi

    Десятичные и двоичные числа

    Десятичные и двоичные числа

    В обыденной жизни человек имеет дело с десятичными числами. В десятичной системе счисления для представления чисел используются цифры от О до 9. Значение числа определяется как сумма произведений цифр числа на весовой коэффициент, определяемый местом цифры в числе. Весовой коэффициент самой правой цифры равен единице, цифры перед ней — десяти, затем ста и т. д. Например, число 2703 равно 2x1000+7x100+0x10+3x1.

    Если места цифр пронумеровать справа налево и самой правой позиции присвоить номер "ноль", то можно заметить, что вес i-го разряда равен i-й степени десяти (Рисунок П3.1).



    Память компьютера

    Память компьютера

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

    Память используется для хранения переменных. Так как переменные различных типов могут принимать различные значения, то для их хранения нужно разное количество памяти. Память под переменные выделяется целым числом байтов. Например, значением переменной типа char может быть любой из 256 символов. Поэтому для хранения переменной этого типа достаточно одного байта. Значением переменной типа integer может быть число от -32 768 до 32 767 (65 535 значений), для хранения переменной этого типа требуется два байта. Очевидно, что чем больше диапазон значений типа, тем больше байтов нужно для хранения переменной этого типа (табл. П3.1).



    Для внутреннего представления чисел

    Рисунок П3.1.

    Для внутреннего представления чисел

    Для внутреннего представления чисел компьютер использует двоичную систему счисления. Двоичные числа записываются при помощи двух цифр -нуля и единицы. Как и десятичная, двоичная система — позиционная. Весовой коэффициент i-го разряда равен двум в i-й степени (Рисунок П3.2).



    Рисунок П3 2

    Рисунок П3.2.

    Рисунок П3 2


    П3 1 Диапазоны значений

    Таблица П3.1. Диапазоны значений и занимаемая память для разных типов переменных

    Тип переменной

    Занимаемая память (количество байтов)

    Диапазон значений

    Char

    1

    Любой символ

    String

    256

    Строка до 256 символов

    String [n]

    1хn

    Строка до n символов

    Тип переменной

    Занимаемая память (количество байтов)

    Диапазон значений

    Byte

    1

    0-255

    Word

    2

    0-65 535

    Integer

    2

    -32 768-32 767

    Longint

    4

    -2 147 483 648-2 147 483 647

    Real

    6

    2,9е-39-1 ,7е38

    Single

    4

    1,5е-45-3,4е38

    Double

    8

    5,0е-324-1 ,7е308

    Extended

    8

    3,4е-4932-1,1е4932

    В программе для хранения одного и того же значения можно использовать переменные разных типов (при этом будет применяться разное количество памяти). Например, если в программе используется переменная Day, содержащая число месяца, то для нее можно задать тип byte, integer или longint. В первом случае будет занят один байт памяти, во втором — два, в третьем — четыре. Но реально будет использоваться только один байт, а остальные будут только заняты. Поэтому, выбирая тип для переменной, следует подбирать наиболее подходящий тип для каждой конкретной ситуации. Особо необходимо обращать внимание на описание строковых переменных и массивов.

    Выделяя память для строковых переменных, следует помнить, что если не указана предельная длина строки, то переменной выделяется 256 байтов. Объявляя переменную, предназначенную, например, для хранения имени человека, нужно писать name: string [30], а не name: string.

    Каждому массиву программы выделяется память, объем которой определяется как типом элементов массива, так и их количеством. Для хранения двумерного массива, например, 20x20 вещественных чисел нужно более 3 Кбайт памяти (20x20x8 = 3200).

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

    

        Программирование: Языки - Технологии - Разработка