Переменные с непостоянным типом значений

Тип данных Variant

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

Переменная с типом Variant занимает в памяти 16 байт. В них хранятся текущее значение переменной (или адрес значения в динамической памяти) и тип этого значения.

Структура вариантного типа представляет собой упакованную запись с вариантной частью. Типы TVarData и TVarType (тождественный типу Word), константы (указывающие тип помещенных в вариант данных) описаны в модуле System. Функциональная часть описана в модуле Variants, который необходимо подключать, если мы хотим работать с вариантным типом.

Значения переменных с типом Variant

1. В переменную-вариант можно поместить:

· целое или вещественное число;

· булевское значение;

· строковое значение;

· время и/или дату;

· OLE-объект;

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

Кроме того, переменные с типом Variant принимают два специальных значения: Unassigned и Null.

Значение Unassigned показывает, что переменной еще не присвоено значение. Оно автоматически устанавливается в качестве начального значения любой переменной с типом Variant.

Значение Null показывает, что переменная имеет неопределенное значение.

В Delphi определены такие константы, указывающие тип помещенных в вариант данных. Таблица…

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

Variant в выражениях

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

var V1, V2, V3, V4: Variant; begin V1 := 5; // целое число V2 := 0.8; // вещественное число V3 := '10'; // строка V4 := V1 + V2 + V3; // вещественное число 15.8end;

Если же V3:=’текст’, то выражение V1 + V2 + V3 вызовет исключение EVariantError.

2. Если в выражении участвует переменная со значением Null, то результат будет Null.

Преобразование вариантов к другим типам данных

Все целочисленные, вещественные, булевские, строковые и символьные типы совместимы по присваиванию с Variant. Для них в выражениях осуществляется автоматическая конвертация по следующим правилам:

  integer real string boolean
integer converts integer formats converts to real converts to string representation returns False if 0, True otherwise
real rounds to nearest integer converts real formats converts to string representation using regional settings returns False if 0, True otherwise
string converts to integer, truncating if necessary; raises exception if string is not numeric converts to real using regional settings; raises exception if string is not numeric converts string/character formats returns False if string is "false" (non-case-sensitive) or a numeric string that evaluates to 0, True if string is "true" or a nonzero numeric string; raises exception otherwise
character same as string (above) same as string (above) same as string (above) same as string (above)
Boolean False = 0, True = -1 (255 if Byte) False = 0, True = -1 False = "0", True = "-1" False = False, True = True
Unassigned returns 0 returns 0 returns empty string returns False
Null raises exception raises exception raises exception raises exception
         

Подпрограммы для работы с вариантами

1. Тип значения выясняется с помощью функции

VarType(const V: Variant): Integer;

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

  if VarType(V) and varTypeMask = varString then ...  
Код типа Значение Описание
varEmpty $0000 Переменная содержит значение Unassigned.
varNull $0001 Переменная содержит значение Null.
varSmallint $0002 Переменная содержит значение типа Smallint.
varInteger $0003 Переменная содержит значение типа Integer.
varSingle $0004 Переменная содержит значение типа Single.
varDouble $0005 Переменная содержит значение типа Double.
varCurrency $0006 Переменная содержит значение типа Currency.
varDate $0007 Переменная содержит значение типа TDateTime.
varOleStr $0008 Переменная содержит ссылку на строку формата Unicode в динамической памяти.
varDispatch $0009 Переменная содержит ссылку на интерфейс IDispatch (интерфейсы позже).
varError $000A Переменная содержит системный код ошибки.
varBoolean $000B Переменная содержит значение типа WordBool.
varVariant $000C Элемент варьируемого массива содержит значение типа Variant (код varVariant используется только в сочетании с флагом varArray).
varUnknown $000D Переменная содержит ссылку на интерфейс IUnknown (интерфейсы рассмотрены в главе 6).
varShortint $0010 Переменная содержит значение типа Shortint
varByte $0011 Переменная содержит значение типа Byte.
varWord $0012 Переменная содержит значение типа Word
varLongword $0013 Переменная содрежит значение типа Longword
varInt64 $0014 Переменная содержит значение типа Int64
varStrArg $0048 Переменная содержит строку, совместимую со стандартом COM, принятым в операционной системе Windows.
varString $0100 Переменная содержит ссылку на длинную строку.
varAny $0101 Переменная содержит значение любого типа данных технологии CORBA
Флаги    
varTypeMask $0FFF Маска для выяснения типа значения.
varArray $2000 Переменная содержит массив значений.
varByRef $4000 Переменная содержит ссылку на значение.
         

2. Функция

VarAsType(const V: Variant; VarType: Integer): Variant;

позволяет вам преобразовать значение варьируемой переменной к нужному типу, например:

V1 := '100';V2 := VarAsType(V1, varInteger);

3. Остальные функции:

function VarAsType(const V: Variant; VarType: Integer): Variant; Преобразует данные варианта V к типу, определяемому параметром VarType
procedure VarCast(var Dest: Variant; const Source: Variant; Var Type: Integer) ; Преобразует данные варианта Source к типу,определяемому параметром VarType, и помещает результат в переменную Dest
procedure VarClear(var V: Variant) ;   Освобождает динамическую память, если она была связана с вариантом, и дает ему тип varEmpty
procedure VarCopy(var Dest: Variant; const Source: Variants; Копирует параметр Source в вариант Dest
function VarFrom-DateTime(DateTime: TDateTime):Variant; Возвращает вариант, содержащий данные DateTime типа дата-время
function VarIsEmpty(const V: Variant): Boolean; Возвращает True, если вариант V не содержит данных
function VarIsNull(const V: Vari ant) : Boolean; Возвращает True, если вариант V содержит данные неопределенного типа (varNull) ',
function VarToDateTime(const V: Variant): TDateTime) ; Преобразует данные варианта V к типу дата-время
function VarToStr(const V: Vari ant) : String; Преобразует данные варианта V к строке ;
function VarType(const V: Variant) : Integer;  

Вариантные массивы

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

Значениями элементов вариантного массива могут быть любые допустимые для варианта значения, кроме строк varstring. Значениями элементов вариантного массива могут быть и варианты, а это значит, что в таком массиве могут одновременно храниться данные разных типов (и в том числе строки). Например:

 

var V: Variant; begin // Создаем одномерный вариантный массив с 5 элементами: V := VarArrayCreate([0, 4], varVariant); // Наполняем его: V[0] := 1; //Тип целый V[1] := 1234.5678; //Тип вещественный V[2] := 'Hello world'; //Строковый тип V[3] := True; //Логический тип //Пятым элементом исходного массива сделаем еще один массив: V[4] := VarArrayOf([1, 10, 100, 1000]); Caption := V[2]; //Hello world IbOutput.Caption := IntToStr(V[4][2]); //100 end;

 

Действия с вариантными массивами можно осуществлять с помощью процедур и функций. Приведем некоторые:

function VarArrayCreate(const Bounds: array of Integer; VarType: Integer): Variant; Создает вариантный массив из элементов типа VarType с количеством и границами измерений, указываемых параметром Bounds
function VarArrayDimCount(const A: Variant): Integers; Возвращает количество измерений вариантного массива А или 0, если А не массив
function VarArrayHighBound(const A: Variant; Dim: Integer): Integer; Возвращает верхнюю границу индекса вариантного массива А по измерению Dim
function VarArrayLowBound(const A: Variant; Dim: Integer): Integers; Возвращает нижнюю границу индекса вариантного массива А по измерению Dim
function VarArrayOf(const Values: array of Variant): Variants;     Создает одномерный вариантный массив по перечню значений, содержащихся в открытом массиве Values. Нижняя граница индексов вариантного массива в этом случае равна 0

 

 

Указатели

Понятие указателя

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

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

Var P1: Pointer; // переменная-указатель нетипизированный N: Integer; // целочисленная переменная P: ^Integer; // переменная - указатель типизированный

Переменная P занимает 4 байта и может содержать адрес любого участка памяти, указывая на байты со значениями любых типов данных: Integer, Real, string, record, array и других. Если указатель указывает на переменную структрированного типа (массив, запись…), то этот указатель содержит адрес первого элемента этой структуры.

Чтобы инициализировать переменную P, присвоим ей адрес переменной N. Это можно сделать двумя эквивалентными способами (для P и P1):

P := Addr(N); // с помощью вызова встроенной функции Addr

или

P1 := @N; // с помощью оператора @

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

2. Если некоторая переменная P содержит адрес другой переменной N, то говорят, что P указывает на N. Графически это обозначается стрелкой, проведенной из P в N (рисунок выполнен в предположении, что N имеет значение 10):


Рисунок. Графическое изображение указателя P на переменную N

3. Теперь мы можем изменить значение переменной N, не прибегая к идентификатору N. Для этого слева от оператора присваивания запишем не N, а P вместе с символом ^:

P^ := 10; // Здесь не нужно приведение типаInteger(P1^) := 10; // Выполонено приведение типа

Символ ^, записанный после имени указателя, называется оператором доступа по адресу. В данном примере переменной, расположенной по адресу, хранящемуся в P, присваивается значение 10. Так как в переменную P мы предварительно занесли адрес N, данное присваивание приводит к такому же результату, что и

N := 10;

4. Отдельно обратим внимание на символ ^.

^typeName; // Для описания типизированного указателяpointer^; // Оператор доступа по адресу

5. При записи P: ^Integer переменная P по-прежнему является указателем, но теперь ей можно присваивать адреса только целых переменных. В данном случае указатель P называют типизированным, в отличие от переменных типа Pointer, которые называют нетипизированнымиуказателями. При использовании типизированных указателей лучше предварительно вводить соответствующий указательный тип данных, а переменные-указатели просто объявлять с этим типом.

type pointerTypeName = ^type;

Чтобы отличать указательные типы данных от других типов, будем назначать им идентификаторы, начинающиеся с буквы P (от слова Pointer). Объявление указательного типа данных является единственным способом введения указателей на составные переменные, такие как массивы, записи, множества и другие. Например, объявление типа данных для создания указателя на некоторую запись TPerson может выглядеть так:

Type PPerson = ^TPerson; TPerson = record FirstName: string[20]; LastName: string[20]; BirthYear: Integer; end; var P: PPerson;

Переменная P, описанная с типом данных PPerson, является указателем и может содержать адрес любой переменной типа TPerson. Впредь все указатели мы будем вводить через соответствующие указательные типы данных. Типом Pointer будем пользоваться лишь тогда, когда это действительно необходимо или оправдано.








Дата добавления: 2016-02-09; просмотров: 1402;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.013 сек.