Символьные типы данных
Символьные типы предназначены для хранения одного символа. Они относятся к целым порядковым типам. Ниже приведена таблица символьных типов. Наличие двух разных типов — ANSIChar и WideChar связано с двумя различными множествами символов: ANSI, каждый символ которого занимает 1 байт, и Unicode, каждый символ которого занимает 2 байта. Первые 256 символов в этих множествах одинаковы и соответствуют символам ASCII от 0 до
255.
|
Тип |
Размер в байтах |
Что может хранить |
|
ANSIChar |
1 |
Один символ ANSI |
|
WideChar |
2 |
Один символ Unicode |
|
Char |
1 |
Сейчас эквивалентен ANSIChar. В будущих версияхDelphiможет быть будет эквивалентенWideChar. |
Родовым (т.е. обеспечивающим максимальную производительность) является тип Char, который в настоящий момент эквивалентен типуANSIChar, но в последующих версиях это может быть изменено. Именно типCharимеет смысл использовать во всех случаях, кроме обращений к функциям, требующим другой тип символьных данных.
Приведенные в таблице затраты памяти могут изменяться от версии к версии и от системы к системе. Поэтому, если требуется достоверно знать затраты памяти для того или иного типа, следует пользоваться функцией SizeOf.
Для символьного типа предопределена функция Chr, возвращающая символ любого целого значения в пределахAnsiCharилиWideChar. Например,Chr(65) возвращает букву "A". Поскольку символьные типы относятся к порядковым, для них предопределены такие функции и процедуры, какOrd,Pred,Succ,Inc,Decи др. ФункцияOrd, возвращающая номер символа, противоположна по смыслу функцииChr. Т.е.Ord(Chr(65)) вернет 65, аChr(Ord('A')) вернет символ "A".
Типы строк
Строки представляют собой последовательность символов. Ниже приведена таблица типов строк.
|
Тип строки |
Максимальная длина |
Используется для |
Нулевой символ в конце |
|
ShortString |
255 |
обратной совместимости |
нет |
|
AnsiString |
~231 (~2 Гб) |
символов ANSI |
есть |
|
String |
или 255, или до 2 Гб |
символов ANSIилиUnicode |
есть или нет |
|
WideString |
~230(~1 Гб) |
символов Unicode, в серверахCOMи интерфейсах |
есть |
Родовым является тип String, который имеет разный смысл в зависимости от директивы компилятора $H. Если включена директива {$H+} (она включена по умолчанию), тоStringинтерпретируется компилятором как типAnsiString- длинная строка с нулевым символом в конце. Если же включить директиву {$H-}, тоStringинтерпретируется компилятором как типShortString- короткая строка без нулевого символа в конце. Если в объявлении типа после ключевого словаStringследует число символов в квадратных скобках (например,String[4]), то, независимо от директив компилятора, тип трактуется как строка без нулевого символа в конце с указанным числом символов.
Стандартная функция Lengthвозвращает число символов в строке, переданной ей в качестве параметра. ПроцедураSetLengthустанавливает длину строки.
Для строк определены операции сравнения > , <, = и т.п. Если сравниваются строки разной длины, то большей считается более длинная строка. Если сравниваются строки одинаковой длины, то принимаются в расчет символы в одинаковых позициях - сравниваются коды этих символов.
Со строками можно оперировать как с индексированными массивами символов. Например, S[i] - это символ, расположенный в строке в позицииi(индексы отсчитываются от 1, т.е. индекс 1 соответствует первому символу). Для строк типаShortStringилиAnsiStringвыражениеS[i] имеет типAnsiChar, для строк типаWideString-WideChar.
Сцепление (конкатенация) строк осуществляется операцией "+". Например, выражение S1+S2 даст в результате строку, в которой после символов строкиS1 будут расположены символы строкиS2.
Строки разных типов могут присваиваться друг другу и смешиваться в одном выражении. Компилятор при этом осуществляет автоматическое приведение типов. Но строки, передаваемые как параметры в функции и процедуры, должны иметь тип, указанный в объявлениях этих функций и процедур. В этих случаях надо использовать операцию явного приведения типов или другие приемы программирования.
Типы строк можно классифицировать по двум признакам: длинные или короткие строки и строки, использующие или не использующие нулевой символ в конце. При работе со строками с нулевым символом в конце часто используют специальные типы указателей: PCharиPWideChar.
Все сказанное относится к Delphi2-7. ВDelphi1 имеются существенные отличия: отсутствие типов длинных строк и отсутствие приведения типов строк, использующих и не использующих нулевой символ в конце. Поэтому для преобразования типов строк надо использовать специальные функции.
Рассмотрим сначала различие между короткими (ShortString) и длинными (AnsiString) строками. Они различаются прежде всего организацией хранения в памяти. Строки типаShortString хранят в своем нулевом байте число символов в строке, а в последующих байтах — сами символы (не более 255). Поэтому, если S — строка типаShortString, то Ord(S[0]) возвращает длину строки, т.е. то же
значение, которое возвращает функция Length(S). Соответственно присваивание значения S[0] эквивалентно вызову функцииSetLength, устанавливающему длину строки.
Размещение в памяти длинных строк отличается от рассмотренного выше для коротких строк. Переменная типа AnsiString является указателем на динамически выделяемую область памяти, в которой хранится строка. Поэтому может быть несколько переменных, ссылающихся на одну и ту
же строку. В этом случае в памяти хранится только один экземпляр строки, что позволяет экономить ресурсы. Если длина строки равна 0, то этот указатель равен nil и память под строку не выделяется. Если же строка не пустая, то в выделенной для нее области памяти хранится сама строка, ее длина и число ссылок на данную строку (число переменных, ссылающихся на данную строку), Если переменной типа AnsiString присваивается новое значение, то число ссылок в прежней строке уменьшается на 1, а в новой — увеличивается на 1. Если число ссылок на строку
становится равным 0, то строка уничтожается, освобождая место в памяти. Если с помощью индексного обращения в строке изменяется один символ, то строка копируется только в том случае, если число ссылок на нее больше 1. Все это позволяет эффективно использовать память.
Теперь остановимся на использовании в строках нулевого конечного символа. В настоящее время тип ShortString поддерживается в Object Pascal только для обеспечения обратной совместимости с более ранними версиями языка. А основным типом строк становятся строки с нулевым символом в конце. Связано это с тем, что этот вид строк поддерживается такими языками программирования, как С и C++, а также API Windows и многими другими системами. Строки с нулевым символом в конце представляют собой массивы символов с индексами, начинающимися с 0. В массиве хранятся символы строки и в конце нулевой символ (#0), указывающий на окончание строки. Таким образом, тип строки с нулевым символом в конце может, например, объявляться какAnsiString, а может объявляться как статический массив символов, например:
type
TS = array[0..15] of Char;
Если значение переменной строки с нулевым символом в конце инициализируется при ее объявлении, то после значащих символов остальные элементы массива надо инициализировать символами #0. Например:
const SHello: array[0..7] of Char = 'Привет!'#0;
Этого не надо делать в операторах присваивания. Например:
SHello := 'Привет!';
Отметим, что ту же самую типизированную константу SHello можно было бы с тем же успехом объявить следующим образом:
const SHello: AnsiString = 'Привет!’ ;
При работе со строками с нулевым символом в конце часто используют специальные типы указателей: PChar и PWideChar, которые являются указателями соответственно на массивы с элементами типовChar и WideChar с нулевым символом в конце. Переменные этих типов часто требуется передавать в различные функции и процедуры в качестве параметров. К тому же, типыPChar и PWideChar существенно упрощают коды. Дело в том, что эти типы совместимы со строковыми константами. Например, объявление и использование переменной
типа PChar может иметь вид:
var
P: PChar;
р := 'Привет!';
Это эквивалентно операторам
const
SHello: array[0..7] of Char = 'Привет!'#0;
var
P: PChar;
…
P := @SHello;
но, конечно, гораздо короче.
Совместимость указателей типов PChar и PWideChar со строковыми константами позволяет в вызовах функций и процедур с параметрами соответствующих типов использовать просто строки символов. Например, если некоторая процедура F требует параметр типаPChar, то обратиться к ней можно так:
var P: PChar;
Р := 'Привет!';
F(Р);
или так:
F ('Привет !');
Указатели типов РСhar и PWideChar могут индексироваться точно так же, как строки и массивы символов. Например,Р[0] — это первый символ строки, на которую указывает Р.
В выражениях, операторах присваивания и при передаче параметров в функции и процедуры можно смешивать длинные строки (AnsiString) и строки с нулевым символом в конце типа PChar. Но иногда требуется явное приведение типаPChar к типу длинной строки. Например, операция склеивания (конкатенации) строк требует, чтобы хотя бы один ее операнд был типа строки. Если же требуется склеить два объекта типаPChar, то это надо делать с помощью приведения типа:
S := string(Pl) + string(P2);
В ряде случаев требуется обратное преобразование типов строк: длинной строки типа AnsiString в строку с нулевым символом в конце типа PChar. Это приходится делать при передаче параметров в функции, требующие тип PChar. В этих случаях надо явным образом приводить тип строки к PChar. Например:
var s: string;
s := StrLower(PChar(Editl.Text)) ;
Свойство Text окна редактирования Edit имеет тип string, а функция StrLower преобразования текста к нижнему регистру требует параметр типа PChar. Поэтому в вызове функции необходимо явное приведение типа. В то же время преобразование возвращаемого функцией StrLower значения
типа PChar к типу string переменной s производится автоматически.
