Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Delphi

.pdf
Скачиваний:
27
Добавлен:
13.04.2015
Размер:
1.18 Mб
Скачать

3 ЯЗЫК ПРОГРАММИРОВАНИЯ 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

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]