ТИПЫ ДАННЫХ


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

ПРОСТЫЕ ТИПЫ


К простым типам относятся порядковые, вещественные типы и тип дата-время.
Порядковые типы отличаются тем, что каждый из них имеет конечное количество возможных значений. Эти значения можно определенным образом упорядочить (отсюда - название типов) и, следовательно, с каждым из них можно сопоставить некоторое целое число - порядковый номер значения.
Вещественные типы , строго говоря, тоже имеют конечное число значений, которое определяется форматом внутреннего представления вещественного числа. Однако количество возможных значений вещественных типов настолько велико, что сопоставить с каждым из них целое число (его номер) не представляется возможным.
Тип дата-время предназначен для хранения даты и времени. Фактически для этих целей он использует вещественный формат.
Порядковые типы
К порядковым типам относятся (см. целые, логические, символьный, перечисляемый и тип-диапазон. К любому из них применима функция Ord(x), которая возвращает порядковый номер значения выражения X.
Для целых типов функция ord(x) возвращает само значение х, т. е. Ord(X) = х для х, принадлежащего любому целому типу. Применение Ord(x) к логическому, символьному и перечисляемому типам дает положительное целое число в диапазоне от 0 до 1 (логический тип), от 0 до 255 (символьный), от 0 до 65535 (перечисляемый). Тип-диапазон сохраняет все свойства базового порядкового типа, поэтому результат применения к нему функции ord(X) зависит от свойств этого типа.
К порядковым типам можно также применять функции:
pred(x) - возвращает предыдущее значение порядкового типа (значение, которое соответствует порядковому номеру
ord (X) -1), т. е. Ord(Pred(X)) = Ord(X) - 1;
succ (X) - возвращает следующее значение порядкового типа, которое соответствует порядковому номеру ord (X) +1, т. е.
Ord(Succ(X)) = Ord(X) + 1.
Например, если в программе определена переменная
var
с : Char;
begin
с := '5';
end;
то функция PRED(C) вернет символ '4', а функция SUCC(C) - символ '6'.
Если представить себе любой порядковый тип как упорядоченное множество значений, возрастающих слева направо и занимающих на числовой оси некоторый отрезок, то функция pred(x) не определена для левого, a succ (X) - для правого конца этого отрезка.
Целые типы. Диапазон возможных значений целых типов зависит от их внутреннего представления, которое может занимать один, два, четыре или восемь байтов. В табл. 7.1 приводятся названия целых типов, длина их внутреннего представления в байтах и диапазон возможных значений. Таблица 7.1. Целые типы


Название

Длина,байт

Диапазон значений

Cardinal

4

0. .. 2 147 483 647

Byte

1

0...255

Shortint

1

-128...+127

Smallint

2

-32 768...+32 767

Word

2

0...65 535

Integer

4

-2 147 483 648...+2 147 483 647

Longint

4

-2 147 483 648...+2 147 483 647

Int64

8

-9*10 18 . ..+9*10 18

LongWord

4

0. . .4 294 967 295

 
Примечание
Типы LongWord и Int64 впервые введены в версии 4, а типы Smallint и Cardinal отсутствуют в Delphi 1. Тип integer для этой версии занимает 2 байта и имеет диапазон значений от -32768 до +32767, т. е. совпадает с Smallint.
При использовании процедур и функций с целочисленными параметрами следует руководствоваться “вложенностью” типов, т. е. везде, где может использоваться word, допускается использование Byte (но не наоборот), в Longint “входит” Smallint, который, в свою очередь, включает в себя Shortint.
Перечень процедур и функций, применимых к целочисленным типам, приведен в табл. 7.2. Буквами b, s, w, i, l обозначены выражения соответственно типа Byte, Shortint, Word, Integer И Longint,
х - выражение любого из этих типов; буквы vb, vs, vw, vi, vl, vx обозначают переменные соответствующих типов. В квадратных скобках указывается необязательный параметр.
Таблица 7.2. Стандартные процедуры и функции, применимые к целым типам


Обращение

Тип результата

Действие

abs (x)

x

Возвращает модуль x

chr(b)

Char

Возвращает символ по его коду

dec (vx [, i] )

-

Уменьшает значение vx на i, а при отсутствии i - на 1

inc(vx[,i])

-

Увеличивает значение vx на i, а при отсутствии i -на 1

Hi(w)

Byte

Возвращает старший бант аргумента

Hi(I)

То же

Возвращает третий по счету байт

Lo(i)

Возвращает младший байт аргумента

Lo(w)

То же

odd(l)

Boolean

Возвращает True, если аргумент-нечетное число

Random(w)
 
 

Как у параметра

Возвращает псевдослучайное число, равномерно распределенное в диапазоне 0...(w-l)

sqr(x)

X

Возвращает квадрат аргумента

swap(i)

Integer

Меняет местами байты в слове

swap (w)

Word

Тоже

При действиях с целыми числами тип результата будет соответствовать типу операндов, а если операнды относятся к различным целым типам - общему типу, который включает в себя оба операнда. Например, при действиях с shortint и word общим будет тип integer. В стандартной настройке компилятор Delphi не вырабатывает код, осуществляющий контроль за возможной проверкой выхода значения из допустимого диапазона, что может привести к недоразумениям.
Например, при прогоне следующей программы на экране появится значение 0:
procedure TfmExample.bbRunClick(Sender: TObject) ;
var
k: Word;
begin
k := 65535; // Максимальное значение типа Word
k := k+1; // По правилам математики
k=65536 IbOutput.Caption := IntToStr(k); // На самом деле k=0!
end;
Если активизировать переключатель project | options | Compiler I Range checking и повторить компиляцию с помощью Project | Build All, компилятор вставит в программу код проверки переполнения и при прогоне программы возникнет исключительная ситуация, которую при желании можно соответствующим образом обработать. Замечу, что, если изменить программу следующим образом:
k := 65535; // Максимальное значение типа Word
IbOutput.Caption := IntToStr(k + 1);// Будет выведено 65536
переполнения не произойдет, т. к. 32-разрядный компилятор версий Delphi 32 автоматически преобразует операнды выражения k+i к 4-байтным величинам.
Логические типы. К логическим относятся типы Boolean, ByteBool, Bool, wordBool и LongBool. В стандартном Паскале определен только тип Boolean, остальные логические типы введены в Object Pascal для совместимости с Windows: типы Boolean и ByteBool занимают по одному байту каждый, Bool и WordBool - по 2 байта, LongBool - 4 байта. Значениями логического типа может быть одна из предварительно объявленных констант False (ложь) или True (истина). Для них справедливы правила:
Ord(False) = 0;
Ord(True) <> 0;
Succ(False)= True;
Pred(True) = False.
Поскольку логический тип относится к порядковым типам, его можно использовать в операторе цикла счетного типа, например:
var
l : Boolean;
begin
for l := False to True do ....
Однако необходимо помнить, что в Delphi 32 для Boolean значение
Ord (True) = +1, В ТО Время как для других типов (Bool, WordBool И Т.Д.)
Ord (True) = -1, поэтому такого рода операторы следует использовать с осторожностью!. Например, для версии Delphi 6 исполняемый оператор showMessage (' --- ') в следующем цикле for не будет выполнен ни разу:
var
L: Bool;
k: Integer;
begin
for L := False to True do ShowMessage ('--);
end; __
Если заменить тип параметра цикла l в предыдущем примере на Boolean, цикл будет работать и сообщение дважды появится на экране.[ Для Delphi версии 1 и 2 ord (True) =+1 для любого логического типа. ]
Символьный тип. Значениями символьного типа является множество всех символов ПК. Каждому символу приписывается целое число в диапазоне О...255. Это число служит кодом внутреннего представления символа, его возвращает функция ord.

Для кодировки в Windows используется код ANSI (назван по имени American National Standard Institute - американского института стандартизации, предложившего этот код). Первая половина символов ПК с кодами 0... 127 соответствует таблице 7.3. Вторая половина символов с кодами 128...255 меняется для различных шрифтов. Стандартные Windows-шрифты Arial Cyr, Courier New Cyr и Times New Roman для представления символов кириллицы (без букв “ё” и “Ё”) используют последние 64 кода (от 192 до 256): “А”... “Я” кодируются значениями 192..223, “а”... “я” - 224...255. Символы “Ё” и “ё” имеют соответственно коды 168 и 184.
Таблица 7.3. Кодировка символов в соответствии со стандартом ANSI


Код

Символ

Код.

Символ

Код.

Символ

Код

Символ

0

NUL

32

BL

64

@

96

'

1

ЗОН

33

!

65

А

97

а

2

STX

34

66

В

98

b

3

ЕТХ

35

#

67

С

99

с

4

EOT

36

$

68

D

100

d

5

ENQ

37

%

69

Е

101

е

6

ACK

38

&

70

F

102

f

7

BEL

39

'

71

G

103

д

8'

BS

40

(

72

Н

104

h

9

HT

41

)

73

I

105

i

10

LF

42

*

74

J

106

j

11

VT

43

+

75

К

107

k

12

FF

44

f

76

L

108

1

13

CR

45

-

77

М

109

m

14

SO

46

 
 

78

N

110

n

15

SI

47

/

79

0

111

о

16

DEL

48

0

80

Р

112

P

17

DC1

49

1

81

Q

113

q

18

DC2

50

2

82

R

114

r

19

DC3

51

3

83

S

115

s

20

DC 4

52

4

84

Т

116

t

21

NAK

53

5

85

U

117

u

22

SYN

54

6

86

V

118

v

23

ETB

55

7

87

W

119

W

24

CAN

56

8

88

х

120

x

25

EM

57

9

89

Y

121

У

26

SUB

58

:

90

Z

.122

z

27

ESC

59

;

91

t

123

{

28

FS

60

<

92

\

124

1

29

GS

61

=

93

]

125

}

30

RS

62

>

94

Л

126

~

31

US

63

f

95

 
 

127

r

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

К типу char применимы операции отношения, а также встроенные функции:
Сhr (в) - функция типа char; преобразует выражение в типа Byte в символ и возвращает его своим значением;
UpCase(CH) - функция типа char; возвращает прописную букву, если сн - строчная латинская буква, в противном случае возвращает сам символ сн (для кириллицы возвращает исходный символ).
Перечисляемый тип. Перечисляемый тип задается перечислением тех значений, которые он может получать. Каждое значение именуется некоторым идентификатором и располагается в списке, обрамленном круглыми скобками, например:
type
colors = (red, white, blue);
Применение перечисляемых типов делает программы нагляднее. Если, например, в программе используются данные, связанные с месяцами года, то такой фрагмент программы:
type
ТипМесяц=(янв,фев,мар,апр,май,июн,июл,авг,сен,окт,ноя,дек);
var
месяц : ТипМесяц;
begin
if месяц = авг then
IbOutput.Caption := 'Хорошо бы поехать к морю!';
end.
 
был бы, согласитесь, очень наглядным. Увы! В Object Pascal нельзя использовать кириллицу в идентификаторах, поэтому мы вынуждены писать так:
type
TypeMonth=(jan,feb,mar,may,jun,jul,aug,sep,oct,nov,dec);
var
month: TypeMonth;
begin
if month = aug then
IbOutput.Caption := 'Хорошо бы поехать к морю!';
end.
Соответствие между значениями перечисляемого типа и порядковыми номерами этих значений устанавливается порядком перечисления: первое значение в списке получает порядковый номер О, второе - 1 и т. д. Максимальная мощность перечисляемого типа составляет 65536 значений, поэтому фактически перечисляемый тип задает некоторое подмножество целого типа word и может рассматриваться как компактное объявление сразу группы целочисленных констант со значениями 0, 1 и т. д.
Использование перечисляемых типов повышает надежность программ благодаря возможности контроля тех значений, которые получают соответствующие переменные. Пусть, например, заданы такие перечисляемые типы:
type
colors = (black, red, white);
ordenal= (one, two, three) ;
days = (Monday, Tuesday, Wednesday);
С точки зрения мощности и внутреннего представления все три типа эквивалентны:
Ord(black)=0, ... , Ord(white)=2,
Ord(one)=0, ... , Ord(three)=2,
Ord(Monday)=0, ... , Ord(Wednesday)=2.
Однако если определены переменные
var
col : colors;
num : ordenal;
day : days ;
то допустимы операторы
col := black;
num := Succ(two);
day := Pred(Tuesday);
но недопустимы
col := one;
day := black;
Как уже упоминалось, между значениями перечисляемого типа и множеством целых чисел существует однозначное соответствие, задаваемое функцией Ord(X). В Object Pascal допускается и обратное преобразование: любое выражение типа Word можно преобразовать в значение перечисляемого типа, если только значение целочисленного выражения не превышает мощности этого типа. Такое преобразование достигается применением автоматически объявляемой функции с'именем перечисляемого типа. Например, для рассмотренного выше объявления типов эквивалентны следующие присваивания:
col := black;
col := colors (0) ;
Разумеется, присваивание
col := 0;
будет недопустимым, т. к. перечисляемому типу нельзя присвоить целое значение.
Переменные любого перечисляемого типа можно объявлять без предварительного описания этого типа, например:
var
col: (black, white, green);
Тип-диапазон. Тип-диапазон есть подмножество своего базового типа, в качестве которого может выступать любой порядковый тип, кроме типа-диапазона.
Тип-диапазон задается границами своих значений внутри базового типа:
<мин.знач.>..<макс.знач.>
Здесь <мин. знач. > - минимальное значение типа-диапазона; <макс. знач. > - максимальное его значение.
Например:
type
digit = '0'..'9';
dig2 = 48 .. 57;
Тип-диапазон не обязательно описывать в разделе type, а можно указывать непосредственно при объявлении переменной, например:
var
date : 1. .31;
month: 1..12;
Ichr : 'А'..'Z';
При определении типа-диапазона нужно руководствоваться следующими правилами:

  • два символа “..” рассматриваются как один символ, поэтому жду ними недопустимы пробелы;
  • левая граница диапазона не должна превышать его правую границу.

Тип-диапазон наследует все свойства своего базового типа, но с ограничениями, связанными с его меньшей мощностью. В частности, если определена переменная
type
days = (то,tu,we,th,fr,sa,su);
WeekEnd = sa .. su;
var
w : WeekEnd;
begin
w := sa;
end;
to ord(w) вернет значение 5, в то время как pred(W) приведет к ошибке.
В стандартную библиотеку Object Pascal включены две функции, поддерживающие работу с типами-диапазонами:
High(X) - возвращает максимальное значение типа-диапазона, к которому принадлежит переменная х;
Low (X) - возвращает минимальное значение типа-диапазона.
7.1.2. Вещественные типы
В отличие от порядковых типов, значения которых всегда сопоставляются с рядом целых чисел и, следовательно, представляются в ПК абсолютно точно, значения вещественных типов определяют произвольное число лишь с некоторой конечной точностью, зависящей от внутреннего формата вещественного числа.
Таблица 7.4. Вещественные типы


Длина, байт

Название

Количество значащих цифр

Диапазон значений

8
4
8
10
8
8

Real
Single
Double
Extended
Comp
Currency

15…16
7…8
15…16
19…20
19…20
19…20

5.0*10e-324…1.7*10e308
1.5*10e-45…3.4*10e38
5.0*10e324…1.7*10e308
3.4*10-4951…1.1*10e4932
-2e63…+2e63-1
+/-922 337 203 685477,5807

Примечание
В предыдущих версиях Delphi 1...3 тип Real занимал 6 байт и имел диапазон значений от2, 9*10 -39 до 1,7*10 38 . В версиях 4 и 5 этот тип эквивалентен типу Double. Если требуется (в целях совместимости) использовать 6-байтньш Real, нужно указать директиву компилятора {SREALCOMPATIBILITY ON}.
Как видно из табл. 7.4, вещественное число в Object Pascal занимает от 4 до 10 смежных байт и имеет следующую структуру в памяти ПК:


S

е

M

Здесь s - знаковый разряд числа; е - экспоненциальная часть; содержит двоичный порядок; m - мантисса числа.
Мантисса m имеет длину от 23 (для single) до 63 (для Extended) двоичных разрядов, что и обеспечивает точность 7...8 для single и 19...20 для Extended десятичных цифр. Десятичная точка (запятая) подразумевается перед левым (старшим) разрядом мантиссы, но при действиях с числом ее положение сдвигается влево или вправо в соответствии с двоичным порядком числа, хранящимся в экспоненциальной части, поэтому действия над вещественными числами называют арифметикой с плавающей точкой (запятой).
Отметим, что арифметический сопроцессор всегда обрабатывает числа в формате Extended, а три других вещественных типа в этом случае получаются простым усечением результатов до нужных размеров и применяются в основном для экономии памяти.
Например, если “машинное эпсилон” вычисляется с помощью такой программы:
type
RealType = Real;
var
Epsilon : RealType;
begin
Epsilon := 1;
while l+Eps4.1on/2 > 1 do
Epsilon := Epsilon/2;
IbOutput.Caption := FloatToStr(Epsilon)
end;
то независимо от объявления типа RealType (он может быть single, Real, Double или Extended) на печать будет выдан результат
1.08420217248550Е-0019
что соответствует типу Extended. Происходит это по той причине, что все операнды вещественного выражения 1+Epsilon/2 в операторе while перед вычислением автоматически преобразуются к типу Extended. Чтобы получить правильный результат, программу необходимо изменить следующим образом:
type
RealType = Real;
var
Epsilon, Epsl : RealType;
begin
Epsilon := 1;
repeat
Epsilon := Epsilon/2;
Epsl := 1 + Epsilon
until Epsl = 1;
IbOutput.Caption := FloatToStr(2*Epsilon)
end.
Особое положение в Object Pascal занимают типы comp и Currency, которые трактуются как вещественные числа с дробными частями фиксированной длины: в comp дробная часть имеет длину 0 разрядов, т. е. просто отсутствует, в currency длина дробной части -4 десятичных разряда. Фактически оба типа определяют большое целое число со знаком, сохраняющее 19...20 значащих десятичных цифр (во внутреннем представлении они занимают 8 смежных байт). В то же время в выражениях comp и currency полностью совместимы с любыми другими вещественными типами: над ними определены все вещественные операции, они могут использоваться как аргументы математических функций и т. д. Наиболее подходящей областью применения этих типов являются бухгалтерские расчеты.
Для работы с вещественными данными могут использоваться встроенные математические функции, представленные в табл. 7.5. В этой таблице Real означает любой вещественный тип, integer - любой целый тип.
Таблица 7.5. Стандартные математические функции Object Pascal


Обращение

Тип параметра

Тип результата

Примечание

abs (x)

Real, Integer

Тип аргумента Real 

Модуль аргумента

Pi

-

<<

П =3.141592653...

ArcTan(x)

Арктангенс (значение в радианах)

cos (x)

To же <<

To же <<

Косинус, угол в радианах

exp(x)

<<

<<

Экспонента

frac(x)

<<

<<

Дробная часть числа

int(x)

<<

<<

Целая часть числа

ln(x)

<<

<<

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

Random

<<

Псевдослучайное число, равномерно распределенное в диапазоне 0...[1]

Random.fx)
 

Integer
 

Integer
 

Псевдослучайное целое число, равномерно распределенное в диапазоне 0...(х-1)

Randomize
 

-
 

-

Инициация генератора псевдослучайных чисел

sin (x)

Real

Real

Синус, угол в радианах

sqr(x)

To же

To же

Квадрат аргумента

sqrt(x)

<<

<<

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

Примечание
На заметку Генератор псевдо случайных чисел представляет собой функцию которая берет некоторое целое число, называемое базовым, изменяет, его разряды По определенному алгоритму и выдает новое число результат. Одновременно с этим новое число становится базовым.прД следующем обращении к функций; и т. д. (Так как алгоритм процедуры не меняется: в ходе ее работы, числа называются псевдослучайна ми.) В системном модуле System, который автоматически доступен любой программе, базовое число хранится в переменной с именеД RandSeek и всегда имеет начальное значение.О. :Это означает, последовательном обращении к Random в разных, программах (или при нескольких прогонах одной программы) будет всегда вь1лапа'оД на и, та же прследовательность псевдослучайных чисел. НапримёД при; следующём обрабЬтчике bbRunCl.i.ck окно, нашей .учебной программы будет иметь вид, показанный на
procedure TfinExaniple.bbRunCliak(Sender:TObject);
var
S,3S: String;.
begin
S='';
for k :=1 to 300 do
SS := IntToStr (Random (1000))
while Length(SS)<3 do
if k mod 2С=0 then
begin
S : = '' ;
end
end
end;
(В программе выводятся 300 псевдослучайных чисел, которые группируются в строки по 20 чисел и дополняются ведущими нулями, если число имеет меньше трех цифр.) Если вы захотите повторить программу, вы получите точно такую же последовательность чисел, что н на С помощью процедуры Randomize в переменную RandSeek помещается
численное значение системного времени, что привёдет к генерации, другой последовательности. Обращение к этой процедуре нужно сделать в самом начале обработчика.
Начиная с версии 2 в Delphi включен модуль Match, который существенно расширяет перечисленный в табл. 7.5 набор встроенных математических функций. Особенностью реализации содержащихся в нем почти 70 функций и процедур является их оптимизация для работы с арифметическим сопроцессором класса Pentium, так что все они производят необходимые вычисления за рекордно малое время.
Исходный текст содержится в файле файле Source\Rtl\Sys\Match.pas каталога размещения Delphi. В прил. 3 перечисляются подпрограммы модуля Match.
Тип дата-время
Тип дата-время определяется стандартным идентификатором TDateTime и предназначен для одновременного хранения и даты, и времени. Во внутреннем представлении он занимает 8 байт и подобно currency представляет собой вещественное число с фиксированной дробной частью: в целой части числа хранится дата, в дробной - время. Дата определяется как количество суток, прошедших с 30 декабря 1899 года, а время - как часть суток, прошедших с 0 часов, так что значение 36444,837 соответствует дате 11.10.1999 и времени 20:05. Количество суток может быть и отрицательным, однако значения меньшие -693594 (соответствует дате 00.00.0000 от Рождества Христова) игнорируются функциями преобразования даты к строковому типу.
Над данными типа TDateTime определены те же операции, что и над вещественными числами, а в выражениях этого типа могут участвовать константы и переменные целого и вещественного типов.
Для работы с датой и временем используются подпрограммы, перечисленные в табл. 7.6.
Таблица 7.6. Подпрограммы для работы с датой и временем


Function Date: TDateTime;
 
Function DateToStr(D: TDateTime): String;
Function DateTimeToStr(D: TDateTime): String ;
 
Function FormatDateTime (Format: String ;
 
Value: TDateTime): String;
 
Function Now: TDateTime;
 
Function Time: TDateTime;
 
Function TimeToStrfT: TDateTime): String;

Возвращает текущую дату
 
Преобразует дату в строку символов
Преобразует дату и время в строку символов
 
 
Преобразует дату и время из параметра value в строку символов в соответствии со спецификаторами параметра Format
 
Возвращает текущую дату и время
 
Возвращает текущее время
 
Преобразует время в строку

 
Более полный перечень функций преобразования даты и времени в строку символов и обратно указан в п. 7.3.1.
Поскольку тип TDateTime совместим с форматом вещественных чисел, можно без труда определить дату, отстоящую от заданной на сколько-то дней вперед или назад: для этого достаточно соответственно прибавить к заданной дате или отнять от нее нужное целое число. Например, оператор
IbOutput.Caption := DateToStr(Date + 21);
поместит в метку IbOutput дату, соответствующую текущей дате плюс 3 недели. Чуть сложнее с исчислением времени. Например, чтобы добавить к текущему времени полтора часа, следует использовать выражение
Time + StrToTime('1:30')
ИЛИ
Time+1.5/24
С помощью показанного ниже обработчика bbRunciick учебной программы вы сможете ввести в строке ввода любое вещественное число и посмотреть его интерпретацию как значение типа
TDateTime:
procedure TfmExample.bbRunClick(Sender: TObject) ;
{Показывает вещественное число, введенное в строке edinput,в формате даты-времени}
var
k: Double;
begin
//Преобразуем строковый ввод в вещественное число
try
k := StrToFloat(edinput.Text);
except
ShowMessage('Ошибка записи вещественного числа');
edinput.SelectAll ;
Exit
end;
//Показываем результат как дату-время
IbOutput. Caption := ForrnatDateTime
('dd.mm.yyyy hh:mm:ss', k);
// Возвращаемфокусвводав edinput edinput.SetFocus ;
end;
СТРУКТУРИРОВАННЫЕ ТИПЫ
Любой из структурированных типов (а в Object Pascal их четыре: массивы, записи, множества и файлы) характеризуется множественностью образующих этот тип элементов. Каждый элемент, в свою очередь, может принадлежать структурированному типу, что позволяет говорить о возможной вложенности типов. В Object Pascal допускается произвольная глубина вложенности типов, однако суммарная длина любого из них во внутреннем представлении не должна превышать 2 Гбайт [ 16-разрядные версии операционной системы Windows З.х используют так называемую “ сегментную” модель памяти, поэтому в Delphi 1 любой структурированный тип не может занимать более одного сегмента (65536 байт). ].
В целях совместимости со стандартным Паскалем в Object Pascal разрешается перед описанием структурированного типа ставить зарезервированное слово packed, предписывающее компилятору по возможности экономить память, отводимую под объекты структурированного типа; но компилятор фактически игнорирует это указание: “упаковка” данных в Object Pascal осуществляется автоматачески везде, где это возможно.
Массивы
Массивы в Object Pascal во многом схожи с аналогичными типами данных в других языках программирования. Отличительная особенность массивов заключается в том, что все их компоненты суть данные одного типа (возможно, структурированного). Эти компоненты можно легко упорядочить и обеспечить доступ к любому из них простым указанием его порядкового номера, например:
type
digit = array [0..9] of Char;
matrix = array [byte] of Single;
var
m : matrix;
d : digit;
i : integer;
begin
m[17] := ord(d[i-l])/10;
end.
Описание типа массива задается следующим образом:
<имя типа> = array [ <сп.инд.типов> ] of <тип>;
Здесь <имя типа> - правильный идентификатор; array, of - зарезервированные слова {массив, из); <сп.инд.типов> - список из одного или нескольких индексных типов, разделенных запятыми; квадратные скобки, обрамляющие список, - требование синтаксиса;
<тип> - любой тип Object Pascal.
В качестве индексных типов в Object Pascal можно использовать любые порядковые типы, имеющие мощность не более 2 Гбайт (т. е. Кроме LongWord И Int64)
Определить переменную как массив можно и непосредственно при описании этой переменной, без предварительного описания типа массива, например:
var
a,b : array [1..10] of Real;
Обычно в качестве индексного типа используется тип-диапазон, в котором задаются границы изменения индексов. Так как тип <тип>, идущий в описании массива за словом of, - любой тип Object Pascal, то он может быть, в частности, и другим массивом, например:
type
mat = array [0..5] of array [-2..2] of array [Char] of Byte;
Такую запись можно заменить более компактной:
type
mat = array [0..5,-2..2,char] of Byte;
Глубина вложенности структурированных типов вообще, а следовательно, и массивов - произвольная, поэтому количество элементов в списке индексных типов (размерность массива) не ограничено, однако суммарная длина внутреннего представления любого массива не может быть больше 2 Гбайт. В памяти ПК элементы массива следуют друг за другом так, что при переходе от младших адресов к старшим наиболее быстро меняется самый правый индекс массива.
Если, например,
var
a: array [1..2,1..2] of Byte;
begin
а[1,1] := 1;
а[2,1] := 2 ;
а[1,2] := 3;
а[2,2] := 4;
end.
то в памяти последовательно друг за другом будут расположены байты со значениями 1,3,2,4 . Это обстоятельство может оказаться важным при использовании стандартной процедуры копирования памяти MoveMemory.
В Object Pascal можно одним оператором присваивания передать все элементы одного массива другому массиву того же типа, например:
var
a,b : array [1..5] of Single;
begin
а := b;
end.
После этого присваивания все пять элементов массива а получат те же значения, что и в массиве в. Замечу, что объявление
var
a: array [1..5] of Single;
b: array [1..5] of Single;
создаст разные типы массивов, поэтому оператор
а := b;
вызовет сообщение об ошибке.
Над массивами не определены операции отношения. Нельзя, например, записать
if а = b then ...
Сравнить два массива можно поэлементно, например:
var
a,b : array [1..5] of Single;
eq : Boolean;
i : Byte;
begin
eq := True; for i := 1 to 5 do
if a[i] <> b[i] then
eq := False/if eq then
end.
Динамические массивы
В версии Delphi 4 впервые введены так называемые динамические массивы. При объявлении таких массивов в программе не следует указывать границы индексов:
var
A: array of Integer;
В: array of array of Char;
C: array of array of array of Real;
В этом примере динамический массив а имеет одно измерение, массив в - два и массив с - три измерения. Распределение памяти и указание границ индексов по каждому измерению динамических массивов осуществляется в ходе выполнения программы путем инициации массива с помощью функции setLength. В ходе выполнения такого оператора:
SetLength(А,3);
одномерный динамический массив а будет инициирован, т. е. получит память, достаточную для размещения трех целочисленных значений. Нижняя граница индексов по любому измерению динамического массива всегда равна 0, поэтому верхней границей индексов для а станет 2.
Фактически идентификатор динамического массива ссылается на указатель (см. гл. 9), содержащий адрес первого байта памяти, выделенной для размещения массива. Поэтому для освобождения этой памяти достаточно присвоить идентификатору значение nil (другим способом является использование процедуры Finalize):
var
А,В: array of Integer;
begin
// Распределяемпамять:
SetLength(A,10) ;
SetLength(B,20) ;
// Используем массивы:
// Освобождаем память:
А := NIL;
Finalize(В);
end;
При изменении длины уже инициированного динамического массива по какому-либо его измерению сначала резервируется нужная для размещения нового массива память, затем элементы старого массива переносятся в новый, после чего освобождается память, выделенная прежнему массиву. Чтобы сократить дополнительные затраты времени, связанные с изменением границ большого динамического массива, следует сразу создать массив максимальной длины.
В многомерных массивах сначала устанавливается длина его первого измерения, затем второго, третьего и т. д. Например:
var
A: array of array of Integer; //Двумерныйдинамическиймассивbegin
//Устанавливаем длину первого измерения (количество столбцов):
SetLength(A,3) ;
//Задаем длину каждого столбца:
SetLength(A[0],3) ;
SetLength(A[l],3) ;
SetLength(A[2] ,3) ;
end;
Обратите внимание: в отличие от обычных массивов стандартного Паскаля (и Object Pascal), динамические массивы могут иметь разную длину по второму и следующим измерениям. В предыдущем примере определен квадратный массив 3х3. Однако ничто не мешает нам создать, например, треугольный массив:
SetLength(A,3) ;
//Задаем длину каждого столбца:
SetLength(A[0],3) ;
SetLength(A[l],4) ;
SetLength(A[2],5) ;
В многомерных динамических массивах каждый элемент любого из N-1 измерений (N - количество измерений) представляет собой динамический массив и, следовательно, нуждается в инициации. Вот как, например, можно инициировать вещественный кубический массив 3х3х3:
var
A: array of array of array of Real;
i, j: Integer;
begin
SetLength(A,3) ;
for i := 0 to 2 do
begin
SetLength(A[i],3) ;
for j := 0 to 2 do SetLength{A[i,j],3) ;
end;
end;

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г. Яндекс.Метрика