Record — Ключевое слово Delphi


Record — Ключевое слово Delphi

При создании любой серьёзной программы не обойтись без дополнительных, более сложных, чем числа и строки, типов данных. В Delphi программист может для своих целей конструировать собственные типы данных. Чтобы ввести в программу (описать) новый тип данных, применяется оператор с ключевым словом type:
type название_типа = описание_типа;

Перечислимый тип — это тип данных, диапазоном значений которого является просто набор идентификаторов. Это может применяться в тех случаях, когда нужно описать тип данных, значения которого нагляднее представить не числами, а словами. Перечислимый тип записывается взятой в круглые скобки последовательностью идентификаторов — значений этого типа, перечисляемых через запятую. При этом, первые элементы типа считаются младшими по сравнению с идущими следом. Например, тип, описывающий названия футбольных команд, можно сформировать так:

type FootballTeam = (Spartak, Dinamo, CSKA, Torpedo, Lokomotiv);
var MyTeam: FootballTeam;
begin
MyTeam:=Spartak;
end;

Вообще, под перечислимыми типами понимают все типы, для которых можно определить последовательность значений и их старшинство. К ним относятся:

  • все целочисленные типы, для которых всегда можно указать число, следующее за числом N;
  • символьные типы (Char): за символом ‘a’ всегда следует ‘b’, за ‘0’ следует ‘1’, и так далее;
  • логические типы — тип Boolean также представляет собой перечислимый тип: type Boolean = (false, true);

Структурные типы данных используются практически в любой программе. Это такие типы, как

  • массивы
  • записи
  • множества

Массив — это структура данных, доступ к элементам которой осуществляется по номеру (или индексу). Все элементы массива имеют одинаковый тип.
Описание массива имеет вид:

type имя_типа_массива = array [диапазон] of тип_элемента;

Диапазон определяет нижнюю и верхнюю границы массива и, следовательно, количество элементов в нём. При обращении к массиву индекс должен лежать в пределах этого диапазона. Массив из ста элементов целого типа описывается так:

type TMyArray = array [1 .. 100] of Integer;

Теперь можно описать переменные типа TMyArray:

var A, B: TMyArray;

Вместо присвоения типа можно явно описать переменные как массивы:

var A, B : array [1..100] of Integer;

Для доступа к элементу массива нужно указать имя массива и индекс элемента в квадратных скобках. В качестве индекса может выступать число, идентификатор или выражение, значение которых должно укладываться в диапазон, заданный при описании массива:

Иногда требуется узнать верхнюю или нижнюю границу массива. Для этого служат встроенные функции:

High() — вернёт число, являющееся верхней границей массива;
Low() — вернёт число, являющееся нижней границей массива.

В скобки нужно подставить массив, границы которого требуется узнать.

Выражение B := A означает, что каждый элемент массива B будет равен элементу с таким же индексом массива A. Такое присвоение возможно только если оба массива объявлены через некий поименованный тип, или перечислены в одном списке. И в случае:

его использовать невозможно (но возможно поэлементное присвоение B[1] := A[2]; и т.д.).

Массивы могут иметь несколько измерений, перечисляемых через запятую. Например, таблицу из четырёх столбцов и трёх строк:

1 2 3 4
5 6 7 8
9 10 11 12

можно описать в виде массива с двумя измерениями:

type MyTable = array[1..4, 1..3] of Integer;
var X : MyTable;
Y : Integer;
begin
Y:=X[3, 2];
end;

Теперь в результате операции присвоения Y будет равен 7.
Многомерный, например, двумерный массив можно описать как массив массивов:

type TMyArray = array [1 .. 4] of array [1 .. 3] of Integer;

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

type TDinArray = array of Integer;
var A : TDinArray;

После создания в динамическом массиве нет ни одного элемента. Необходимый размер задаётся в программе специальной процедурой SetLength. Массив из ста элементов:

Нижняя граница динамического массива всегда равна нулю. Поэтому индекс массива A может изменяться от до 99.
Многомерные динамические массивы описываются именно как массивы массивов. Например, двумерный:

type T3DinArray = array of array of Integer;
var A : T3DinArray;

В программе сначала задаётся размер по первому измерению (количество столбцов):

SetLength(A, 3);

Затем задаётся размер второго измерения для каждого из трёх столбцов, например:

SetLength(A[0], 3);
SetLength(A[1], 2);
SetLength(A[2], 1);


В этом примере мы делаем следующее:

  1. Открываем файл существующий AssignFile/Reset
  2. Определяем количество записей в файле (Count:=FileSize(TypedFile))
  3. Если количество записей меньше двух, то спрашиваем у пользователя стереть ли все записи и, в случае положительного ответа, вызываем метод Tuncate
  4. Если количество записей в файле больше двух, то смещаемся на нужную нам позицию в файле (Seek(TypedFile, Count-2)) и затираем две последние записи методом Truncate.

Подведем итог

Для работы с типизированными файлами в Delphi в самом общем случае нам необходимо выполнить следующую последовательность операций:

  1. Определить тип записей в файле — это могут быть стандартные типы данных Delphi с фиксированным размером: ShortString, integer, single и так далее или собственные типы данных, например, записи (record), но, в этом случае, главное условие — размер записи должен быть фиксированным.
  2. В коде Delphi/Pascal определить файловую переменную, используя ключевое слово fileи, указав тип записей файла, определенный в пункте 1.
  3. Ассоциировать файловую переменную с внешним файлом на диске, используя метод AssignFile.
  4. Открыть файл для чтения/записи, используя методы Rewrite/Reset.
  5. Чтобы сделать в файл очередную запись используем метод Write, для чтения очередной записи из файла — используем метод Read.
  6. Закрыть файл методом CloseFile.

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

Функции и процедуры для работы с типизированными файлами в Delphi/Pascal

Record — Ключевое слово Delphi

Ясно почему размер структуры равен 6 байт(1+1+4=6)

А почему тогда вот тут размер структуры НЕ 6 байт?

Вроде бы тоже (1+1+4=6).

Объясните кто то доступно. как можно понятнее. пожалуйста.

10.11.2009, 22:44 #6
А почему тогда вот тут размер структуры НЕ 6 байт?

граница структуры выравнивается до 8

то есть два байта зря.
вот насчет времени доступа к упакованным данным я точно не знаю.
но оно поидее больше. так как процессору не удобно юзать такие данные(предпологгаю я)

Пепел Феникса
Посмотреть профиль
Найти ещё сообщения от Пепел Феникса
11.11.2009, 02:24 #7

If you want to get to the top, you have to start at the bottom

st_tsourkan

ЖЗЛ: из жизни искателя приключений

Заметки фотопутешественника

Данный пост написан в интересах рабочего процесса.

Ай нид хэлп! По работе нужно сделать программку, которая переводит xml-файлы (в частности, xml-тэги) в массив структур (переменная типа record в Delphi)).

Дано: строка вида

Надо: преобразовать в запись с полями вида имя_поля.значение_поля. То есть, чтобы получилась переменная MyRec (имя задано произвольно) типа record:
MyRec.name=’scene013′;
MyRec.thumb=’gallery/013.jpg’;
MyRec.thumb_weight=[];
MyRec.radar=’radar4′;
MyRec.heading=160;

Одним словом, мне надо в рантайме (т. е. когда программа уже выполняется) задавать названия полей (thumb, radar, name и т. д.) и присваивать им значения. Сложность в том, что количество полей записи MyRec по условию задачи неизвестно; возможные названия полей тоже неопределены (они должны определяться сами в ходе чтения xml-файла.
Я могу создать массив строк, у которого в первом столбце — имена полей, во втором — их значения:
‘name’ ‘scene013’
‘thumb’ ‘gallery/013.jpg’
‘thumb_weight’ »
‘heading’ ‘160’
Но потом их всё равно как-то надо преобразовать к типу record, чтобы можно было обращаться к полям в виде Массив.Имя_поля=Значение_поля. Например, запросить значение параметра heading: MyRec.heading

На Матлабе это делается элементарно (там динамическая типизация):

MyRec.(field_name)=field_value;
field_name — имя поля, которое мы храним в строковой переменной, field_value — соответственно, значение данного поля. В Матлабе это всё делается рантайм; не надо ничего заранее описывать (количество полей, тип данных поля, имя поля). А вот как это сделать в Дельфи? Я уже рассматривал вариантные поля в переменных типа record, но тоже не вариант, потому что названия полей и их количество надо задавать в области объявления переменных, а также потому, что названия полей нельзя читать из переменных (как в Матлабе).

Structured Types (Delphi)

Instances of a structured type hold more than one value. Structured types include sets, arrays, records, and files as well as class, class-reference, and interface types. Except for sets, which hold ordinal values only, structured types can contain other structured types; a type can have unlimited levels of structuring.

This topic covers the following structured types:

  • Sets
  • Arrays, including static and dynamic arrays
  • Records
  • File types

Contents

Alignment of Structured Types

By default, the values in a structured type are aligned on word- or double-word boundaries for faster access.

You can, however, specify byte alignment by including the reserved word packed when you declare a structured type. The packed word specifies compressed data storage. Here is an example declaration:

Using packed is not a recommended practice, because it can prevent compatibility with other languages or platforms, it slows data access, and, in the case of a character array, it affects type compatibility. For more information, see Memory management and Implicit Packing of Fields with a Common Type Specification.

A set is a collection of values of the same ordinal type. The values have no inherent order, nor is it meaningful for a value to be included twice in a set.

The range of a set type is the power set of a specific ordinal type, called the base type; that is, the possible values of the set type are all the subsets of the base type, including the empty set. The base type can have no more than 256 possible values, and their ordinalities must fall between 0 and 255. Any construction of the form:

where baseType is an appropriate ordinal type, identifies a set type.

Because of the size limitations for base types, set types are usually defined with subranges. For example, the declarations:

create a set type called TIntSet whose values are collections of integers in the range from 1 to 250. You could accomplish the same thing with:

Given this declaration, you can create a set like this:

You can also use the set of . construction directly in variable declarations:

Other examples of set types include:

The in operator tests set membership:

Every set type can hold the empty set, denoted by []. For more information about sets, see «Set Constructors» and «Set Operators» in Expressions (Delphi).

Arrays

An array represents an indexed collection of elements of the same type (called the base type). Because each element has a unique index, arrays, unlike sets, can meaningfully contain the same value more than once. Arrays can be allocated statically or dynamically.

Static Arrays

Static array types are denoted by constructions of the form:

where each indexType is an ordinal type whose range does not exceed 2GB. Since the indexTypes index the array, the number of elements an array can hold is limited by the product of the sizes of the indexTypes. In practice, indexTypes are usually integer subranges.

In the simplest case of a one-dimensional array, there is only a single indexType. For example:

declares a variable called MyArray that holds an array of 100 character values. Given this declaration, MyArray[3] denotes the third character in MyArray . If you create a static array but don’t assign values to all its elements, the unused elements are still allocated and contain random data; they are like uninitialized variables.

A multidimensional array is an array of arrays. For example:

is equivalent to:

Whichever way TMatrix is declared, it represents an array of 500 real values. A variable MyMatrix of type TMatrix can be indexed like this: MyMatrix[2,45]; or like this: MyMatrix[2][45] . Similarly:

is equivalent to:

The standard functions Low and High operate on array type >Length returns the number of elements in the array’s first dimension.

A one-dimensional, packed, static array of Char values is called a packed string. Packed-string types are compatible with string types and with other packed-string types that have the same number of elements. See Type Compatibility and Identity (Delphi).

An array type of the form array[0..x] of Char is called a zero-based character array. Zero-based character arrays are used to store null-terminated strings and are compatible with PChar values. See «Working with null-terminated strings» in String Types (Delphi).

Dynamic Arrays

Dynamic arrays do not have a fixed size or length. Instead, memory for a dynamic array is reallocated when you assign a value to the array or pass it to the SetLength procedure. Dynamic-array types are denoted by constructions of the form:

array of baseType

declares a one-dimensional dynamic array of reals. The declaration does not allocate memory for MyFlexibleArray . To create the array in memory, call SetLength . For example, given the previous declaration:

allocates an array of 20 reals, indexed 0 to 19. An alternative method of allocating memory for dynamic arrays is to invoke the array constructor:

which allocates memory for three elements and assigns each element the given value.

Similar to the array constructor, a dynamic array may also be initialized from an array constant expression as below.

Notice that unlike with an array constructor, an array constant can be applied to unnamed dynamic array type directly. This syntax is specific to dynamic arrays; applying this technique to other array types is likely to result in the constant being interpreted as a set, leading to an incompatible types error at compile-time.

Dynamic arrays are always integer-indexed, always starting from 0.

Dynamic-array variables are implicitly pointers and are managed by the same reference-counting technique used for long strings. To deallocate a dynamic array, assign nil to a variable that references the array or pass the variable to Finalize ; either of these methods disposes of the array, prov >New or Dispose procedure.

If X and Y are variables of the same dynamic-array type, X := Y points X to the same array as Y . (There is no need to allocate memory for X before performing this operation.) Unlike strings and static arrays, copy-on-write is not employed for dynamic arrays, so they are not automatically copied before they are written to. For example, after this code executes:

the value of A[0] is 2. (If A and B were static arrays, A[0] would still be 1.)

Assigning to a dynamic-array index (for example, MyFlexibleArray[2] := 7 ) does not reallocate the array. Out-of-range indexes are not reported at compile time.

In contrast, to make an independent copy of a dynamic array, you must use the global Copy function:

When dynamic-array variables are compared, their references are compared, not their array values. Thus, after execution of the code:

A = B returns False but A[0] = B[0] returns True.

To truncate a dynamic array, pass it to SetLength , or pass it to Copy and assign the result back to the array variable. (The SetLength procedure is usually faster.) For example, if A is a dynamic array, either of the following truncates all but the first 20 elements of A :

Once a dynamic array has been allocated, you can pass it to the standard functions Length , High , and Low . Length returns the number of elements in the array, High returns the array’s highest index (that is, Length — 1 ), and Low returns 0. In the case of a zero-length array, High returns -1 (with the anomalous consequence that High ).

Note: In some function and procedure declarations, array parameters are represented as array of baseType, without any index types specified. For example, function CheckStrings(A: array of string): Boolean;

This indicates that the function operates on all arrays of the specified base type, regardless of their size, how they are indexed, or whether they are allocated statically or dynamically.

Multidimensional Dynamic Arrays

To declare mult >array of . constructions. For example:

declares a two-dimensional array of strings. To instantiate this array, call SetLength with two integer arguments. For example, if I and J are integer-valued variables:

allocates an I-by-J array, and Msgs[0,0] denotes an element of that array.

You can create mult >SetLength , passing it parameters for the first n dimensions of the array. For example:

allocates ten rows for Ints but no columns. Later, you can allocate the columns one at a time (giving them different lengths); for example:

makes the third column of Ints five integers long. At this point (even if the other columns haven’t been allocated) you can assign values to the third column — for example, Ints[2,4] := 6 .

The following example uses dynamic arrays (and the IntToStr function declared in the SysUtils unit) to create a triangular matrix of strings.

Array Types and Assignments

Arrays are assignment-compatible only if they are of the same type. Because the Delphi language uses name-equivalence for types, the following code will not compile.

To make the assignment work, declare the variables as:

String-Like Operations Supported on Dynamic Arrays

Dynamic arrays can be manipulated similarly to strings. For example:

String-like Support Routines

Some of the Delphi Intrinsic Routines support operations on dynamic arrays in addition to operations on strings.

System.Insert The Insert function inserts a dynamic array at the beginning at the position index. It returns the modified array:

The Delete function eliminates elements from a dynamic array and returns the modified array:

System.Concat The Concat function can be used to put together two different dynamic arrays:

Records (traditional)

A record (analogous to a structure in some languages) represents a heterogeneous set of elements. Each element is called a field; the declaration of a record type specifies a name and type for each field. The syntax of a record type declaration is:

where recordTypeName is a valid identifier, each type denotes a type, and each fieldList is a valid identifier or a comma-delimited list of identifiers. The final semicolon is optional.

For example, the following declaration creates a record type called TDateRec .

Each TDateRec contains three fields: an integer value called Year , a value of an enumerated type called Month , and another integer between 1 and 31 called Day . The >Year , Month , and Day are the field designators for TDateRec , and they behave like variables. The TDateRec type declaration, however, does not allocate any memory for the Year , Month , and Day fields; memory is allocated when you instantiate the record, like this:

This variable declaration creates two instances of TDateRec , called Record1 and Record2 .

You can access the fields of a record by qualifying the field designators with the record’s name:

Or use a with statement:

You can now copy the values of Record1 ‘s fields to Record2 :


Because the scope of a field designator is limited to the record in which it occurs, you don’t have to worry about naming conflicts between field designators and other variables.

Instead of defining record types, you can use the record . construction directly in variable declarations:

However, a declaration like this largely defeats the purpose of records, which is to avoid repetitive coding of similar groups of variables. Moreover, separately declared records of this kind will not be assignment-compatible, even if their structures are identical.

Variant Parts in Records

A record type can have a variant part, which looks like a case statement. The variant part must follow the other fields in the record declaration.

To declare a record type with a variant part, use the following syntax:

The first part of the declaration — up to the reserved word case — is the same as that of a standard record type. The remainder of the declaration — from case to the optional final semicolon — is called the variant part. In the variant part,

    tag is optional and can be any val >

where each fieldList is a valid identifier or comma-delimited list of identifiers, each type denotes a type, and the final semicolon is optional. The types must not be long strings, dynamic arrays, variants (that is, Variant types), or interfaces, nor can they be structured types that contain long strings, dynamic arrays, variants, or interfaces; but they can be pointers to these types.

Records with variant parts are complicated syntactically but deceptively simple semantically. The variant part of a record contains several variants which share the same space in memory. You can read or write to any field of any variant at any time; but if you write to a field in one variant and then to a field in another variant, you may be overwriting your own data. The tag, if there is one, functions as an extra field (of type ordinalType) in the non-variant part of the record.

Variant parts have two purposes. First, suppose you want to create a record type that has fields for different kinds of data, but you know that you will never need to use all of the fields in a single record instance. For example:

The >TEmployee , there is no reason to allocate enough memory for both fields. In this case, the only difference between the variants is in the field names, but the fields could just as easily have been of different types. Consider some more complicated examples:

For each record instance, the compiler allocates enough memory to hold all the fields in the largest variant. The optional tag and the constantLists (like Rectangle , Triangle , and so forth in the last example) play no role in the way the compiler manages the fields; they are there only for the convenience of the programmer.

The second reason for variant parts is that they let you treat the same data as belonging to different types, even in cases where the compiler would not allow a typecast. For example, if you have a 64-bit Real as the first field in one variant and a 32-bit Integer as the first field in another, you can assign a value to the Real field and then read back the first 32 bits of it as the value of the Integer field (passing it, say, to a function that requires integer parameters).

Records (advanced)

In addition to the traditional record types, the Delphi language allows more complex and «class-like» record types. In addition to fields, records may have properties and methods (including constructors), class properties, class methods, class fields, and nested types. For more information on these subjects, see the documentation on Classes and Objects (Delphi). Here is a sample record type definition with some «class-like» functionality.

Though records can now share much of the functionality of classes, there are some important differences between classes and records.

  • Records do not support inheritance.
  • Records can contain variant parts; >New and Dispose function. > File Types (Win32)

File types, as available on the Win32 platform, are sequences of elements of the same type. Standard I/O routines use the predefined TextFile or Text type, which represents a file containing characters organized into lines. For more information about file input and output, see Standard Routines and Input-Output under the «File Input and Output» section.

To declare a file type, use the syntax:

where fileTypeName is any valid identifier and type is a fixed-size type. Pointer types — whether implicit or explicit — are not allowed, so a file cannot contain dynamic arrays, long strings, classes, objects, pointers, variants, other files, or structured types that contain any of these.

declares a file type for recording names and telephone numbers.

You can also use the file of . construction directly in a variable declaration. For example,

The word file by itself indicates an untyped file:

For more information, see «Untyped Files» in Standard Routines and Input-Output.

Files are not allowed in arrays or records.

Record — Ключевое слово Delphi

Я смотрю, что-то во многих учебниках этот элемент вообще не освещён.

никак, поэтому и не освещен

Удалено модератором
Примечание: Выражения выбираем


> Удалено модератором
> Примечание: Выражения выбираем

Но он врёт. Вводит людей в заблуждение.

Никто не врет. Просто нужно прочитать не много учебников а один. Но прочитать а не просмотреть.
«поля» записи это просто понятные компилятору псевдонимы адресов. Поэтому выбора там реально никакого нет. Просто записываешь и читаешь по адресу. Можешь записать по одному адресу а прочитать по другому.

TMyRec = packed record
case integer of
0: (a : dword);
1: (b : word; c : word);
end;

var rec :TMyRec;
begin
rec.a := 65537; // 10000000000000001 в двоичном
ShowMessage(Format(«%d %d»,[rec.b,rec.c]));
end;

идея понятна? перед wicked © извинишься?


> Sergey Masloff (27.07.07 06:00) [4]
>
> Никто не врет. Просто нужно прочитать не много учебников
> а один.

Сакчай учебник delphi7_self-tuition_beg.zip и пойди найди там эту тему.

В поваренной книге об этом тоже ничего нет.


> Sergey Masloff (27.07.07 06:00) [4]

Я никогда не понимал смысла в этом case integer of . Зачем указывать тип, когда он ни на что не влияет. Можно было бы просто разработать другой синтаксис. Объясните это?


> Я никогда не понимал смысла в этом case integer of. Зачем
> указывать тип, когда он ни на что не влияет. Можно было
> бы просто разработать другой синтаксис. Объясните это?

Исторически так сложилось. В классическом Паскале синтаксис предусматривал наличие селектора — специального поля, которое переключало альтернативы, что-то типа такого:

TSomeType = record
case S: Integer of
0: (X: Single;);
1: (A: array[0..3] of Byte);
end;

Подразумевалась проверка значяения селектора в run-time, т.е., например, к полю X можно было обратиться только тогда, когда поле S было равно 0, иначе — run-time error. аналогично к полю A обращаться можно было только когда S = 1 и т.п. Но это не прижилось из-за больших накладных расходов на проверку, на старых компьютерах это было критично, поэтому многие реализации компиляторов отказывались от проверки значения селектора. В такой ситуации сам селектор стал ненужным, поле выкинули, оставили только тип (точнее — произвольный идентификатор), который ни на что не влияет. Если не ошибаюсь, такое упрощение синтаксиса — это изобретение Borland

>поле выкинули, оставили только тип
есть два вида синтаксиса, один с полем селектора, под него даже место в записи отводится, только оно не заполняется ;)


> Однокамушкин (27.07.07 10:32) [8]
> TSomeType = record
> case S: Integer of
> 0: (X: Single;);
> 1: (A: array[0..3] of Byte);
> end;
> В такой ситуации сам селектор стал ненужным, поле выкинули,
> оставили только тип (точнее — произвольный идентификатор),
> который ни на что не влияет. Если не ошибаюсь, такое
> упрощение синтаксиса — это изобретение Borland

Нет не выкинули. S можно проверить и в зависимости от него самому обращаться к нужному полю.

>Жирный (28.07.07 07:50) [10]
> S можно проверить и в зависимости от него самому обращаться к нужному полю.

procedure TForm1.Button1Click(Sender: TObject);
type
TRec = packed record
case Selector: Byte of
0: (i: Integer);
1: (s: Single);
end;
var
r: TRec;
begin
FillChar(r, SizeOf(r), 0);
r.s := Pi;
Caption := Format(«%d %d»,[SizeOf(r), r.Selector])
end;


> MBo © (28.07.07 10:36) [11]
>
> >Жирный (28.07.07 07:50) [10]
> > S можно проверить и в зависимости от него самому обращаться
> к нужному полю.
>
> сам пробовал?

Само собой.
Только Дельфи не выдаёт ошибки если обращаешься не туда. Селектор для человека, а не для неё.


> Жирный (28.07.07 07:50) [10]
> Нет не выкинули. S можно проверить и в зависимости от него
> самому обращаться к нужному полю.

Это всё равно не селектор. В чём разница между

TSomeType1 = record
case S: Integer of
0: (X: Single;);
1: (A: array[0..3] of Byte);
end;
и
TSomeType2 = record
S: Integer;
case Integer of
0: (X: Single;);
1: (A: array[0..3] of Byte);
end;

А ни в чём! И там, и там для компилятора S — просто поле в записи, никак не связанное с вариантной частью. А то, что человек может придать этому полю смысл селектора — так он его чему угодно придать может. Весь смысл был именно в том, что проверка является обязательной и неявной. Если бы это сохранилось, то даже финализируемые типы вроде string и Variant можно было бы вставлять в вариантную часть — тогда компилятор мог бы при изменении значения селектора финализировать и инициализировать соответствующие альтернативы в вариантной части. А сейчас — не может, и вручную сделать не даёт.

С Сях это, вроде, union называется. Там даже пример есть, как на этом преобразуются типы


> Однокамушкин (29.07.07 17:32) [13]
> А то, что человек может придать этому полю смысл селектора
> — так он его чему угодно придать может.

Только как читающий код об этом догадается? Телепаты вышли из отпуска?

Это рудимент. Кто-нибудь видел код, где record case реально нужен и сипользован?


> TUser © (31.07.07 01:55) [16]
>
> Это рудимент. Кто-нибудь видел код, где record case реально
> нужен и сипользован?

TVarData = packed record
case Integer of
0: (VType: TVarType;
case Integer of
0: (Reserved1: Word;
case Integer of
0: (Reserved2, Reserved3: Word;
case Integer of
varSmallInt: (VSmallInt: SmallInt);
varInteger: (VInteger: Integer);
varSingle: (VSingle: Single);
varDouble: (VDouble: Double);
varCurrency: (VCurrency: Currency);
varDate: (VDate: TDateTime);
varOleStr: (VOleStr: PWideChar);
varDispatch: (VDispatch: Pointer);
varError: (VError: HRESULT);
varBoolean: (VBoolean: WordBool);
varUnknown: (VUnknown: Pointer);
varShortInt: (VShortInt: ShortInt);
varByte: (VByte: Byte);
varWord: (VWord: Word);
varLongWord: (VLongWord: LongWord);
varInt64: (VInt64: Int64);
varString: (VString: Pointer);
varAny: (VAny: Pointer);
varArray: (VArray: PVarArray);
varByRef: (VPointer: Pointer);
);
1: (VLongs: array[0..2] of LongInt);
);
2: (VWords: array [0..6] of Word);
3: (VBytes: array [0..13] of Byte);
);
1: (RawData: array [0..3] of LongInt);
end;

Если это рудимент, то как ты объявишь TVarData тогда?

TRect = packed record
case Integer of
0: (Left, Top, Right, Bottom: Longint);
1: (TopLeft, BottomRight: TPoint);
end;

Можно задавать TRect четырьмя числами или двумя точками.

а классом почему нельзя?


> ferr © (31.07.07 02:23) [19]
>
> а классом почему нельзя?

Типа барон любит чтоб было посложнее?

И как именно классом? Напиши такой класс.

> И как именно классом? Напиши такой класс.

public class Rectangle
<
private int _left, _top, _width, _height;

public Point TopLeft

public Point BottomRight

public int Width

public int Height
>

Класс полностью я писать не собираюсь, но морда у него обычно примерно такая. За подробности в .net framework классы Point и PointF.

P.S. в с++ в отличии от c# можно сделать и Rectangle ..


> ferr © (31.07.07 02:35) [22]
> > И как именно классом? Напиши такой класс.
>
>
> public class Rectangle
> <
> private int _left, _top, _width, _height;

Осталось выяснить, какое это имеет отношение к делфи.


> Жирный (31.07.07 02:12) [17]
> TVarData = packed record
>

Вообще-то этот тип является переводом на Delphi системного типа VARIANT: http://msdn2.microsoft.com/en-us/library/ms221627.aspx

Там нет селектора, сишный синтаксис его вообще не предусматривает, и ничего, всё понятно благодаря комментариям. Потому что всё-таки селектор без принудительной проверки — это не селектор, а способ написания комментария. Не самый лучший способ, кстати.


> Там нет селектора, сишный синтаксис его вообще не предусматривает,
> и ничего, всё понятно благодаря комментариям.

Типичный сишный идиотизм. Непонятный, нечитаемый код, который объясняется комментариями. Иногда на немецком или французском языке.

Пример того каким язык программирования не должен быть.


> Потому что всё-таки селектор без принудительной проверки

Какая тебе нужна проверка в вариантном типе из [17] ?
Или в [18] какая тебе проверка?


> Типичный сишный идиотизм. Непонятный, нечитаемый код, который
> объясняется комментариями. Иногда на немецком или французском
> языке.
>
> Пример того каким язык программирования не должен быть.

но увы реальный мир говорит об обратном:(


> Жирный (01.08.07 01:43) [25]
> Какая тебе нужна проверка в вариантном типе из [17] ?

Примерно такая, чтобы код типа
X := VarData.varInteger;
транслировался компилятором вот в такое:
if VarData.VType = varInteger then
X := VarData.varInteger
else
raise . // Неверное значение селектора

Кстати, объявление, приведённое в [17], в этом смысле неправильное, потому что у вариантного типа поле VType является селектором для полей varInteger, varDouble и т.п., а из данного объявления этот вывод сделать нельзя.

> celades © (01.08.07 02:10) [26]
> но увы реальный мир говорит об обратном:(

Любите башорг — источник мудрости:

Паша Форкерт: вот ты мне скажи, если фряха такая классная, то почему большинство сидит на линухе?
Bobs: паша
Bobs: если смотреть шире
Bobs: то _большинство_ сидит на винде
Bobs: а если смотреть еще шире, то большинство лускает семечки и спрашивает: «слышь, лох, закурить не найдется?»

С выбором языка программирования ситуация примерно та же самая.

Record — Ключевое слово Delphi

Each field in the structure is referenced in the manner record.field .

When declared, the Packed option tells Delphi to minimise the storage taken by the record. This reduction in storage can impact performance, where data is not aligned to appropriate 2, 4 or 8 byte boundaries. The default is to align, with fillers where necessary.

There are two basic types of record field, as shown in the two syntax types:

1.Basic field declarations

These are standard Delphi variable declarations, such as :

with the exception that their size must be defined. For example :

because Delphi must know the precise amount of storage to allocate to that field in the record.

2.Case (Variant) field sections

These must always follow any basic field declarations (which is why the case statement does not have a terminating end; clause).

These allow different, alternative data types to overlay each other. For example, a patient record may have a different section of declarations for women compared to men. Using the same basic record with a Variant portion is sensible when the bulk of the record is common.

By default, fields in a record are aligned on Byte and Word boundaries as appropriate for performance reasons. For both Record types, the packed option allows this to be overriden to reduce storage requirements, with the necessary small performance penalty.

11.11.2009, 11:43 #8
Notes
Using the With keyword, the fields of a record can be addressed without the need to prefix each with the record name.

Unlike Object Oriented languages like Java , the Delphi Record type provides a better performing mechanism for passing similar groups of data than data classes. They have their place in OO applications, especially where a class would otherwise have to be created for a structure of 2 or 3 fields.

Related commands
Case A mechanism for acting upon different values of an Ordinal
Packed Compacts complex data types into minimal storage
With A means of simplifying references to structured variables
Author links

Buy Website Traffic at
Buywebsitetrafficexperts.com

Buy Proxies at
Buyproxies.io

Download this web site as a Windows program.

Example code : Standard record definition
type
// Declare a customer record
TCustomer = Record
firstName : string[20];
lastName : string[20];
address1 : string[100];
address2 : string[100];
address3 : string[100];
city : string[20];
postCode : string[8];
end;

var
John, Sarah : TCustomer;

begin
// Set up the John’s customer details
with John do
begin
firstName := ‘John’;
lastName := ‘Smith’;
address1 := ‘7 Park Drive’;
address2 := ‘Branston’;
address3 := ‘Grimworth’;
city := ‘Banmore’;
postCode := ‘BNM 1AB’;
end;

// Set up John’s sister similarly — simply copying the whole record
Sarah := John;

// And then changing the first name to suit
Sarah.firstName := ‘Sarah’;

// Now show the details of both customers
with John do ShowCustomer([firstName, lastName,
address1, address2, address3,city,
postCode]);
ShowMessage(»);
with Sarah do ShowCustomer([firstName, lastName,
address1, address2, address3,city,
postCode]);
end;

// A procedure that displays a variable number of strings
procedure TForm1.ShowCustomer(const fields: array of string);
var
i : Integer;

begin
// Display all fields passed — note : arrays start at 0
for i := 0 to Length(fields)-1 do
ShowMessage(fields[i]);
end;

Show full unit code
John
Smith
7 Park Drive
Branston
Grimworth
Banmore
BNM 1AB

Sarah
Smith
7 Park Drive
Branston
Grimworth
Banmore
BNM 1AB

Записи Delphi

Здравствуйте. Сегодня мы познакомимся с записями Delphi. Записи, они же структуры в С++ это удобный способ хранения и обработки информации.

Объявление записи

В Delphi запись определяется следующим образом.

Мы оюбъявили запись MyRecord с двумя полями:

  • текстовым — MyString
  • целочисленным — MyInt

Записи по природе своей напоминают объекты, которые не имеют событий и методов, только свойства.

Применение записей Delphi

Записи в Delphi помогают решить некоторые вопросы без лишних усилий. Частенько приходится использовать массивы записей. Давайте разберем пример. Мы создадим структуру в которой будем хранить название месяца и количество дней. После мы объявим массив структур и заполним его. Наша программа будет выводить название месяца и количество дней по порядковому номеру.

Я набросал форму будущей программы, у меня получилось примерно так:

На форме расположены элементы:

  • TEdit
  • TUpDown (Максимальное значение 12, минимальное значение 1, привязан к TEdit)
  • TBUtton
  • Tlabel — 4 шт.
Илон Маск рекомендует:  Олимпиады по информатике
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL