Delphi
.pdf3 ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal
funF2: begin {вычислить функцию F2}... end; funF3: begin {вычислить функцию F3}... end;
end;
При определении нового скалярного типа вместо перечисления идентификаторов всех его значений можно указать отрезок из некоторого известного скалярного типа (отрезок типа):
Type
<идентиф. скалярного типа>= <нач. значен. отрезка>..<конечн. значен.>;
Например стандартный тип Byte можно рассматривать как отрезок целых чисел, например, Type Byte=0..255;
|
П р и м е р 3.17 |
Type |
|
TIndex |
=1..99; |
TValue |
=-1000..1000; |
TAlphabet = 'A'..'Z'; |
|
Var |
|
i,j |
: TIndex; |
x,y,z |
: TValue; |
c1,c2,c3,c4: TAlphabet;
3.6.2 Множества (Set)
Язык Pascal позволяет работать с переменными как с множествами. Для этого у него существует специальный тип данных. Переменные типа множеств описываются следующим образом:
Type <идентификатор множества> = Set Of <базовый тип множества>
Множественный тип переменной позволяет ей принимать сразу несколько значений (множество данных), но не более чем их указано в базовом типе множества. Базовый тип множества представляет собой или перечислимый тип, или отрезок типа, или простой скалярный тип.
Множества-константы, в отличие от переменных, описываются уточнением типа вводимого идентификатора константы и перечислением конкретных элементов множества, заключенных в квадратные скобки.
П р и м е р 3.18
Type |
|
TLetter =Set Of 'A'..'X'; |
{отрезок типа} |
50
3.6 ОПИСАНИЯ ТИПОВ
TDig |
=Set Of |
11..88; |
{отрезок типа} |
TColor |
=Set Of (colRed,colGreen,colBlue); |
||
|
|
|
{перечислимый тип} |
TAllLet =Set Of Char; |
{скалярный тип} |
||
Const |
|
|
|
MyLet |
|
:Set Of 'a'..'z'=['a','b','c']; |
|
Var |
|
|
|
Dig1, Dig2 |
: TDig; |
|
|
G1,G2, |
|
: TColor; |
|
c1,c2,c3,c4 |
: TAllLet; |
|
В данном примере множества G1, G2 типа TColor могут принимать следующие значения: [colRed]; [colRed,colGreen]; [colRed,colGreen,colBlue];
[colGreen,colBlue]; [colBlue]; [colGreen], [colRed,colBlue], [ ] – пустое множество. Порядок перечисления элементов не имеет значения, например,
множество [colRed,colGreen] равно множеству [colGreen,colRed].
После присваивания c1:=['C'..'A'] множество c1=[ ] т.е. будет пустым, так как отрезок 'C' .. 'A'не содержит ни одного элемента, порядковый номер 'C'больше порядкового номера 'A'.После присваивания К:=7 и Dig1:=[K+10..18] множество Dig1 будет состоять из двух элементов [17,18].
При определении множества нужно учитывать следующие ограничения. Базовый тип множества не может содержать более 256 элементов, порядковые номера которых – это 0÷255. Поэтому базовым типом не могут быть, например, типы Double, Word. Тип Double не может быть базовым, так как он не является скалярным.
Операции над множествами:
A*B – пересечение множеств А и В, например, [Green,Red,Blue]*[Red,Brown]=[Red].
A+B – объединение множеств A и B, например, ['A'..'X']+['Y','Z']=['A'..'Z']. A-B – разность множеств A и B, например, [1, 5, 9]-[2,4,8,9]=[1,5].
A=B – имеет результат True, если множества А и В состоят из одних и тех же элементов, например, ['C'..'E'] = ['C','E','D']равно True.
A<>B – имеет результат True, если множества А и В отличаются хотя бы одним элементом, например, [7,1,3]<>[2,4,6,8] равно True.
A<=B – имеет результат True, если элементы множества А одновременно являются и элементами множества В, например, выражение [Red]<= [Red,Green] имеет значение True.
A>=B – имеет результат True, если элементы множества B одновременно являются и элементами множества A, например, выражение
['A'..'E']>= ['A','E']имеет значение True.
51
3 ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal
element In B – имеет результат True, если element имеется в множестве В, например, 5 In [3..7] имеет значение True.
Для добавления и удаления элементов из множеств, вместо операций + и - , целесообразно использовать более эффективные стандартные процедуры Include(<множество>, <добавляемый элемент>), Exclude(<множество>, <удаляемый элемент>).
П р и м е р 3.19
Выражение
(К+2) In [0..7]*[4, 6, 8]
при К=1 имеет значение False, так как 3 не входит в результат пересечения множеств, т.е. в множество [4,6]. При К=2 выражение принимает значение
True.
3.6.3 Описание массивов (Array)
Массив – это совокупность однотипных элементов к которым можно обращаться по их индексам. Это очень популярный и полезный тип данных. Описание типов массивов имеет вид:
Type
<идентификатор типа> = Array [<тип индексов>] Of <тип элементов>;
Объявление переменных-массивов может осуществляться или указанием на ранее описанный тип или непосредственным описанием:
Var
<идентификаторы массивов> : <идентификатор типа>;
Var
<идент-ры массивов> : Array [<тип индексов>] Of <тип элементов>;
Индексы массивов могут быть скалярного типа или тоже массивами. Максимальный размер массива – это количество элементов × размер элемента = 2 Гбайта.
Массивы являются однотипными, если они описаны под одним словом Type (первый пример объявления переменных-массивов). Одному массиву можно присвоить значение другого массива, не перечисляя их индексы, если они однотипны или идентичны (описаны в Var под одним словом Array). Если массив двухмерный, то первый индекс – это строки
52
3.6 ОПИСАНИЯ ТИПОВ
массива, а второй – столбцы, т.е. все наоборот, по сравнению с ячейками таблиц TStringGrid !
П р и м е р 3.20
Var K: Array[-4..4,Boolean] of Double;
Переменная K – это двухмерный массив из вещественных чисел с общим количеством 9×2=18 элементов и размером 18×8 байт = 144 байта.
Описание однотипных массивов (например, А,В типа MyArray), идентичных массивов и их инициализация осуществляется следующим образом:
Пр и м е р 3.21 (однотипные и идентичные массивы)
//Описание типа массивов:
Type TMyArray=Array[1..10] of Double;
Var
A, B : |
TMyArray; |
{объявление однотипных массивов} |
M1,M2: |
Array[0..5,-5..0] of Double; {идентичные массивы} |
NN: Array[0..5,-5..0] of Double;
//Объявление и инициализация массива С:
C: Array[1..2,1..3] of Double=((11,12,13),(21,22,23));
{- две строки по три элемента}
Присваивание, например, третьему элементу одномерного массива А значения 5 имеет вид: А[3]:=5, а первому элементу двухмерного массива NN - NN [0,-5]:=5. Для идентичных и однотипных массивов допустимо присваивание M1:=M2. При этом все элементы массива M1 станут равными элементам массива M2.Недопустимо присваивание M1:=NN, т. к. они не идентичны и не однотипны.
П р и м е р 3.22 (Символьный массив)
Var A: Array[1..8] of Сhar; |
{ Символьный массив A} |
Это описание эквивалентно описанию Var A: String[8]. К символьным массивам применимы все строковые операции.
П р и м е р 3.23
Вычисление максимального и минимального элементов двухмерного массива.
Const |
M=10; |
N=5; |
// количество строк и столбцов |
Type TItem = |
Double; |
// тип элементов массива |
|
|
TxArr = |
Array [1..M, 1..N] of TItem; //тип массива |
|
Var x |
|
: TxArr; |
|
53
3 ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal
Max, Min : TItem; |
|
|
i,j |
: Integer; |
|
Begin |
|
|
< Ввод элементов массива x[i,j] > |
|
|
(* |
Поиск максимального и минимального элементов: *) |
|
Max:=x[1,1]; Min:= Max; |
|
|
For i:=1 To M Do |
// внешний цикл |
|
For j:=1 To N Do |
// внутренний цикл |
|
begin |
|
|
If x[i,j]>Max Then Max:=x[i,j]; |
|
|
If x[i,j]<Min Then Min:=x[i,j]; |
|
end;
< Вывод максимального Max и минимального Min элементов > end;
Задание 5.
Организация циклов с контрольным выводом итераций
Цель задания
1.Знакомство с операторами циклов и итерационными процессами.
2.Приобретение навыков работы с данными типа множеств.
3.Освоение вывода данных в таблицы.
Постановка задачи
Согласно варианту задания, найдите сумму ряда с общим членом an и
точностью |an| ≤ ε. Организуйте вывод в таблицу номера итерации, значения текущего члена ряда и суммы.
Контроль сходимости ряда должен осуществляться на некотором заданном множестве (тип данных Set) итераций. После попадания на контрольную итерацию делать остановку вычислений. Если наблюдается сходимость ряда – продолжить цикл. Предусмотреть средства очистки таблицы и повтора расчетов, а также средства борьбы с возможным зацикливанием приложения. Типичный интерфейс такой программы приведен на рис. 3.3.
Рекомендации:
При составлении программы с типами переменных невысокой точности необходимо учесть возможность переполнения результатов вычислений, когда число выходит за пределы допустимые для описанного типа. Один из способов, позволяющий избежать такой ситуации – это использование рекуррентных формул для членов ряда (см. пример 3.14). Более
54
3.6 ОПИСАНИЯ ТИПОВ
простой способ – это переход к данным повышенной точности, однако, он менее эффективен, чем предыдущий.
Общий алгоритм работы приложения может быть построен по схеме, представленной на рис. 3.4.
Рис. 3.3 Интерфейс приложения для вывода итераций в таблицу с контролем сходимости
Итерационный цикл организуйте при помощи оператора While или Repeat, поскольку необходимое количество итераций заранее неизвестно.
Остановку вычислений, без закрытия приложения, можно организовывать посредством выхода из текущего обработчика события в раздел Implementation главного модуля. Это можно сделать при помощи процедуры Exit или генерации исключения Raise… (см. раздел «Обработка исключительных ситуаций»). Чтобы продолжить вычисления, необходимо в обработчике соответствующего события предусмотреть начало цикла итераций не с начальных данных, а с текущего значения некоторых глобальных переменных, равных последним значениям, рассчитанным в цикле до его прерывания.
Вывод данных в таблицу следует осуществлять при помощи компонента
TStringGrid – таблица строк, которая находится на странице Additional в палитре компонент. Обращение к ячейкам таблицы осуществляется через свойство Cells[<номер столбца>,<номер строки>]. Нумерация начинается с нуля. Перечислим другие свойства таблицы:
55
3 ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal
ColCount – количество колонок; DefaultColWidth – ширина колонок по умолчанию; DefaultRowHeight – высота колонок по умолчанию; FixedCols – количество ячеек, зафиксированных для заголовков колонок; FixedRows – количество ячеек, зафиксированных для заголовков строк; GridLineWidth – толщина линий сетки таблицы; RowCount – количество строк; ScrollBars – расположение слайдеров (линеек прокрутки) в таблице;
Раздел Interface
Раздел Implementation
Обработчик кнопки « Закрыть»
Обработчик кнопки « Старт»
отключить кнопки «Старт», «Очистить», «Продолжить», показать – « Стоп», задать начальные значения всем глобальным переменным и вызвать обработчик кнопки «Продолжить»
Обработчик кнопки « Продолжить»
цикл вычисления суммы ряда (без задания начальных условий, они – в кнопке «Старт») с наращиванием строк таблицы вывода и вывод в неё результатов. В цикле:
1.проверка нажатия кнопки «Стоп», через значение соответствующей логической переменной после обработки очереди сообщений.
2.проверка попадания на множество заданных итераций. При любом попадании – отключить кнопку «Стоп», показать кнопки «Старт», «Очистить», «Продолжить» и выйти из блока.
Обработчик кнопки « Стоп»
Изменить значение глобальной логической переменной – признака остановки вычислений для обработчика кнопки «Продолжить».
Обработчик кнопки « Очистить»
Задать начальное количество строк в таблице вывода результатов.
Обработчик « Создание формы»
Создать заголовки в таблице вывода результатов.
56
3.6 ОПИСАНИЯ ТИПОВ
Рис. 3.4 Главный модуль и его основные блоки.
Заголовки столбцов целесообразно создать до начала работы приложения, в момент создания формы. Для этого необходимо обработать событие формы OnCreate:
procedure TForm1.FormCreate(Sender: TObject); begin
StringGrid1.Cells[0,0]:='Номер'; StringGrid1.Cells[1,0]:='Член ряда'; StringGrid1.Cells[2,0]:='Сумма ряда';
end;
Поскольку максимальное количество строк в таблице заранее неизвестно, то можно на этапе построения приложения через инспектор объектов задать только одну строку для заголовков столбцов, а при вычислении каждой новой итерации добавлять очередную строку:
StringGrid1.RowCount := StringGrid1.RowCount + 1; Для очистки таблицы необходимо установить начальное количество строк равным 1.
Начальные значения глобальных переменных (номер итерации, член ряда…) целесообразно задавать в обработчике кнопки «Старт». Сам цикл лучше организовывать отдельно – в обработчике кнопки «Продолжить». Теперь, что бы при нажатии на кнопку «Старт» начал работать цикл, надо в конце обработчика «Старт» вызвать обработчик «Продолжить». Например, если идентификатор кнопки «Продолжить» был btnNext, то вызов её существующего обработчика можно сделать посредством оператора btnNextClick(Self);
Варианты задания: |
|
|
|
an = (n!) (2n)!, ε =5×10-8 |
||||||
1. |
an |
= (−1)n−1 nn , |
ε =10-25. |
6. |
||||||
|
|
|
n |
n |
|
-15 |
|
a = n! nn |
|
-17 |
2. |
an = 1 2 |
|
+ 1 3 , |
ε =2×10 . |
7. |
n |
, |
ε =10 . |
||
|
|
|||||||||
3. a |
= (2n −1) / 2n , ε =5×10-16. |
8. an = 2n n! (nn )!, ε =2×10-27. |
||||||||
|
n |
= 1 ((3n − 2)(3n +1)), ε =5×10-10. |
|
a = 3n n! (3n)!, ε =5×10-15. |
||||||
4. |
a |
9. |
||||||||
|
n |
|
|
|
|
|
|
n |
|
(2n2 )!, ε =10-26. |
5. |
an |
= 10n |
|
n!, ε =2×10-17. |
|
10. an = (n!)2 |
|
Контрольные вопросы для сдачи лабораторной работы:
1. Какие типы циклов имеются в языке Object Pascal?
57
3ЯЗЫК ПРОГРАММИРОВАНИЯ Object Pascal
2.Какого типа может быть параметр цикла For?
3.Как можно войти и выйти из цикла?
4.Что такое переполнение и исчезновение числа, и как с этим бороться?
5.Какие операции допустимы с множествами?
6.Как в Object Pascal реализуется возведение в степень?
7.Как убрать или скрыть ненужный визуальный объект в приложении?
8.Как организовать остановку и продолжение вычислений?
3.6.4Ссылочные типы данных, указатели (Pointer)
В языке Pascal есть возможность по ходу выполнения программы выделять и освобождать необходимую память оперативного запоминающего устройства (ОЗУ). Область ОЗУ, где можно динамически выделять отдельные блоки для размещения данных и освобождать их, называется "хипом" (Неар – куча). Максимальный размер каждого блока – 2 Гбайта. Поочередное размещение и удаление больших блоков в хипе, например, массивов, позволяет существенно экономить ОЗУ. Очевидно, что это очень мощный механизм создания эффективных приложений.
Неявно вы уже сталкивались с динамическим размещением данных – это строки String и списки строк TStrings. В Delphi их длина регулируется автоматически. Однако существуют и специальные типы данных.
Динамические данные являются переменными ссылочного типа или указателями. Они указывают, ссылаются на адрес в хипе, где находится блок требуемых данных, т.е. они хранят адреса блоков, а не сами данные. Такие переменные (ссылки) можно описывать двумя способами:
с указанием типа данных, например, Var X,Y: ^Double; без указания типа данных, например, Var P1: Pointer;
Конструкция ^<тип> означает, что переменные X,Y будут указывать адреса блоков для размещения данных заданного типа, в частности, - типа Double. Тип Pointer указывает на то, что переменной P1 будет поставлен в соответствие адрес блока какого-либо данного без уточнения его типа.
Для обращения к данным (к содержимому блоков хипа) посредством ссылки на их адреса необходимо использовать конструкцию <идентификатор ссылки>^. Символ ^ отправляет нас за данными по указанному адресу.
Для работы с указателями существуют стандартные процедуры:
GetMem(<указатель>,<размер блока в байтах>: Integer) – выделяет в хипе блок памяти заданного размера и адрес блока заносит в указатель;
FreeMem(<указатель>) – освобождает блок памяти по указанному адресу. Область хипа становится свободной для повторного использования, а указатель приобретает неопределенное значение;
58
3.6 ОПИСАНИЯ ТИПОВ
New(<указатель>) – выделяет в хипе блок памяти согласно указателю.
New(P)= GetMem(P,SizeOf(P^)).
Dispose(<указатель>) – уничтожает динамическую переменную, размещенную через New, т.е. освобождает блок хипа с адресом, указанным в указателе;
П р и м е р 3.24
Организация динамических массивов посредством указателей.
Const N=100; |
|
|
// Размер массивов |
Type |
|
|
|
TArr = Array[1..N] of Double; |
// Введение типа массивов |
||
PArr = ^TArr; |
// Введение типа указателей на адреса массивов |
||
Var |
|
|
|
Array1,Array2: PArr; |
{ Объявление указателей на адреса |
||
|
|
|
массивов типа TArr} |
i: Integer; |
|
|
|
Begin
//Выделение блока памяти из хипа для массива с адресом,
//содержащимся в указателе Array1:
GetMem(Array1,N*8); |
{N*8 – размер блока для массива |
|
|
|
из N вещественных чисел. |
|
Можно использовать New(Array1)} |
|
For i:=1 To N Do Array1^[i]:=1; |
{Работа с массивом} |
|
... |
|
|
// Освобождение блока памяти: |
|
|
FreeMem(Array1,N*8); |
|
{или Dispose(Array1), |
|
если использовалось New(Array1)} |
|
... |
|
|
3.6.5 Динамический массив
В отличие от массива с фиксированным числом элементов у динамического массива число элементов заранее не задается. Это число уточняется и, соответственно, динамически выделяется ОЗУ в процессе работы приложения. Такие массивы более удобны и эффективны в работе, чем массивы, созданные при помощи указателей.
Описание, например, одномерного динамического типа-массива имеет вид:
Type
<имя типа-массива> = Array Of <тип элементов массива>; Для двухмерного массива:
Type
59