- •Методическое пособие для самостоятельных работ «Основы интегрированной среды программирования delphi6»
- •6.100301 "Судовождение",
- •6.100302 "Эксплуатация судовых энергетических установок"
- •6.092201 "Электрические системы и комплексы транспортных средств",
- •Введение
- •Глава 1. Интегрированная среда Delphi. Принципы работы
- •1.1. Интегрированная среда Delphi
- •1.2. Принципы визуального программирования
- •Val(Edit1.Text,k1,sign);
- •Val(Edit2.Text,k2,sign);
- •Val(MaskEdit1.Text,r1,sig);
- •Val(МaskEdit2.Text,r2,sig);
- •1.3. Событийно-управляемые программы
- •1.4. Составление программ обработки массивов
- •I :integer;
- •I, j :integer;
- •1.5. Вывод на печать
- •Глава 2. Общие свойства компонентов
- •2.1. Иерархия компонентов
- •2.2. Имена и собственники компонентов
- •2.3. Родительские и дочерние компоненты
- •2.4. Положение, размеры и оформление компонентов
- •2.5.Указатели мыши
- •2.3. Окно редактора с готовым изображением указателя
- •2.6. Реакция на события от мыши и клавиатуры
- •2.6.1. События от мыши
- •2.6.2. События от клавиатуры
- •2.6.3. Клавиатура в ms-dos и Windows
- •2.6.4. Фокус ввода
- •2.7. Механизм действий Action
- •2.8. Иинтерфейс Drag&Drop
- •2.9. Иинтерфейс Drag&Dock
- •2.10. Поддержка справочной службы
- •2.11. Поддержка Сом
- •2.12. Свойства разного назначения
- •Глава 3. Использование компонентов общего назначения
- •3.1. Компоненты страницы Standard
- •3.1.1. TFrame - рама и шаблоны компонентов
- •6) Окно регистрации рамы в палитре компонентов
- •3.1.2. Создание шаблонов без рам
- •3.1.3. TMainMenu - главное меню формы (программы)
- •3.1.4. TPopupMenu - вспомогательное (локальное) меню
- •3.1.5. TLabel - метка для отображения текста
- •3.1.6. TEdit - ввод и отображение строки
- •3.1.7. TMemo - ввод и отображение текста
- •3.1.8. TButton - кнопка
- •3.1.9. TCheckBox - независимый переключатель
- •3.11. Компонент tCheckBox - независимый переключатель
- •3.1.10. TRadioButton - зависимые переключатели
- •3.1.11. TListBox - список выбора
- •3.1.12. TComboBox – комбинированный или раскрывающийся список выбора
- •3.1.13. TScrollBar - управление значением величины
- •3.1.14. TGroupBox - панель группирования
- •3.1.15. TRadioGroup - группа зависимых переключателей
- •3.1.16. TPanel - панель
- •3.1.17. TActionList - механизм действий
- •3.2. Компоненты страницы Аdditional
- •3.2.1. TBitBtn - кнопка с изображением
- •3.2.2. TSpeedButton - кнопка для инструментальных панелей
- •3.2.3. TMaskEdit - специальный редактор
- •3.2.4. TStringGrid - таблица строк
- •3.2.5. TDrawGrid - произвольная таблица
- •3.2.6. TImage - отображение картинок
- •3.2.7. TShape - стандартная фигура
- •3.2.8. TBevel - кромка
- •3.2.9. TScrollBox - панель с прокруткой
- •3.2.10. TСheckListBox - группа независимых переключателей
- •3.2.11. TSplitter - компонент для изменения размеров
- •3.2.12. TStaticText - метка для отображения текста
- •3.2.13. TControlBar - инструментальная панель
- •3.2.14. TApplicationEvents - обработчик сообщений Windows
- •3.2.15. TValueListEditor - специализированный редактор строк
- •3.2.16. TLabelEdit - однострочный редактор с меткой
- •3.2.17. TColorBox - список выбора цвета
- •3.2.18. TChart - построитель графиков
- •3.2.19. TActionManager - менеджер действий
- •3.2.20. TActionMainMenuBar - полоса меню для действий
- •3.2.21. TActionTollBar - полоса кнопок для действий
- •3.2.22. TCustomizeDIg - диалог настройки интерфейса
- •Глава 4. Многодокументный и однодокументный интерфейсы (mdi и sdi)
- •4.1. Mdi и sdi: сравнение
- •4.2. Разработка mdi—приложений
- •4.2.1. Разработка главного и информационного окон
- •4.2.2. Использование стандартных диалоговых окон
- •If OpenDialog1.Execute then
- •4.2.3. Разработка диалогового окна
- •Var dlg6:tokRightDlg;
- •X1,x2,x3:String;
- •If b1 or b2 then
- •4.2.4. Управление окнами
- •I:integer;
- •I:integer;
- •4.2.5. Работа с меню
- •Var tf5:tForm2;
- •4.3. Разработка sdi–приложения
- •4.3.1. Простое sdi–приложение
- •I,j :byte;
- •I,j :byte;
- •I,j :byte;
- •4.3.2. Управление окнами в sdi–приложениях
- •I :byte;
- •Var I :byte; ptr6 :tForm2;
- •I :byte;
- •Глава 5. Реализация алгоритмов решаемых задач на Delphi
- •5.1. Традиционный подход реализации алгоритмов на Delphi
- •5.2. Объектно-ориентированный подход
- •Val(Edit1.Text,k,sig);
- •Val(Edit2.Text,l,sig);
- •I,j :byte;
- •I,j :integer;
- •Inherited Create (Ni,Nj);
- •Val(Edit1.Text, p, sig1);
- •Val(Edit2.Text, q, sig2);
- •Val(Edit3.Text, r, sig3);
- •Vas :real;
- •Val(Edit4.Text,n,sig);
- •Глава 6. Тестирование и отладка приложений
- •6.1. Виды ошибок
- •6.2. Отладочные средства Delphi
- •6.3. Составление тестов
- •Глава 7. Исключительные ситуации
- •7.1. Обработка исключительных ситуаций
- •I, j, k : integer;
- •I:integer;
- •I, j, k : integer;
- •7.2. Обработка определенных исключительных ситуаций
- •Var I,j,k :shortint; p,q :real;
- •Заключение
- •Литература
- •Методическое пособие для самостоятельных работ «Основы интегрированной среды программирования delphi6»
- •6.100301 "Судовождение",
- •6.100302 "Эксплуатация судовых энергетических установок"
- •6.092201 "Электрические системы и комплексы транспортных средств",
6.3. Составление тестов
До ввода в эксплуатацию приложение должно быть всесторонне проверено. Дадим в этом параграфе некоторые рекомендации. При разработке событийно-управляемой программы естественно требовать, чтобы она правильно реагировала на все возможные события. Разделим условно события на два класса:
события без исходных данных;
события с исходными данными.
К первому классу относятся, например, выход из программы, управление расположением окон. Для проверки реакции приложения на такие события надо их просто вызвать и убедиться в правильности реакций на них. Требуется проверить все пункты меню, кнопки нажатия, все возможные комбинации радиокнопок и кнопок выбора.
Сложнее обстоит дело с событиями, которым требуются исходные данные. В таком случае придется заняться составлением тестов. Как показывает практика, много ошибок в программах вызваны просто невнимательностью программистов. Поэтому перечислим здесь ряд вопросов, на которые следует обращать внимание уже на стадии написания программ (в нашем случае процедур реализации пунктов меню, кнопок и собственных алгоритмов):
Существуют ли обращения к переменным, не имеющим значения? Если Вы пользуетесь значениями по умолчанию, убедитесь, что они соответствуют требуемым; лучше присвоить все исходные значения явно.
Находятся ли индексы в допустимых границах? Не забудьте, что в массивах на Pascal’e и в объекте StringGrid разная очередность индексов.
Находятся ли значения переменных в допустимых для данного типа данных границах? Это касается и промежуточных результатов.
Имеются ли вычисления с нечисловыми данными? Нет ли возможности потенциальной ошибки в преобразованиях типов данных? Процедура val( ); функции StrToInt, StrToFloat. . . Согласуются ли типы числовых данных при вычислениях (тип результата деления целых не всегда целый).
Возможны ли недопустимые значения аргументов функций (например, логарифм отрицательного числа), деление на нуль, квадратный корень отрицательного числа?
Соблюдается ли требуемая очередность операций в арифметических и логических выражениях? Простое правило: если сомневаетесь – ставьте скобки, они никогда не мешают. Правильно ли в выражениях расставлены скобки?
Правильно ли расставлены пары Begin. . .End; некоторые программисты рекомендуют: если набрали Begin, наберите сразу же и End и вставьте нужные операторы между ними. Не забудьте, когда за End нужна ; а когда нет!
Существует ли потенциальная возможность зацикливания в циклах while . . do и repeat . . until, изменяется ли условие продолжения (прерывания) цикла по ходу его выполнения?
Соответствуют ли формальные и фактические параметры по количеству, типу и очередности?
Если решается задача, имеющая физическую суть, согласованы ли единицы измерения?
Приведенными здесь вопросами не исчерпываются возможные подводные камни при программировании. Остается лишь рекомендовать: будьте внимательны, часто труднее всего обнаружить самые простые ошибки, потому что никто даже не догадается, что там тоже можно ошибиться.
Имеется два подхода к тестированию:
функциональное тестирование (тестирование по данным, тестирование “черного ящика”);
структурное тестирование (тестирование по управлению, тестирование “белого ящика”).
При функциональном тестировании структура программы при составлении тестов не используется. Задают исходные данные и анализируют полученный результат.
При структурном тестировании тесты составляют на основе анализа структуры программы.
Наиболее распространенным методом функционального тестирования является эквивалентное разбиение: всю область значений исходных данных разбивают на конечное число классов эквивалентности так, чтобы можно было предположить, что каждый тест, являющийся представителем некоторого класса, эквивалентен любому другому тесту этого класса. Например, исходя из определения модуля y=abs(x), можем выделить два класса эквивалентности: x>=0 и x<0. Различают:
правильные классы эквивалентности, представляющие допустимые значения исходных данных;
неправильные классы эквивалентности, представляющие недопустимые значения исходных данных.
В примере с модулем неправильным классом эквивалентности является случай, когда вместо х используется нечисловое значение. Для y=ln(x) правильным классом эквивалентности является x>0; неправильными классами x<=0 и нечисловое значение х. Программа должна быть составлена таким образом, чтобы исходные данные из неправильных классов эквивалентности не вызывали программные прерывания во время решения, а лишь сообщение об этом, запрашивание новых исходных данных или возврат в исходное состояние. Например, в системе продажи билетов, если кассир ошибочно ввел дату 30.02, то необходимо запрашивать новую и продолжать работу. Чтобы это обеспечить, программа должна быть протестирована на всех правильных и неправильных классах эквивалентности.
Для структурного тестирования необходимо обеспечить комбинаторное покрытие условий, чтобы все возможные комбинации результатов условий выполнялись по крайней мере один раз. Проиллюстрируем это на примере следующего отрывка программы:
if (a>1)AND(b=0) then x:=x/a;
if (a=2)OR(x>1) then x:=x+1;
Нужны тесты, удовлетворяющие следующим условиям:
1. |
a>1 b=0 |
5. |
a=2 x>1 |
2. |
a>1 b<>0 |
6. |
a=2 x<=1 |
3. |
a<=1 b=0 |
7. |
a<>2 x>1 |
4. |
a<=1 b<>0 |
8. |
a<>2 x<=1 |
Для того, чтобы протестировать эти комбинации, достаточно 4 теста:
x=4 a=2 b=0 покрывает 1, 5;
x=1 a=2 b=1 покрывает 2, 6;
x=2 a=0 b=0 покрывает 3, 7;
x=1 a=0 b=1 покрывает 4, 8.
Для составления тестов надо сначала составить приведенную таблицу для всех условных операторов, а затем составить перечень тестов, чтобы их общее количество было минимальным.
Программа должна протестироваться как функционально, так и структурно. Кроме того, необходимо проверять работу программы в разных случаях, учитывающих специфику решаемой задачи, например:
файл пуст, в массиве нет элементов;
требуется найти максимальный элемент, но все элементы равны; требуется выделить n наибольших элементов, но n-1, n и n+1 элементы имеют одинаковые значения (после упорядочения).
Контрольные вопросы
Что такое синтаксическая ошибка? Возможности их устранения.
Поясните понятия: тестирование, отладка, испытание программы.
Поясните понятие трассировка.
Для чего используются окна просмотра?
Что такое точки прерываний?
Поясните понятие функциональне тестирование.
Поясните понятие структурное тестирование.
Что такое эквивалентное разбиение?
Какие классы эквивалентного разбиения вы знаете?
Примеры составления программ
Иллюстрация пробной версии программы
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Label1: TLabel;
Label2: TLabel;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
end.
Тестовая программа
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls;
type
TfmExample = class(TForm)
Panel1: TPanel;
bbRun: TBitBtn;
bbClose: TBitBtn;
edInput: TEdit;
lbOutput: TLabel;
mmOutput: TMemo;
private
{ Private declarations }
public
{ Public declarations }
end;
var
fmExample: TfmExample;
implementation
{$R *.dfm}
end.
Иллюстрация процедурных типов
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Buttons, ExtCtrls;
type
TfmExample = class(TForm)
Panel1: TPanel;
bbRun: TBitBtn;
bbCancel: TBitBtn;
edInput: TEdit;
mmOutput: TMemo;
lbOutput: TLabel;
procedure bbRunClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
fmExample: TfmExample;
implementation
{$R *.dfm}
Function Sin1(X: Real): Real;
begin
Result := (Sin(X) + 1) * Exp(-X)
end; // Sin1
Function Cos1(X: Real): Real;
begin
Result := (Cos(X) + 1) * Exp(-X)
end; // Cos1
procedure TfmExample.bbRunClick(Sender: TObject);
type
Func = function (X: Real): Real; // Процедурный тип
Procedure PrintFunc(NP: Integer; F: Func) ;
var
k: Integer;
X: Real;
begin
for k := 0 to NP do
begin
X := k * 2 * pi / NP;
mmOutput.Lines.Add(FloatToStrF(X, ffExponent, 10, 2) +
#9 + #9 + FloatToStrF(F(X), ffExponent, 10, 2));
end;
end; // PrintFunc
begin // bbRunClick
mmOutput.Lines.Add(#9'Функция SIN1:');
PrintFunc(10, Sin1);
mmOutput.Lines.Add(#9'Функция COS1:');
PrintFunc(10, Cos1);
end;
end.
Отображение свойств объекта
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Buttons, ExtCtrls;
type
TfmExample = class(TForm)
Panel1: TPanel;
bbRun: TBitBtn;
bbClose: TBitBtn;
edInput: TEdit;
lbOutput: TLabel;
mmOutput: TMemo;
procedure bbRunClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
fmExample: TfmExample;
implementation
{$R *.DFM}
procedure TfmExample.bbRunClick(Sender: TObject);
var
MemSourceStream, MemDestStream: TMemoryStream;
begin
MemSourceStream := TMemoryStream.Create;
try
MemDestStream := TMemoryStream.Create;
try
MemSourceStream.WriteComponent(bbRun);
MemSourceStream.Seek(0, soFromBeginning);
ObjectBinaryToText(MemSourceStream, MemDestStream);
MemDestStream.Seek(0, soFromBeginning);
mmOutput.Lines.LoadFromStream(MemDestStream)
finally
MemDestStream.Free
end;
finally
MemSourceStream.Free
end;
end;
end.
Демонстрация отображения файла в память
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, ComCtrls, Spin;
type
TForm1 = class(TForm)
btMem: TButton;
btFile: TButton;
se: TSpinEdit;
Label1: TLabel;
pb: TProgressBar;
Label2: TLabel;
lbMem: TLabel;
lbFile: TLabel;
procedure btMemClick(Sender: TObject);
procedure btFileClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.btMemClick(Sender: TObject);
// Создание файла методом его отображения
type
PReal = ^Real;
var
HFile, HMap: THandle;
AdrBase, AdrReal: PReal;
k: Integer;
FSize: Cardinal;
BegTime: TDateTime;
begin
BegTime := Time; // Засекаем время пуска
// Готовим ProgressBar:
pb.Max := se.Value;
pb.Position := 0;
pb.Show;
FSize := se.Value * SizeOf(Real); // Длина файла
HFile := FileCreate('test.dat'); // Создаем файл
if HFile = 0 then // Ошибка: возбуждаем исключение
raise Exception.Create('Ошибка создания файла');
try
// Отображаем файл в память
HMap := CreateFileMapping(HFile, NIL, PAGE_READWRITE, 0, FSize, NIL);
if HMap = 0 then // Ошибка: возбуждаем исключение
raise Exception.Create('Ошибка отображения файла');
try
// Создаем окно просмотра:
AdrBase := MapViewOfFile(HMap, FILE_MAP_WRITE, 0, 0, FSize);
if AdrBase = NIL then // Ошибка: возбуждаем исключение
raise Exception.Create('Невозможно просмотреть файл');
// Сохраняем начальный адрес для правильной ликвидации
// окна просмотра:
AdrReal := AdrBase;
for k := 1 to se.Value do
begin
AdrReal^ := Random; // Помещаем в файл новое число
// Перед наращиванием текущего адреса необходимо
// привести его к типу Integer или Cardinal:
AdrReal := Pointer(Integer(AdrReal) + SizeOf(Real));
lbMem.Caption := IntToStr(k);
pb.Position := k;
Application.ProcessMessages;
end;
// Освобождаем окно просмотра:
UnmapViewOfFile(AdrBase)
finally
// Освобождаем отображение
CloseHandle(HMap)
end
finally
// Закрываем файл
CloseHandle(HFile)
end;
// Сообщаем время счета
pb.Hide;
lbMem.Caption := TimeToStr(Time-BegTime)
end;
procedure TForm1.btFileClick(Sender: TObject);
// Создание файла обычным методом
var
F: File of Real;
k: Integer;
BegTime: TDateTime;
R: Real; // Буферная переменная для обращение к Write
begin
BegTime := Time; // Засекаем начальное время счета
// Готовим ProgressBar:
pb.Max := se.Value;
pb.Position := 0;
pb.Show;
// Создаем файл:
AssignFile(F, 'test.dat');
Rewrite(F);
for k := 1 to se.Value do
begin
R := Random; // Параметрами обращения к Write
Write(F, R); // могут быть только переменные
lbFile.Caption := IntToStr(k);
pb.Position := k;
Application.ProcessMessages;
end;
CloseFile(F);
pb.Hide;
lbFile.Caption := TimeToStr(Time-BegTime)
end;
end.
Иллюстрация использования функции CreateFontIndirect
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
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
X: Integer;
LF: TLogFont;
Fnt: HFont;
const
Text = 'Лучшая в мире система программирования';
begin
// Определяем параметры нового шрифта
FillChar(LF, SizeOf(LF), 0);
with LF do
begin
lfHeight := 20;
lfWeight := fw_Medium;
lfUnderline := 1;
lfEscapement := 450;
StrPCopy(lfFaceName, 'Courier New Cyr');
end;
with Form1.Canvas do
begin
// Создаем шрифт
Fnt := CreateFontIndirect(LF);
// Присваиваем его дескриптор шрифту канвы
Font.Handle := Fnt;
// Выводим текст под углом +45 градусов
TextOut(0, 300, Text);
X := TextWidth(Text);
DeleteObject(Fnt); // Удаляем ненужный шрифт
// Изменяем параметры шрифта
with LF do
begin
lfHeight := 120;
lfEscapement := -900;
lfWeight := fw_Heavy;
StrPCopy(LF.lfFaceName, 'Arial Cyr');
end;
Fnt := CreateFontIndirect(LF); // Создаем новый шрифт
Font.Handle := Fnt;
Font.Color := clRed;
// Выводим с наклоном -90 градусов
TextOut(X+10, 10, 'Delphi');
DeleteObject(Fnt); // Удаляем ненужный шрифт
end;
end;end.
Задания для самостоятельного выполнения
Ввести в компонент Memo1 строку, состоящую из нескольких слов. Составить из данной строки новую строку, в которую войдут только слова, содержащие не более 7 букв. Вывести полученную строку в компонент Label1.
Ввести в компонент Memo1 строку, состоящую из нескольких слов. Поменять местами первое и последнее слова в строке. Вывести новую строку в компонент Label1.
Ввести в компонент Memo1 строку, состоящую из нескольких слов. Составить строку, в которую войдут слова исходной строки имеющие четное количество букв. Вывести новую строку в компонент Label1.
Ввести в компонент Memo1 строку, состоящую из нескольких слов. Заменить в строке слова, содержащие нечетное количество букв, на номер слова. Вывести новую строку в компонент Label1.
Ввести в компонент Memo1 строку, состоящую из нескольких слов. Ввести букву в компонент Edit1. Заменить в исходной строке первую и последнюю букву пятого слова на заданную букву. Вывести новую строку в компонент Label1.
Ввести в компонент Memo1 строку, состоящую из нескольких слов. Ввести букву в компонент Edit1. Заменить в каждом слове строки каждую третью букву на букву, заданную в компоненте Edit1. Вывести новую строку в компонент Label1.
Ввести в компонент Memo1 строку, состоящую из нескольких слов. Заменить все слова, содержащие не менее пяти букв, на слово «пример». Вывести новую строку в компонент Label1.