Программирование на языке Delphi. Глава 2. Основы языка Delphi. Часть 3 |
Автор Administrator | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
10.02.2009 г. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ОглавлениеПрограммные модулиСтруктура модуляЛогически обособленные группы процедур и функций чрезвычайно удобно объединять в специализированные библиотеки - модули. Для этого язык Delphi предлагает специальные средства и доступную каждому технологию. Приведем общую структуру программного модуля: Заголовок модуля unit <имя модуля>; Директивы компилятора {$<директивы>} Интерфейсная часть interface Подключение модулей uses <имя>, ..., <имя>; Константы const ... ; Типы данных type ... ; Переменные var ... ; Заголовки процедур procedure <имя> (<параметры>); Заголовки функций function <имя> (<параметры>): <тип>; Часть реализации implementation Подключение модулей uses <имя>, ..., <имя>; Константы const ... ; Типы данных type ... ; Переменные var ... ; Реализация процедур procedure <имя>; begin ... end; Реализация функций function <имя>; begin ... end; Код инициализации initialization <операторы> Код завершения finalization <операторы> end. После слова unit записывается имя модуля. Оно должно совпадать с именем файла, в котором находится исходный текст модуля. Например, если файл называется MathLib.pas, то модуль должен иметь имя MathLib. Заголовок модуля формируется автоматически при сохранении файла на диске, поэтому его не следует изменять вручную. Чтобы дать модулю другой заголовок, просто сохраните его на диске под другим именем. В разделе interface описываются глобальные данные, процедуры и функции, доступные для использования в основной программе и других модулях. В разделе implementation реализуется программный код глобальных процедур и функций и описываются локальные данные, процедуры и функции, недоступные основной программе и другим модулям. Блок initialization является необязательным. Он состоит из операторов и выполняется автоматически непосредственно перед запуском основной программы. Блоки инициализации подключенных к программе модулей выполняются в том порядке, в котором они упоминаются в секции uses. Блок finalization тоже является необязательным. Он состоит из операторов и выполняется автоматически непосредственно после завершения основной программы. Блоки завершения подключенных к программе модулей выполняются в порядке, обратном порядку подключения модулей в секции uses. Если модуль не нуждается в инициализации и завершении, блоки initialization и finalization можно опустить. В качестве упражнения давайте создадим модуль и подключим его к основной программе (для этого сначала запустите среду Delphi):
Рисунок 8. Окно сохранения модуля
Теперь перейдем к содержимому модуля. Давайте объявим в нем константу Pi и две функции: Power - вычисление степени числа, и Average - вычисление среднего арифметического двух чисел: unit MathLib; interface const Pi = 3.14; function Power(X, Y: Double): Double; function Average(X, Y: Double): Double; implementation function Power(X, Y: Double): Double; begin Result := Exp(Y * Ln(X)); end; function Average(X, Y: Double): Double; begin Result := (X + Y) / 2; end; end. Вот как могла бы выглядеть программа, использующая модуль Math: program Console; {$APPTYPE CONSOLE} uses SysUtils, MathLib in 'MathLib.Pas'; begin Writeln(Pi); Writeln(Power(2, 4)); Writeln(Average(2, 4)); Writeln('Press Enter to exit...'); Readln; end. После компиляции и запуска программы вы увидите на экране три числа (рисунок 10):
Рисунок 10. Результат работы программы Console Стандартные модули языка DelphiВ состав среды Delphi входит великолепный набор модулей, возможности которых удовлетворят даже самого привередливого программиста. Все модули можно разбить на две группы: системные модули и модули визуальных компонентов. К системным модулям относятся System, SysUtils, ShareMem, Math. В них содержатся наиболее часто используемые в программах типы данных, константы, переменные, процедуры и функции. Модуль System - это сердце среды Delphi; содержащиеся в нем подпрограммы обеспечивают работу всех остальных модулей системы. Модуль System подсоединяется автоматически к каждой программе и его не надо указывать в операторе uses. Модули визуальных компонентов (VCL - Visual Component Library) используются для визуальной разработки полнофункциональных GUI-приложений - приложений с графическим пользовательским интерфейсом (Graphical User Interface). Эти модули в совокупности представляют собой высокоуровневую объектно-ориентированную библиотеку со всевозможными элементами пользовательского интерфейса: кнопками, надписями, меню, панелями и т.д. Кроме того, модули этой библиотеки содержат простые и эффективные средства доступа к базам данных. Данные модули подключаются автоматически при помещении компонентов на форму, поэтому вам об этом заботиться не надо. Их список слишком велик, поэтому мы его не приводим. Все основные модули среды Delphi, включая модули визуальных компонентов, поставляются вместе с их исходными текстами на языке Delphi. По мере роста вашего профессионального опыта мы рекомендуем чаще обращаться к этим исходным текстам. Во-первых, в них вы найдете ответы на многие вопросы о внутреннем устройстве среды Delphi, а во-вторых, они послужат образцовым примером профессионального подхода в решении широкого круга задач. И, в-третьих, что не менее важно, это поможет научиться красиво и правильно (в рамках устоявшегося стиля) оформлять тексты Ваших собственных программ так, чтобы их с легкостью читали и понимали другие программисты. Исходные тексты стандартных модулей среды Delphi находятся в каталоге Delphi/Source. Область действия идентификаторовПри программировании необходимо соблюдать ряд правил, регламентирующих использование идентификаторов:
СтрокиСтроковые значенияСтрока - это последовательность символов. При программировании строковые значения заключаются в апострофы, например: Writeln('Я тебя люблю'); Так как апостроф является служебным символом, для его записи в строке как значащего символа применяются два апострофа, следующих непосредственно друг за другом: Writeln('Object Pascal is Delphi''s and Kylix''s language'); Для записи отсутствующих на клавиатуре символов используется символ #, за которым следует десятичный номер символа в кодовой таблице ASCII, например: Writeln('Copyright '#169' А.Вальвачев, К.Сурков, Д.Сурков, Ю.Четырько'); Строка, которая не содержит символов, называется пустой: Writeln(''); Теперь, когда известно, что представляют собой строковые значения, займемся строковыми переменными. Строковые переменныеСтроковая переменная объявляется с помощью зарезервированного слова string или с помощью идентификатора типа данных AnsiString, например: var
FileName: string;
EditText: AnsiString; Строку можно считать бесконечной, хотя на самом деле ее длина ограничена 2 ГБ. В зависимости от присваиваемого значения строка увеличивается и сокращается динамически. Это удобство обеспечивается тем, что физически строковая переменная хранит не сами символы, а адрес символов строки в области динамически распределяемой памяти (о динамически распределяемой памяти мы расскажем ниже). При создании строки всегда инициализируются пустым значением (''). Управление динамической памятью при операциях со строками выполняется автоматически с помощью стандартных библиотек языка Delphi. Вы конечно же можете описывать строковые типы данных и использовать их при объявлении переменных и типизированных констант, например: type TName = string; var Name: TName; const FriendName: TName = 'Alexander'; Символы строки индексируются от 1 до N+1, где N - реальная длина строки. Символ с индексом N+1 всегда равен нулю (#0). Для получения длины следует использовать функцию Length, а для изменения длины - процедуру SetLength (см. ниже). Для того чтобы в программе обратиться к отдельному символу строки, нужно сразу за идентификатором строковой переменной или константы в квадратных скобках записать его номер. Например, FriendName[1] возвращает значение ‘A’, а FriendName[4] - ‘x’. Символы, получаемые в результате индексирования строки, принадлежат типу Char. Достоинство строки языка Delphi состоит в том, что она объединяет в себе свойства строки самого языка Delphi и строки языка C. Оперируя строкой, вы оперируете значением строки, а не адресом в оперативной памяти. В то же время строка не ограничена по длине и может передаваться вместо C-строки (как адрес первого символа строки) в параметрах процедур и функций. Чтобы компилятор позволил это сделать, нужно, записывая строку в качестве параметра, преобразовать ее к типу PChar (тип данных, используемый в языке Delphi для описания нуль-терминированных строк языка C). Такое приведение типа допустимо по той причине, что строка всегда завершается нулевым символом (#0), который хоть и не является ее частью, тем не менее всегда дописывается сразу за последним символом строки. В результате формат строки удовлетворяет формату C-строки. О работе с нуль-терминированными строками мы поговорим чуть позже. Строки в формате UnicodeДля поддержки работы со строками формата Unicode в язык Delphi имеется строковый тип данных WideString. Работа со строками типа WideString почти не отличается от работы со строками типа AnsiString; существуют лишь два отличия. Первое отличие состоит в представлении символов. В строках типа WideString каждый символ кодируется не одним байтом, а двумя. Соответственно элементы строки WideString - это символы типа WideChar, тогда как элементы строки AnsiString - это символы типа AnsiChar. Второе отличие состоит в том, что происходит при присваивании строковых переменных. Об этом вы узнаете чуть позже, прочитав параграф "Представление строк в памяти". Короткие строкиКороткая строка объявляется с помощью идентификатора типа ShortString или зарезервированного слова string, за которым следует заключенное в квадратные скобки значение максимально допустимой длины, например: var Address: ShortString; Person: string[30]; Короткая строка может иметь длину от 1 до 255 символов. Предопределенный тип данных ShortString эквивалентен объявлению string[255]. Реальная длина строки может быть меньше или равна той, что указана при ее объявлении. Например, максимальная длина строки Friend в примере выше составляет 30 символов, а ее реальная длина - 9 символов. Реальную длину строки можно узнать с помощью встроенной функции Length. Например, значение Length(Friend) будет равно 9 (количество букв в слове Alexander). Все символы в строке типа ShortString пронумерованы от 0 до N, где N - максимальная длина, указанная при объявлении. Символ с номером 0 - это служебный байт, в нем содержится реальная длина короткой строки. Значащие символы нумеруются от 1. Очевидно, что в памяти строка занимает на 1 байт больше, чем ее максимальная длина. Поэтому значение SizeOf(Friend) будет равно 31. type TName = string[30]; var Name: TName; const FriendName: TName = 'Alexander'; Обратиться к отдельному символу можно так же, как и к символу обычной строки. Например, выражения FriendName[1] и FriendName[9] возвращают соответственно символы 'A' и 'r'. Значения FriendName[10] .. FriendName[30] будут случайными, так как при объявлении типизированной константы FriendName символы с номерами от 10 до 30 не были инициализированы. Символы, получаемые в результате индексирования короткой строки, принадлежат типу Char. Поскольку существует два типа строк: обычные (длинные) строки и короткие строки, возникает закономерный вопрос, можно ли их совмещать. Да, можно! Короткие и длинные строки могут одновременно использоваться в одном выражении, поскольку компилятор языка Delphi автоматически генерирует код, преобразующий их тип. Более того, можно выполнять явные преобразования строк с помощью конструкций вида ShortString(S) и AnsiString(S). Операции над строкамиВыражения, в которых операндами служат строковые данные, называются строковыми. Они состоят из строковых констант, переменных, имен функций и строковых операций. Над строковыми данными допустимы операции сцепления и отношения. Операция сцепления (+) применяется для сцепления нескольких строк в одну строку.
Операции отношения (=, <>, >, <, >=, <=) проводят сравнение двух строковых операндов. Сравнение строк производится слева направо до первого несовпадающего символа, и та строка считается больше, в которой первый несовпадающий символ имеет больший номер в кодовой таблице. Строки считаются равными, если они полностью совпадают по длине и содержат одни и те же символы. Если строки имеют различную длину, но в общей части символы совпадают, считается, что более короткая строка меньше, чем более длинная.
Если короткой строке присваивается значение, длина которого превышает максимально допустимую величину, то все лишние символы справа отбрасываются.
Допускается смешение в одном выражении операндов строкового и символьного типа, например при сцеплении строки и символа. Строковые ресурсыВ языке Delphi существует специальный вид строковых данных - строковые ресурсы. Строковые ресурсы очень похожи на строковые константы, но отличаются от них тем, что размещаются не в области данных программы, а в специальной области выполняемого файла, называемой ресурсами. Если данные всегда загружаются вместе с кодом программы и остаются в оперативной памяти вплоть до завершения программы, то ресурсы подгружаются в оперативную память лишь по мере надобности. В программе строковые ресурсы описываются как обычные строковые константы, с той лишь разницей что раздел их описания начинается не словом const, а словом resourcestring: resourcestring SCreateFileError = 'Cannot create file: '; SOpenFileError = 'Cannot open file: '; Использование строковых ресурсов ничем не отличается от использования строковых констант: var S: string; begin S := SCreateFileError + 'MyFile.txt'; ... end; На роль строковых ресурсов отлично подходят сообщения об ошибках, которые занимают много места в памяти и остаются не нужны до тех пор, пока в программе не возникнет ошибка. Использование ресурсов упрощает перевод пользовательского интерфейса на другие языки, поскольку замена текстовых сообщений может производиться непосредственно в выполняемом файле, т.е. без перекомпиляции программы. Форматы кодирования символовСуществуют различные форматы кодирования символов. Отдельный символ строки может быть представлен в памяти одним байтом (стандарт Ansi), двумя байтам (стандарт Unicode) и даже четырьмя байтами (стандарт UCS-4 - Unicode). Строка "Wirth" (фамилия автора языка Pascal - прародителя языка Delphi) будет представлена в указанных форматах следующим образом (рисунок 11):
Рисунок 11. Форматы кодирования символов Существует также формат кодирования MBCS (Multibyte Character Set), согласно которому символы одной строки кодируются разным количеством байт (одним или двумя байтами в зависимости от алфавита). Например, буквы латинского алфавита кодируются одним байтом, а иероглифы японского алфавита - двумя. При этом латинские буквы и японские иероглифы могут встречаться в одной и той же строке. Стандартные процедуры и функции для работы со строкамиТак как обработка строк выполняется практически в каждой серьезной программе, стандартно подключаемый модуль System имеет набор процедур и функций, значительно облегчающих этот процесс. Все следующие процедуры и функции применимы и к коротким, и к длинным строкам.
Примеры:
Описанные процедуры и функции являются базовыми для всех остальных подпрограмм обработки строк из модуля SysUtils.
МассивыОбъявление массиваМассив - это составной тип данных, состоящий из фиксированного числа элементов одного и того же типа. Для описания массива предназначено словосочетание array of. После слова array в квадратных скобках записываются границы массива, а после слова of - тип элементов массива, например: type TStates = array[1..50] of string; TCoordinates = array[1..3] of Integer; После описания типа можно переходить к определению переменных и типизированных констант: var States: TStates; { 50 strings } const Coordinates: TCoordinates = (10, 20, 5); { 3 integers } Обратите внимание, что инициализация элементов массива происходит в круглых скобках через запятую. Массив может быть определен и без описания типа: var Symbols: array[0..80] of Char; { 81 characters } Чтобы получить доступ к отдельному элементу массива, нужно в квадратных скобках указать его индекс, например Symbols[0] Объявленные выше массивы являются одномерными, так как имеют только один индекс. Одномерные массивы обычно используются для представления линейной последовательности элементов. Если при описании массива задано два индекса, массив называется двумерным, если n индексов - n-мерным. Двумерные массивы используются для представления таблицы, а n-мерные - для представления пространств. Вот пример объявления таблицы, состоящей из 5 колонок и 20 строк: var Table: array[1..5] of array[1..20] of Double; То же самое можно записать в более компактном виде: var Table: array[1..5, 1..20] of Double; Чтобы получить доступ к отдельному элементу многомерного массива, нужно указать значение каждого индекса, например Table[2][10] или в более компактной записи Table[2, 10] Эти два способа индексации эквивалентны. Работа с массивамиМассивы в целом участвуют только в операциях присваивания. При этом все элементы одного массива копируются в другой. Например, если объявлены два массива A и B, var A, B: array[1..10] of Integer; то допустим следующий оператор: A := B; Оба массива-операнда в левой и правой части оператора присваивания должны быть не просто идентичны по структуре, а описаны с одним и тем же типом, иначе компилятор сообщит об ошибке. Именно поэтому все массивы рекомендуется описывать в секции type. С элементами массива можно работать, как с обычными переменными. В следующей программе элементы численного массива последовательно вводятся с клавиатуры, а затем суммируются. Результат выводится на экран. program Console; {$APPTYPE CONSOLE} uses SysUtils; var A: array[1..5] of Double; Sum: Double; I: Integer; begin for I := 1 to 5 do Readln(A[I]); Sum := 0; for I := 1 to 5 do Sum := Sum + A[I]; Writeln(Sum); Writeln('Press Enter to exit...'); Readln; end. Для массивов определены две встроенные функции - Low и High. Они получают в качестве своего аргумента имя массива. Функция Low возвращает нижнюю, а High - верхнюю границу этого массива. Например, Low(A) вернет значение 1, а High(A) - 5. Функции Low и High чаще всего используются для указания начального и конечного значений в операторе цикла for. Поэтому вычисление суммы элементов массива A лучше переписать так: for I := Low(A) to High(A) do Sum := Sum + A[I]; В операциях с многомерными массивами циклы for вкладываются друг в друга. Например, для инициализации элементов таблицы, объявленной как var Table: array[1..5, 1..20] of Double; требуются два вложенных цикла for и две целые переменные Col и Row для параметров этих циклов: for Col := 1 to 5 do for Row := 1 to 20 do Table[Col, Row] := 0; Массивы в параметрах процедур и функцийМассивы, как и другие типы данных, могут выступать в качестве параметров процедур и функций. Вот как может выглядеть функция, вычисляющая среднее значение в массиве действительных чисел: const Max = 63; type TStatistics = array [0..Max] of Double; function Average(const A: TStatistics): Double; var I: Integer; begin Result := 0; for I := Low(A) to High(A) do Result := Result + A[I]; Result := Result / (High(A) - Low(A) + 1); end; Функция Average принимает в качестве параметра массив известной размерности. Требование фиксированного размера для массива-параметра часто является чрезмерно сдерживающим фактором. Процедура для нахождения среднего значения должна быть способна работать с массивами произвольной длины. Для этой цели в язык Delphi введены открытые массивы-параметры. Такие массивы были заимствованы разработчиками языка Delphi из языка Modula-2. Открытый массив-параметр описывается с помощью словосочетания array of, при этом границы массива опускаются: function Average(const A: array of Double): Double; var I: Integer; begin Result := 0; for I := Low(A) to High(A) do Result := Result + A[I]; Result := Result / (High(A) - Low(A) + 1); end; Внутри подпрограммы Average нижняя граница открытого массива A равна нулю (Low(A) = 0), а вот значение верхней границы (High(A)) неизвестно и выясняется только на этапе выполнения программы. Существует только два способа использования открытых массивов: обращение к элементам массива и передача массива другой подпрограмме, принимающей открытый массив. Нельзя присваивать один открытый массив другому, потому что их размеры заранее неизвестны. Вот пример использования функции Average: var Statistics: array[1..10] of Double; Mean: Double; begin ... Mean := Average(Statistics); Mean := Average([0, Random, 1]); ... end; Заметьте, что во втором операторе открытый массив конструируется в момент вызова функции Average. Конструктор открытого массива представляет собой заключенный в квадратные скобки список выражений. В выражениях могут использоваться константы, переменные и функции. Тип выражений должен быть совместим с типом элементов массива. Конструирование открытого массива равносильно созданию и инициализации временной переменной. И еще одно важное замечание по поводу открытых массивов. Некоторые библиотечные подпрограммы языка Delphi принимают параметры типа array of const - открытые массивы констант. Массив, передаваемый в качестве такого параметра, обязательно конструируется в момент вызова подпрограммы и может состоять из элементов различных типов (!). Физически он состоит из записей типа TVarRec, кодирующих тип и значение элементов массива (записи рассматриваются ниже). Открытый массив констант позволяет эмулировать подпрограммы с переменным количеством разнотипных параметров и используется, например, в функции Format для форматирования строки (см. выше). Уплотнение структурных данных в памятиС целью экономии памяти, занимаемой массивами и другими структурными данными, вы можете предварять описание типа зарезервированным словом packed, например: var A: packed array[1..10] of Byte; Ключевое слово packed указывает компилятору, что элементы структурного типа должны храниться плотно прижатыми друг к другу, даже если это замедляет к ним доступ. Если структурный тип данных описан без ключевого слова packed, компилятор выравнивает его элементы на 2- и 4-байтовых границах, чтобы ускорить к ним доступ. Заметим, что ключевое слово packed применимо к любому структурному типу данных, т.е. массиву, множеству, записи, файлу, классу, ссылке на класс. МножестваОбъявление множестваМножество - это составной тип данных для представления набора некоторых элементов как единого целого. Область значений множества - набор всевозможных подмножеств, составленных из его элементов. Все элементы множества должны принадлежать однобайтовому порядковому типу. Этот тип называется базовым типом множества. Для описания множественного типа используется словосочетание set of, после которого записывается базовый тип множества: type TLetters = set of 'A'..'Z'; Теперь можно объявить переменную множественного типа: var
Letters: TLetters; Можно объявить множество и без предварительного описания типа: var
Symbols: set of Char; В выражениях значения элементов множества указываются в квадратных скобках: [2, 3, 5, 7], [1..9], ['A', 'B', 'C']. Если множество не имеет элементов, оно называется пустым и обозначается как [ ]. Пример инициализации множеств: const Vowels: TLetters = ['A', 'E', 'I', 'O', 'U']; begin Letters := ['A', 'B', 'C']; Symbols := [ ]; { пустое множество } end; Количество элементов множества называется мощностью. Мощность множества в языке Delphi не может превышать 256. Операции над множествамиПри работе с множествами допускается использование операций отношения (=, <>, >=, <=), объединения, пересечения, разности множеств и операции in. Операции сравнения (=, <>). Два множества считаются равными, если они состоят из одних и тех же элементов. Порядок следования элементов в сравниваемых множествах значения не имеет. Два множества A и B считаются не равными, если они отличаются по мощности или по значению хотя бы одного элемента.
Операции принадлежности (>=, <=). Выражение A >= B равно True, если все элементы множества B содержатся в множестве A. Выражение A <= B равно True, если выполняется обратное условие, т.е. все элементы множества A содержатся в множестве B.
Операция in. Используется для проверки принадлежности элемента указанному множеству. Обычно применяется в условных операторах.
Операция in позволяет эффективно и наглядно выполнять сложные проверки условий, заменяя иногда десятки других операций. Например, оператор if (X = 1) or (X = 2) or (X = 3) or (X = 5) or (X = 7) then можно заменить более коротким: if X in [1..3, 5, 7] then Операцию in иногда пытаются записать с отрицанием: X not in S. Такая запись является ошибочной, так как две операции следуют подряд. Правильная запись имеет вид: not (X in S). Объединение множеств (+). Объединением двух множеств является третье множество, содержащее элементы обоих множеств.
Пересечение множеств (*). Пересечение двух множеств - это третье множество, которое содержит элементы, входящие одновременно в оба множества.
Разность множеств (-). Разностью двух множеств является третье множество, которое содержит элементы первого множества, не входящие во второе множество.
В язык Delphi введены две стандартные процедуры Include и Exclude, которые предназначены для работы с множествами. Процедура Include(S, I) включает в множество S элемент I. Она дублирует операцию + (плюс) с той лишь разницей, что при каждом обращении включает только один элемент и делает это более эффективно. Процедура Exclude(S, I) исключает из множества S элемент I. Она дублирует операцию - (минус) с той лишь разницей, что при каждом обращении исключает только один элемент и делает это более эффективно.
Использование в программе множеств дает ряд преимуществ: значительно упрощаются сложные операторы if, улучшается наглядность программы и понимание алгоритма решения задачи, экономится время разработки программы. Поэтому множества широко используются в библиотеке компонентов среды Delphi. ЗаписиОбъявление записиЗапись - это составной тип данных, состоящий из фиксированного числа элементов одного или нескольких типов. Описание типа записи начинается словом record и заканчивается словом end. Между ними заключен список элементов, называемых полями, с указанием идентификаторов полей и типа каждого поля: type TPerson = record FirstName: string[20]; // имя LastName: string[20]; // фамилия BirthYear: Integer; // год рождения end; Идентификаторы полей должны быть уникальными только в пределах записи. Допускается вложение записей друг в друга, т.е. поле записи может быть в свою очередь тоже записью. Чтобы получить в программе реальную запись, нужно создать переменную соответствующего типа: var
Friend: TPerson; Записи можно создавать и без предварительного описания типа, но это делается редко, так как мало отличается от описания полей в виде отдельных переменных. Доступ к содержимому записи осуществляется посредством идентификаторов переменной и поля, разделенных точкой. Такая комбинация называется составным именем. Например, чтобы получить доступ к полям записи Friend, нужно записать: Friend.FirstName := 'Alexander'; Friend.LastName := 'Ivanov'; Friend.BirthYear := 1991; Обращение к полям записи имеет несколько громоздкий вид, что особенно неудобно при использовании мнемонических идентификаторов длиной более 5 символов. Для решения этой проблемы в языке Delphi предназначен оператор with, который имеет формат: with <запись> do
<оператор>; Однажды указав имя записи в операторе with, можно работать с именами ее полей как с обычными переменными, т.е. без указания идентификатора записи перед идентификатором поля: with Friend do begin FirstName := 'Alexander'; LastName := 'Ivanov'; BirthYear := 1991; end; Допускается применение оператора присваивания и к записям в целом, если они имеют один и тот же тип. Например, Friend := BestFriend; После выполнения этого оператора значения полей записи Friend станут равными значениям соответствующих полей записи BestFriend. Записи с вариантамиСтрого фиксированная структура записи ограничивает возможность ее применения. Поэтому в языке Delphi имеется возможность задать для записи несколько вариантов структуры. Такие записи называются записями с вариантами. Они состоят из необязательной фиксированной и вариантной частей. Вариантная часть напоминает условный оператор case. Между словами case и of записывается особое поле записи - поле признака. Оно определяет, какой из вариантов в данный момент будет активизирован. Поле признака должно быть равно одному из расположенных следом значений. Каждому значению сопоставляется вариант записи. Он заключается в круглые скобки и отделяется от своего значения двоеточием. Пример описания записи с вариантами: type TFigure = record X, Y: Integer; case Kind: Integer of 0: (Width, Height: Integer); // прямоугольник 1: (Radius: Integer); // окружность end; Обратите внимание, что у вариантной части нет отдельного end, как этого можно было бы ожидать по аналогии с оператором case. Одно слово end завершает и вариантную часть, и всю запись. На этом мы пока закончим рассказ о записях, но хотим надеяться, что читатель уже догодался об их потенциальной пользе при организации данных с более сложной структурой. |
« Пред. | След. » |
---|