PString — Тип Delphi


Содержание

Чем отличается тип String в Delphi2 и выше от аналогичного в Delphi1

Delphi , Синтаксис , Типы и Переменные

B D2 и выше на самом деле используется тип LongString вместо String, а стаpый тип тепеpь обзывается ShortString (о чем, кстати, написано в help). Из того же help можно узнать, что указатель LongString указывает на nullterminated string и потому возможно обычное пpиведение типа LongString к PChar (о чем я и написал), котоpое сводится пpосто к смене вывески. Там же можно узнать, что длина стpоки хpанится в dword пеpед указателем. Есть также намек на то, что пpи пpисваивании дpугой стpоке инфоpмация не копиpуется, а увеличивается только счетчик ссылок. Более подpобную инфоpмацию можно почеpпнуть из system.pas:

От себя добавлю:

Сама пеpеменная LongString указывает на байт, непосpедственно следующий за этой пpоцедуpой, там же находится собственно значение стpоки. Значение » (пустая стpока) пpедставляется как указатель nil, кстати, поэтому сpавнение str=» это быстpая опеpация.

Тепеpь подpобнее о счетчике ссылок. Я уже говоpил, что пpи пpисваивании копиpования не пpоисходит, а только увеличивается счетчик. Когда он уменьшается? Hу, очевидно, когда в pезультате опеpации значение стpоки меняется, то для стаpого значения счетчик уменьшается. Это понятно. Более непонятно, когда освобождаются значения, на котоpые ссылаются поля некого класса. Это пpоисходит в System. TObject.FreeInstance пpи вызове _FinalizeRecord, а инфоpмация беpется из vtInitTable (кстати, здесь же очищаются Variant). Ещё более непонятно, когда освобождаются пеpеменые String, котоpые описаны как локальные в пpоцедуpах/функциях/методах. Здесь pаботает компилятоp, котоpые вставляет эти неявные опеpации в код этой функции.

Тепеpь о типе PString. Hа самом деле пеpеменные этого типа указывают на такие же значения, как и LongString, но для пеpеменных этого типа для всех опеpаций по созданию/копиpованию/удалению нужно помнить об этих самых счетчиках ссылок. Иногда без этого типа не обойтись. Вот опеpации для этого типа (sysutils.pas):

Можно отметить, что явно задать использование long strings можно декларацией

Хотелось бы также предупредить наиболее частные ошибки при использовании длинных строк:

  • Если Вы передаёте указатель PChar на буфер, взятый от длинной строки, в функцию, которая может изменить содержание буфера, то убедитесь, что на этот буфер указывает только одна строка. Это верно в случаях сложения строк, вызова UniqueString или SetLength и некоторых других;
  • Если Вы используете длинные строки как аргументы или результаты для функций, располагающихся в DLL, то в DLL надо использовать модуль ShareMem;
  • Не используйте длинные строки как члены структур типа record. Используйте там короткие строки или array[0..n] of char. Также нельзя использовать в структурах типа record динамические массивы. Данные ограничения отсутствуют для классов.

Статья Чем отличается тип String в Delphi2 и выше от аналогичного в Delphi1 раздела Синтаксис Типы и Переменные может быть полезна для разработчиков на Delphi и FreePascal.

Комментарии и вопросы

Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.

String Types in Delphi (Delphi For Beginners)

As with any programming language, in Delphi, variables are placeholders used to store values; they have names and data types. The data type of a variable determines how the bits representing those values are stored in the computer’s memory.

When we have a variable that will contain some array of characters, we can declare it to be of typeString.
Delphi provides a healthy assortment of string operators, functions and procedures. Before assigning a String data type to a variable, we need to thoroughly understand Delphi’s four string types.

Short String

Simply put, Short String is a counted array of (ANSII) characters, with up to 255 characters in the string. The first byte of this array stores the length of the string. Since this was the main string type in Delphi 1 (16 bit Delphi), the only reason to use Short String is for backward compatibility.
To create a ShortString type variable we use:

The s variable is a Short string variable capable of holding up to 256 characters, its memory is a statically allocated 256 bytes. Since this is usually wasteful — unlikely will your short string spread to the maximum length — second approach to using Short Strings is using subtypes of ShortString, whose maximum length is anywhere from 0 to 255.

This creates a variable called ssmall whose maximum length is 50 characters.

Note: When we assign a value to a Short String variable, the string is truncated if it exceeds the maximum length for the type. When we pass short strings to some Delphi’s string manipulating routine, they are converted to and from long string.

String / Long / Ansi

Delphi 2 brought to Object Pascal Long String type. Long string (in Delphi’s help AnsiString) represents a dynamically allocated string whose maximum length is limited only by available memory. All 32-bit Delphi versions use long strings by default. I recommend using long strings whenever you can.

The s variable can hold from zero to any practical number of characters. The string grows or shrinks as you assign new data to it.

We can use any string variable as an array of characters, the second character in s has the index 2. The following code

assigns T to the second character os the s variable. Now the few of the first characters in s look like: TTe s str. .
Don’t be mislead, you can’t use s[0] to see the length of the string, s is not ShortString.

Reference counting, copy-on-write

Since memory allocation is done by Delphi, we don’t have to worry about garbage collection. When working with Long (Ansi) Strings Delphi uses reference counting. This way string copying is actually faster for long strings than for short strings.
Reference counting, by example:

When we create string s1 variable, and assign some value to it, Delphi allocates enough memory for the string. When we copy s1 to s2, Delphi does not copy the string value in memory, it only increases the reference count and alters the s2 to point to the same memory location as s1.

To minimize copying when we pass strings to routines, Delphi uses copy-on-write technique. Suppose we are to change the value of the s2 string variable; Delphi copies the first string to a new memory location, since the change should affect only s2, not s1, and they are both pointing to the same memory location.

Wide String

Wide strings are also dynamically allocated and managed, but they don’t use reference counting or the copy-on-write semantics. Wide strings consist of 16-bit Unicode characters.

About Unicode character sets

The ANSI character set used by Windows is a single-byte character set. Unicode stores each character in the character set in 2 bytes instead of 1. Some national languages use ideographic characters, which require more than the 256 characters supported by ANSI. With 16-bit notation we can represent 65,536 different characters. Indexing of multibyte strings is not reliable, since s[i] represents the ith byte (not necessarily the i-th character) in s.

If you must use Wide characters, you should declare a string variable to be of the WideString type and your character variable of the WideChar type. If you want to examine a wide string one character at a time, be sure to test for multibite characters. Delphi doesn’t support automatic type conversions betwwen Ansi and Wide string types.

Null terminated

A null or zero terminated string is an array of characters, indexed by an integer starting from zero. Since the array has no length indicator, Delphi uses the ASCII 0 (NULL; #0) character to mark the boundary of the string.
This means there is essentially no difference between a null-terminated string and an array[0..NumberOfChars] of type Char, where the end of the string is marked by #0.

We use null-terminated strings in Delphi when calling Windows API functions. Object Pascal lets us avoid messing arround with pointers to zero-based arrays when handling null-terminated strings by using the PChar type. Think of a PChar as being a pointer to a null-terminated string or to the array that represents one. For more info on pointers, check:Pointers in Delphi.

For example, The GetDriveType API function determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive. The following procedure lists all the drives and their types on a users computer. Place one Button and one Memo component on a form and assign an OnClick handler of a Button:

Mixing Delphi’s strings

We can freely mix all four different kinds of strings, Delphi will give it’s best to make sense of what we are trying to do. The assignment s:=p, where s is a string variable and p is a PChar expression, copies a null-terminated string into a long string.

Character types

In addition to four string data types, Delphi has three character types: Char, AnsiChar, and ​WideChar. A string constant of length 1, such as ‘T’, can denote a character value. The generic character type is Char, which is equivalent to AnsiChar. WideChar values are 16-bit characters ordered according to the Unicode character set. The first 256 Unicode characters correspond to the ANSI characters.

PString — Тип Delphi

В выражениях Delphi поддерживает три физических строковых формата: короткий (ShortString), длинный (LongString) и широкий (WideString). Их можно комбинировать в операторах присваивания и выражениях (все необходимые преобразования Delphi выполняет автоматически).
Переменные типов AnsiString и WideString — это динамически распределяемые массивы символов, максимальная длина которых ограничивается только наличием памяти. Разница между ними состоит в том, что в AnsiString знаки записываются в формате char, а в WideString— в формате WideChar. Обычно вполне достаточно одного типа AnsiString, однако при работе с международными наборами символов, такими как UNICODE, удобнее использовать WideString.
Тип ShortString—это, по существу, массив Array [0..255] of char. Первый его элемент задает динамическую длину строки, которая может принимать значения от 0 до 255 символов. Символы, составляющие строку, занимают места от 1 до 255. Тип ShortString предназначен, в основном, для обеспечения совместимости с ранними версиями Delphi и Borland Pascal.
Логический строковый тип именуется просто String. Отнесение его к типу AnsiString или ShortString задается командой $Н. По умолчанию задается < $Н+>, и String совпадает с AnsiString. Если задать команду <$Н- >, то String будет совпадать с ShortString и иметь максимальную длину, равную 255 символам.
Для совместимости с другими языками программирования в Delphi поддерживается класс строк с конечным нулем. Зарезервированных слов или идентификаторов для этого класса не существует.
Строки с конечным нулем состоят из ненулевых символов и оканчиваются символом с порядковым номером 0 (#0). В отличие от типов AnsiString, ShortString и WideString, строки с нулевым окончанием не имеют указателя длины. Конец в этих стооках обозначается нулем.
Физически строки с нуль-окончанием подобны массивам символов с нумерацией элементов от нуля, наподобие array [ 0 . . X] of char, где Х — некоторое положительное целое, большее нуля, хотя никаких объявлении подобного рода не происходит. Вместо этого определяется переменная-указатель PChar и распределяется необходимый объем памяти. При необходимости строке AnsiString можно присвоить тип PChar.
В табл. 1.7 перечислены некоторые процедуры и функции обработки данных строковых типов.

Совет: Программисты, работающие на С, привыкли записывать все строки в массивы с нуль-окончанием. Фактически они применяют в выражениях не строковые переменные, а указатели на них. Программисты, работающие на Basic, привыкли использовать строку как одно целое. Для типа AnsiString из Delphi годятся оба подхода.

Работа со строками в Delphi 10.3 Rio

Работа со строками в Delphi — это отдельная и очень обширная тема. Рассмотреть в одной статье все тонкости и особенности строк delphi представляет собой достаточно сложную задачу сравнимую, наверное, с написанием небольшой книги, просто по причине того, что в Delphi на сегодняшний день используются разные типы строк (ShortString, AnsiString, UnicodeString и прочие) и каждый тип для чего-то да нужен — для обратной совместимости, для COM BSTR, для разработки под мобильные платформы и так далее.

Вместе с этим, Delphi постоянно развивается, что-то добавляется, что-то улучшается и вот уже те инструменты работы со строками в Delphi, которые вызывали недоумение своим появлением, например, в Delphi 2009 в Delphi 10.3 Rio начинают играть другими красками. На написание этой статьи меня подтолкнула статья « What’s New » для Delphi 10.3 Rio, а именно то, что разработчики Delphi отдельным пунктом выделили, что давным давно существующий в Delphi класс TStringBuilder оптимизирован и даже обзавелся перегруженным методом ToString использование которого может увеличить производительность. Вот я и решил проверить — на сколько же выросла производительность TStringBuilder в Delphi по сравнению с тем, что было в далеком 2008 году, когда не было ни поддержки мобильных платформ, ни x64 с Linux.

Справка по TStringBuilder

TStringBuilder — это специализированный класс для работы со строками в Delphi (аналог класса StringBuilder в .NET Framework).

TStringBuilder поддерживает выполнение таких операций со строками как конкатенация (сложение), поиск, заменена и вставка подстрок. При этом, массив символов может быть запрошен по индексу или преобразован в строку для сравнения.

На массив символов можно ссылаться напрямую, используя свойство Chars. Свойство Length содержит текущую длину массива символов.

Работать с классом TStringBuilder в Delphi достаточно просто:

Обратить внимание стоит на то, что TStringBuilder работает с 0-индексированными (0-based) строками — первый символ имеет индекс 0, а не 1, как мы привыкли в Delphi. В остальном же, работа с TStringBuilder основана на использовании следующих методов:

Append — добавить подстроку к строке (конкатенация строк). Метод перегружен поэтому, Вы можете добавлять к строке числа, массивы символов и другие типы, например так:

Insert — вставить подстроку в строку с заданной позиции (метод также перегружен)

Replace — заменить подстроку (или символ) на другую строку (символ). Заменяет все вхождения подстрок.

CopyTo — копирование части строки в строку-приемник.

В Delphi 10.3 Rio TStringBuilder обзавелся также перегруженным методом ToString:

По сообщению разработчиков Delphi, ToString (True) даст лучшую производительность, если больше не ожидается никаких изменений для TStringBuilder, поскольку это уменьшает объем копируемых данных.

Со всеми методами TStringBuilder можно ознакомиться в справке Delphi.

Меня же больше интересует насколько TStringBuilder стал более производительным в части конкатенации строк по сравнению с обычной (привычной, классической) операцией сложения?

Вводные для теста производительности TStringBuilder

Итак, что у меня имеется для тестирования TStringBuilder:

Стационарный компьютер имеет следующие характеристики:

  • Процессор Intel Core i5 8400 (6-ти ядерный)
  • ОЗУ: 16 ГБ
  • ОС: Windows 10 x64

Смартфон LG Q7+ (Android 8.1.0)

Модель процессора MediaTek MT6750S
Частота процессора 1.5 ГГц
Кол-во ядер процессора 8
Оперативная память 3 ГБ

Проверять будем конкатенацию (сложение) строк Delphi в следующем порядке:

  1. Проверяем скорость сложения строк с использованием метода Append TStringBuilder
  2. Проверяем обычное сложение строк (Str1+Str2)
  3. Проверяем скорость сложения строк с использованием метода Append TStringBuilder и вывод строки обновленным методом ToString(True).

Все три проверки буду проводить на всех доступных устройствах.

Приложение для тестирование производительности TStringBuilder

Версия для ОС Windows

Внешний вид приложения для теста производительности TStringBuilder в Windows:

Каждую операцию сложения строк будем повторять по десять раз и результаты теста выводить в TStringGrid.

Код обработчика OnClick:

Результаты теста TStringBuilder в Windows

Тестирование сложение двух строк

  • Строка 1: edStr1
  • Строка 2: edStr2
  • Количество сложений: 30 000 000
# TStringBuilder Классика TStringBuilder.ToString(True)
1 234 483 165
2 249 527 163
3 197 482 155
4 206 495 157
5 186 503 155
6 185 503 162
7 188 499 155
8 188 519 155
9 187 478 155
10 208 537 154

Прибавление к строке одного символа

  • Строка 1: edStr1
  • Строка 2: a
  • Количество сложений: 30 000 000
# TStringBuilder Классика TStringBuilder.ToString(True)
1 149 314 124
2 149 318 128
3 137 332 207
4 122 312 123
5 121 311 123
6 146 312 173
7 130 327 124
8 122 315 124
9 122 317 123
10 122 312 123

Как можно видеть из представленных результатов TStringBuilder при сложении строк оказывается практически вдвое быстрее, чем обычная операция сложения, чего ранее за этим классом не наблюдалось при работе в Windows — ранее время, затрачиваемое на операцию сложения было практически одинаковым или, как в свое время проверял Marco Cantu — TStringBuilder оказывался намного медленнее.

Версия для ОС Android

Внешний вид приложения для тестирования TStringBuilder:

Исходный код программы тот же, что и в версии для Windows с одним лишь исключением — результаты теста будут выводиться в обычный Memo:

Результаты теста TStringBuilder на LG Q7+

Тестирование сложение двух строк

  • Строка 1: edStr1
  • Строка 2: edStr2
  • Количество сложений: 1 000 000


# TStringBuilder Классика TStringBuilder.ToString(True)
1 302 849 232
2 233 847 221
3 231 830 221
4 230 828 224
5 230 831 221
6 238 829 227
7 230 821 221
8 230 821 221
9 230 838 223
10 238 822 228

Прибавление к строке одного символа

  • Строка 1: edStr1
  • Строка 2: a
  • Количество сложений: 1 000 000
# TStringBuilder Классика TStringBuilder.ToString(True)
1 302 776 221
2 221 774 218
3 221 775 219
4 221 776 218
5 221 772 218
6 221 773 218
7 221 773 219
8 221 773 219
9 221 773 219
10 221 772 218

Опять же, как можно видеть по результатам тестирования, TStringBuilder ускоряет работу по сложению двух строк примерно в 2,5 раза, при этом, новый метод ToString(True) дает незначительное ускорение по сравнению с обычным ToString.

Резюмируем

На рисунке ниже представлено среднее время сложения двух строк в Windows.

  1. Синий столбик — сложение двух строк
  2. Оранжевый — прибавление к строке одного символа

То де самое, но уже для Android:

Представленные выше диаграммы наглядно демонстрируют рост производительности TStringBuilder при работе со строками в Delphi 10.3 Rio как в Windows, так и в Android. Между тем, новые метод TStringBuilder.ToStrng(True) дает незначительный прирост производительности по сравнению с ранее существующим методом ToString.

Таким образом, если в вашем приложении Delphi часто приходится иметь дело со строками, то, думаю, что имеет смысл обратит внимание на работу с TStringBuilder вне зависимости от того в какой операционной системе вы работаете.

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

Исходники обоих тестовых приложений можно скачать со страницы:

Property Lines: TStrings. Непонятки

а теперь интересное. SetLines не отрабатывает. т.е. Сообщение не показывается, хотя значение FLines меняется.

еще более интересное, это если объявить процедуру так

без реализации, FLines все равно меняется.

но самое интересное, если свойство объявить так

FLines все равно меняется.

где я что упустил в понимании свойств? ведь в реализации того же Мемо из коробки именно так и сделано: через SetLines

Добавлено через 1 минуту
при использовании класса я естественно обращаюсь к свойству, а не к полю

Добавлено через 1 минуту
изначальная задача была: проверить в SetLines равенство значения FLines и значения Value и предпринять неоходимые действия, а затем обнаружилось, что не работает.

Добавлено через 11 минут
мои рассуждения: поскольку свойство является классом (указателем по сути), при обращении к свойству мы получаем ссылку на объект TStrings в памяти и работаем с ним, поскольку в самом объекте не запрещено изменять свойство. тогда возникают вопросы:
1. Почему в реализации исходников сделано через SetLines, если эта процедура вообще не нужна?
2. Как следствие первого, как проверить «входящее» значение списка на равенство с уже существующим в FLines?

Добавлено через 1 час 15 минут
WTF!
Почему SetLines срабатывает, если при использовании объекта делать не так

Добавлено через 1 час 10 минут
забыл добавить: Delphi XE2

Работа со строками в Delphi 10.1 Berlin

Автор: Alex. Опубликовано в Программирование 31 Январь 2020 . просмотров: 23141

Для работы со строками в последних версиях Delphi разработчикам доступно большое количество функций, помимо которых ещё есть помощники для работы со строками, такие как TStringHelper, TStringBuilder и TRegEx. Во всём этом разнообразии бывает сложно найти нужную функцию. Я попытался разобраться, что есть в Delphi 10.1 Berlin для работы со строками и как этим всем пользоваться.

Итак, прежде чем начнём разбираться с функциями, замечу, что начиная с Delphi XE3, появился помощник TStringHelper, и теперь работать со строками можно как с записями. Т.е., если вы определили переменную со строкой (на картинке снизу – это myStr), то вы можете поставить точку и посмотреть, какие функции доступны. Это очень удобно.

Кстати аналогичные помощники появились и для работы с типами Single, Double и Extended: TSingleHelper, TDoubleHelper и TExtendedHelper.

Ну и конечно, помимо помощника TStringHelper, никуда не делся класс TStringBuilder, который используется для работы со строкой как с массивом, и который является полностью совместимым с .NET классом StringBuilder.

А для работы с текстовыми документами незаменимым окажется класс TRegEx, который является обёрткой над библиотекой PCRE, позволяющий использовать регулярные выражения для поиска, замены подстрок и расщепления текста на части.

Все приведённые в статье примеры сделаны с помощью Delphi 10.1 Berlin, поэтому в других версиях Delphi их работа не гарантируется.

Вот основные моменты, которые мы рассмотрим в статье:

Строки в Delphi

В последних версиях Delphi тип string, обозначающий строку, является псевдонимом встроенного типа System.UnicodeString. Т.е. когда вы объявляете переменную str: string, то автоматически вы объявляете переменную типа UnicodeString.

Кстати, на платформе Win32 вы можете использовать директиву « », которая превратит тип string в ShortString. С помощью этого способа вы можете использовать старый 16-битный код Delphi или Turbo Pascal в ваших проектах.

Обратите внимание, что кроме типа UnicodeString и ShortString в Delphi есть и другие типы строк, такие как AnsiString и WideString, однако дальше в статье мы будем рассматривать только работу со строками типа string.

Более глубокое изучение строк в Delphi вы можете начать с прочтения документации здесь.

Инициализация строк

Конечно, начнём мы с инициализации строк. Итак, рассмотрим объявление переменной с типом string.

В этой строчке кода мы объявляем переменную s с типом string, т.е., как было написано выше, по умолчанию с типом UnicodeString. Объявленные переменные с типом UnicodeString, в которые не присвоено значение, всегда гарантированно содержат строку нулевой длины. Чтобы теперь в переменной s была нужная нам строка, нужно просто присвоить переменной другое значение, например:

Это самый простой и часто используемый способ инициализации. Кроме этого есть ряд полезных функций, которые пригодятся вам для инициализации строк в некоторых ситуациях (здесь и далее я буду давать полный код проекта консольного Win32 приложения):

Изменение регистра

Для изменения регистра строк в Delphi есть функции LowerCase, UpperCase, TStringHelper.ToLower, TStringHelper.ToUpper, TStringHelper.ToLowerInvariant и TStringHelper.ToUpperInvariant. В нижний регистр строки меняют функции LowerCase, TStringHelper.ToLower и TStringHelper.ToLowerInvariant, остальные – в верхний. Обратите внимание, что функции LowerCase и UpperCase не работают с кириллицей. Функции TStringHelper.ToUpperInvariant и TStringHelper.ToLowerInvariant всегда работают независимо от текущей пользовательской локали. Вот примеры использования функций:

Конкатенация строк

Здесь конечно самый простой вариант – это использование оператора +. Но есть и другие варианты, например, функция Concat. А если вам нужно в цикле добавлять в конец одной строки большое количество других строк, то здесь пригодится метод Append класса TStringBuilder. Вот пример использования перечисленных способов:

Во всех четырёх переменных, после выполнения нашей программы, будет следующая строка: «Абвгдеёжзиклмнопрст». Четвёртый способ выглядит более громоздким, но у такого способа есть три преимущества. Во-первых, при большом количестве конкатенаций этот способ даст выигрыш по времени по сравнению с первыми тремя способами. Во-вторых, при создании объекта TStringBuilder вы сразу можете задать нужный размер массива для хранения строки, если он конечно известен. Это тоже даст выигрыш по времени. В-третьих, функция Append принимает на вход не только строки, но и другие типы, такие как Integer и Single, автоматически преобразуя их в строку.

Третий способ удобно использовать, если нужно сложить строки, находящиеся в массиве или списке. К тому же здесь первым параметром можно задать строку-разделитель, которая будет вставлена между строками, взятыми из массива. Вот пример, в котором формируется строка со списком городов, разделённых запятыми:

В результате выполнения этой функции получится строка «Москва, Санкт-Петербург, Севастополь».

Вставка подстроки в строку

Для того чтобы вставить внутрь строки подстроку вы можете использовать процедуру Insert или функцию TStringHelper.Insert. У класса TStringBuilder тоже есть аналогичная функция. Кстати, функция TStringBuilder.Insert, кроме строк умеет вставлять и другие типы, такие как Integer и Single, автоматически преобразуя их в строку. Вот пример использования:

Обратите внимание, в процедуре Insert нумерация символов начинается с 1, а в функциях TStringHelper.Insert и TStringBuilder.Insert – с 0. Все приведённые способы меняют строку, хранящуюся в переменной.

Удаление части строки

Допустим, вам нужно удалить из строки часть символов. Здесь нам помогут процедура Delete и функция TStringHelper.Remove. У класса TStringBuilder тоже есть функция Remove. Вот примеры использования:

Во всех трёх способах из строки «Абвгд» получится строка «Агд». Обратите внимание, что в процедуре Delete нумерация символов начинается с 1, а в функциях Remove – с 0.

Также интересно, что функция TStringHelper.Remove не трогает исходную строку. Вместо этого она возвращает новую строку с удалёнными символами. Именно поэтому мы присваиваем результат обратно в переменную. Процедура Delete работает по-другому: она меняет исходную строку.

Помимо приведённых здесь вариантов, для удаления части строки можно использовать функции замены подстроки, просто для этого искомая подстрока заменяется на пустую, например, StringReplace(str1, substr1, »).

Копирование части строки

Здесь идёт речь о том, что часть длиной строки нужно скопировать в новую строку или массив символов. Для этого в Delphi есть функции LeftStr, RightStr, Copy, TStringHelper.Substring и TStringHelper.CopyTo. А в классе TStringBuilder – только функция CopyTo. Есть также функция MidStr в юните System.StrUtils, которая работает аналогично функции Copy, поэтому в примере её не будет.

Первые два способа копируют часть строки слева (функция LeftStr) или справа (RightStr). Остальные четыре способа подходят, как для копирования части строки слева или справа, так и из середины.

В способах 3-6 из примера мы получим сроку «вгд» или массив [‘в’, ‘г’, ‘д’]. Обратите внимание, что в функциях Copy и MidStr нумерация символов начинается с 1, а во всех остальных с 0. Исходная строка или массив символов во всех четырёх способах не меняется.

Сравнение строк

Конечно, сравнивать строки можно с помощью операторов =, , >= и <>. Но кроме этого существуют ещё много функций: StrComp, StrIComp, StrLComp, StrLIComp, CompareStr, CompareText, TStringHelper.Compare, TStringHelper.CompareOrdinal, TStringHelper.CompareTo, TStringHelper.CompareText, SameStr, SameText, TStringHelper.Equals и TStringBuilder.Equals. Функции SameText, StrIComp, CompareText, TStringHelper.CompareText и TStringHelper.Compare умеют производить регистронезависимое сравнение строк, остальные функции и операторы — регистрозависимое.

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

Самая продвинутая здесь функция – это TStringHelper.Compare. С помощью неё можно сравнивать не только целые строки, но и части строк. Здесь можно настроить зависимость от регистра, включить игнорирование символов и знаков препинания или сравнение цифр как чисел и т.д.

Операторы, а также функции TStringHelper.Equals и TStringBuilder.Equals, в результате сравнения, отдадут вам True, если условие верно, и False, если условие не верно. Функции CompareStr, CompareText, TStringHelper.Compare, TStringHelper.CompareTo, TStringHelper.CompareOrdinal и TStringHelper.CompareText работают по-другому. Они сравнивают строки с точки зрения сортировки. Функции возвращают отрицательное число, если строка, указанная в первом параметре, сортируется до строки, указанной во втором параметре, положительное число — если первая строка сортируется после второй и 0 – если строки равны.

Функции SameStr, SameText, TStringHelper.Equals и TStringBuilder.Equals сравнивают строки на соответствие.

Итак, вот примеры использования вышеперечисленных функций и операторов:

Поиск подстроки в строке

Теперь давайте посмотрим, как можно найти подстроку (определённую последовательность символов) в строке. Здесь у вас есть большой выбор функций, которые возвращают либо индекс найденной подстроки, либо true или false в зависимости от того, найдена подстрока в строке или нет. Итак, давайте перечислим все функции для поиска подстроки:

В первую очередь – это функция Pos, которая ищет подстроку, начиная с указанного номера символа. Функция осуществляет регистрозависимый поиск. Здесь нумерация символов начинается с 1. Если подстрока найдена, то возвращается номер первого символа найденной подстроки, иначе – 0. Есть также функция PosEx (в юните System.StrUtils), которая работает абсолютно также. Вот пример использования функции Pos:

Аналогично функции Pos работают и функции IndexOf и LastIndexOf помощника TStringHelper. Они также осуществляют регистрозависимый поиск. Функция IndexOf ищет подстроку (или символ) с начала и до конца строки, а функция LasIndexOf – наоборот, т.е. с конца и до начала. Если подстрока найдена, то функции возвращают индекс первого символа найденной подстроки в строке. Здесь нумерация символов начинается с 0. Если подстрока не найдена, то функции возвращают -1. Также при поиске вы можете задать начало и интервал поиска. Вот примеры использования этих функций:

Теперь рассмотрим функции для проверки, есть ли подстрока в строке, и не важно, в каком месте. Для этого есть функции ContainsStr и ContainsText в юните System.StrUtils, а также функция Contains в помощнике TStringHelper.Contains. Функции ContainsStr и TStringHelper.Contains – регистрозависимые, а функция ContainsText – нет. Вот примеры использования этих функций:

Дополнительно есть функции проверяющие, наличие определённой подстроки в начале или в конце текста. Это функции StartsStr, StartsText, EndsStr и EndsText в юните System.StrUtils, а также функции StartsWith, EndsWith и EndsText у помощника TStringHelper. Функции StartsStr и EndsStr регистрозависимые, функции StartsText, EndsText и TStringHelper.EndsText регистронезависимые, а у функций TStringHelper.StartsWith и TStringHelper.EndsWith есть второй параметр для выбора режима поиска. Учтите, что регистронезависимый поиск в функции TStringHelper.StartsWith работает только с буквами латинского алфавита. По умолчанию поиск в функциях TStringHelper.StartsWith и TStringHelper.EndsWith регистрозависимый.

Обратите внимание, что регистронезависимый поиск в функциях StartsText, EndsText и TStringHelper.EndsText и TStringHelper.EndsWith ведётся для текущей локали. Т.е. если на компьютере будет установлена английская локаль, то регистронезависимый поиск по русскому тексту работать не будет.

Вот примеры использования функций:

И конечно самые продвинутые условия для поиска подстрок можно задавать при помощи регулярных выражений. Для этого есть функции TRegEx.Match и TRegEx.Matches. Вот несколько примеров использования этих функций:

Примеры и описание регулярных выражений смотрите на сайте библиотеки PCRE.

Поиск символов в строке

Случается, что нужно найти определённые символы в строке. Конечно, для этого вы можете воспользоваться функциями для поиска подстроки, о которых было написано выше, но есть и специальные функции, позволяющие найти первый попавшийся в строке символ из нескольких искомых. Это функции помощника TStringHelper: IndexOfAny, IndexOfAnyUnquoted и LastIndexOfAny. Функции IndexOfAny и IndexOfAnyUnquoted ищут, перебирая символы сначала до конца строки, а функция LastIndexOfAny – наоборот. Во всех функциях можно указать интервал поиска. Функция IndexOfAnyUnquoted умеет игнорировать символы, заключенные в кавычки, скобки и т.п. Вот пример использования этих функций:

Замена подстроки в строке

Для поиска и замены подстроки (или символа) в строке можно использовать функции StringReplace, ReplaceStr и ReplaceText, TStringHelper.Replace, TStringBuilder.Replace и TRegEx.Replace. Функции ReplaceStr и TStringBuilder.Replace – регистрозависимые, функция ReplaceText – регистронезависимая, в функциях StringReplace, TStringHelper.Replace и TRegEx.Replace зависимость от регистра настраивается флажком rfIgnoreCase. Функции TRegEx.Replace ищут подстроку, используя регулярные выражения. В функции TStringBuilder.Replace можно задать диапазон поиска подстроки. Вот примеры использования этих функций:

Обрезка пробелов и управляющих символов

Для такой часто встречающейся операции, как удаление пробелов и управляющих символов в начале и в конце строки, есть несколько функций: Trim, TrimLeft, TrimRight, TStringHelper.Trim, TStringHelper.TrimLeft и TStringHelper.TrimRight. При вызове функций TStringHelper.Trim, TStringHelper.TrimLeft и TStringHelper.TrimRight вы можете перечислить, какие символы нужно удалять. Вот пример использования этих функций:

Выравнивание текста за счёт установки пробелов

И напоследок ещё пара интересных функций, которые умеют дополнять строку пробелами или другими символами, пока она не станет нужной длины. Это функции TStringHelper.PadLeft и TStringHelper.PadRight. С помощью этих функций, например, для лучшего восприятия можно добавить пробелы в начало чисел, которые вы выдаёте столбиком в консоли или дополнить числа ведущими нулями. Вот пример использования этих функций:

Вместо заключения

Итак, в статье я постарался собрать все возможные функции Delphi, которые постоянно нужны при работе со строками. Надеюсь, вы найдёте в этой статье что-то новое и интересное для себя. Если я упустил что-то важное на ваш взгляд, просьба не держать это в себе, а написать об этом в комментариях.

Строковый тип (String)

Операции со строковыми переменными

Название Aeyrwbz Описание Пример
Copy Copy ( Source : string; StartChar, Count : Integer ) : string; Возвращает строку состоящую из указанных в Count количестве символов, начиная с StartChar символа.


Если до конца строки меньше символов, чем указано в Count, то копируются все символы, начиная с StartChar и до конца строки.
Первый символ строки имеет индекс = 1.

Copy(Text, 3, 4); Delete Delete ( var Source : string; StartChar : Integer; Count : Integer ); Процедура Delete удаляет последовательность символов вплоть до символа Count из строки источника, начиная с позиции StartChar. Процедура вырезает символы из строки и после этого сдвигает символы справа на их место.

Ошибка не произойдет, если Count превышает реальную длину строки.
Первый символ строки = 1.

Delete(Text, 3, 4) Trim function Trim ( const Text : String ) : String; Функция Trim удаляет пробельные и управляющие символы (такие как перевод строки) в начале и в конце строки. Trim(Text) TrimLeft function TrimLeft ( const Text : String ) : String; Функция TrimLeft удаляет пробельные и управляющие символы (такие как перевод строки) в начале строки. TrimLeft(Text) TrimRight TrimRight ( const Text : String ) : String; Функция TrimRight удаляет пробельные и управляющие символы (такие как перевод строки) в конце строки. TrimRight(Text) Pos Pos(const Needle, HayStack : string): Integer; Функция Pos находит позицию одной строки Needle в другой строке HayStack.

Если строка не найдена, возвращается 0.
Поиск чувствителен к регистру.

Pos(Word, Text) Concat Concat(const String1 <,String2 . >: string): string; Функция Concat соединяет несколько строк в одну результирующую строку, смотри пример.

Она эквивалентна оператору +, который быстрее.

Concat(Text1,’ and ‘,Text2); StringReplace StringReplace(const SourceString, OldPattern, NewPattern: string; Flags: TReplaceFlags): string; Заменяет первое или все вхождения подстроки OldPattern в SourceString строкой NewPattern в соответствии с настройками Flags:

rfReplaceAll : Заменяет все вхождения;
rfIgnoreCase : игнорирует регистр при поиске.

StringReplace(Text, ‘Word1’, ‘Word2’, [rfReplaceAll, rfIgnoreCase]); AnsiReplaceStr AnsiReplaceStr(const HayStack, Needle, NewNeedle: string): string; Функция AnsiReplaceStr заменяет все вхождения строки Needle в строку Haystack строкой NewNeedle.

Это команда чувствительна к регистру.

AnsiReplaceStr(Text, ‘Word1’, ‘Word2’); StuffString StuffString(const Source: string; Start, Length: Cardinal; const SubString: string): string; Функция StuffString вставляет SubString (дополнительную строку) в другую строку, заменяя Length символов, начиная с позиции Start.

Если длина равна -1, то строка просто вставляется, не заменяя никаких символов.

3.3.1. Виды строк в Delphi

3.3.1. Виды строк в Delphi

Для работы с кодировкой ANSI в Delphi существует три вида строк: AnsiString , ShortString и PChar . Различие между ними заключается в способе хранения строки, а также выделения и освобождения памяти для нее. Зарезервированное слово string по умолчанию означает тип AnsiString , но если после нее следует число в квадратных скобках, то это означает тип ShortString , а число — ограничение по длине. Кроме того, существует опция компилятора Huge strings (управляется также директивами компилятора <$H+/->и <$LONGSTRINGS ON/OFF>, которая по умолчанию включена, но если ее выключить, то слово string станет эквивалентно ShortString ; или, что то же самое, string[255] . Эта опция введена для обратной совместимости с Turbo Pascal, в новых программах отключать ее нет нужды. Внутреннее устройство этих типов данных иллюстрирует рис. 3.2.

Рис. 3.2. Устройство различных строковых типов Delphi

Наиболее просто устроен тип ShortString . Это массив символов с индексами от 0 до N, где N — число символов, указанное при объявлении переменной (в случае использования идентификатора ShortString N явно не указывается и равно 255). Нулевой элемент массива хранит текущую длину строки, которая может быть меньше или равна объявленной (эту длину мы будем далее обозначать M), элементы с индексами от 1 до M — это символы, составляющие строку. Значения элементов с индексами M+1..N не определены. Все стандартные функции для работы со строками игнорируют эти символы. В памяти такая переменная всегда занимает N+1 байтов.

Ограничения типа ShortString очевидны: на хранение длины отводится только один байт, поэтому такая строка не может содержать больше 255 символов. Кроме того, такой способ записи длины не совпадает с принятым в Windows, поэтому ShortString несовместим с системными строками.

В системе приняты так называемые нуль-терминированные строки: строка передается указателем на ее первый символ, длина строки отдельно нигде не хранится, признаком конца строки считается встретившийся в цепочке символов #0 . Длина таких строк ограничена только доступной памятью и способом адресации (т. е. в Windows теоретически это 4 294 967 295 символов). Для работы с такими строками предусмотрен тип PChar . Переменная такого типа является указателем на начало строки. В литературе нередко можно встретить утверждение, что PChar = ^Сhar , однако это неверно: тип PChar встроен в компилятор и не выводится из других типов. Это позволяет выполнять с ним операции, недопустимые для других указателей. Во-первых, если P — переменная типа PChar , то допустимо обращение к отдельным символам строки с помощью конструкции P[N] , где N — целочисленное выражение, определяющее номер символа (в отличие от типа ShortString , здесь символы нумеруются с 0, а не с 1). Во-вторых, к указателям типа PChar разрешено добавлять и вычитать целые числа, смещая указатель на соответствующее число байтов вверх или вниз (здесь речь идет только об операторах «+» и «-«; адресная арифметика с помощью процедур Inc и Dec доступна для любых типизированных указателей, а не только для PChar ).

При работе с PChar программист целиком и полностью отвечает за выделение памяти для строки и за ее освобождение. Именно это и служит основным источником ошибок у новичков: они пытаются работать с такими строками так же, как и с AnsiString , надеясь, что операции с памятью будут выполнены автоматически. Это очень грубая ошибка, способная привести к самым непредсказуемым последствиям.

Хотя программист имеет полную свободу выбора в том, как именно выделять и освобождать память для нуль-терминированных строк, в большинстве случаев самыми удобными оказываются специально предназначенные для этого функции StrNew , StrDispose и т. п. Их преимущество заключается в том, что менеджер памяти выделяет чуть больше места, чем требуется для хранения строки, и в эту дополнительную память записывается, сколько байтов было выделено. Благодаря этому функция StrDispose удаляет ровно столько памяти, сколько было выделено, даже если в середину выделенного блока был записан символ #0 , уменьшающий длину строки.

Компилятор также позволяет рассматривать статические массивы типа Char , начинающиеся с нулевого индекса, как нуль-терминированные строки. Такие массивы совместимы с типом PChar , что позволяет обойтись без использования динамической памяти при работе со строками.

Тип AnsiString объединяет достоинства типов ShortString и PChar : строки имеют фактически неограниченную длину, заботиться о выделении памяти для них не нужно, в их конец автоматически добавляется символ #0 , что делает их совместимыми с системными строками (впрочем, эта совместимость не абсолютная; как и когда можно использовать AnsiString в функциях API, мы рассматривали в разд. 1.1.13.).

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

Счетчик ссылок позволяет реализовать то, что называется copy-on-demand, копирование по необходимости. Если у нас есть две переменные S1 , S2 типа AnsiString , присваивание вида S1:= S2 не приводит к копированию всей строки. Вместо этого в указатель S1 копируется значение указателя S2 , а счетчик ссылок строки увеличивается на единицу. В дальнейшем, если одну из этих строк потребуется модифицировать, она сначала будет скопирована (а счетчик ссылок оригинала, естественно, уменьшен) и только потом изменена, чтобы это не затрагивало остальные переменные.

Далее мы рассмотрим, какие проблемы могут возникнуть при использовании строк разного вида.

PString — Тип Delphi

Работа со строками Delphi позволяет извлечь из строки необходимую информацию и представить её в нужном виде. Система предоставляет весь спектр необходимых функций для работы со строками Delphi и преобразования строк Delphi в необходимые форматы:

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

Непосредственно сами строки Delphi поддерживают единственную операцию, так называемую операцию конкатенации, то есть присоединения. Несмотря на «научное» название, операция конкатенации выполняет очень простую процедуру. С помощью операции конкатенации одна строка присоединяется к другой:

Результирующая строка S будет суммой двух слагаемых строк. Длина строки, то есть количество символов в строке, возвращается встроенной функцией

function Length(S: String): Integer;

Delphi работает со строками типа String, в котором длина строки записывается в начале строки, перед первым символом. Поэтому индекс первого символа в строке не 0, а 1. То есть, если:

S:=’Строка типа String’;

то S[1] — символ ‘С’, S[2] — символ ‘т’ , последний символ в строке — S[Length(S)], равный ‘g’.

Однако часто приходится иметь дело со строками типа PChar, которые использует операционая система Windows. В строках типа PChar длина строки определяется специальным символом конца строки — #0. Поэтому для использования функций Windows тип String необходимо предварительно переводить в тип PChar. Преобразование типа String в тип PChar выполняет функция

function PChar(S: String): PChar;

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

Функции преобразования в числовой формат и обратно

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

функция IntToStr(N: Integer): String
Преобразует целое число N в строку.
функция StrToInt(S: String): Integer
Преобразует строку S в целое число.
функция FloatToStr(X: Extended): String
Преобразует число с плавающей точкой X в строку.
функция StrToFloat(S: String): Extended
Преобразует строку S в число с плавающей точкой.

Процедуры и функции преобразования дат и времени

Сначала собственно функции, предоставляющие информацию о текущих дате и времени:

функция Now: TDateTime
Возвращает текущую дату и время.
функция Date: TDateTime
Возвращает текущую дату.
функция Time: TDateTime
Возвращает текущее время.

Далее, функции, работающие с составляющими даты и времени (год, месяц, число, день недели, часы, минуты, секунды и даже миллисекунды):

функция DayOfWeek(Date: TDateTime): Integer
Возвращает текущий номер дня недели: 1 — воскресенье, 7 — суббота.
процедура DecodeDate(Date: TDateTime; var Year, Month, Day: Word)
Разбивает дату Date на год — Year, месяц — Month и день — Day.
процедура DecodeTime(Time: TDateTime; var Hour, Min, Sec, MSec: Word)
Разбивает время Time на час — Hour, минуты — Min, секунды — Sec и миллисекунды — MSec.
функция EncodeDate(Year, Month, Day: Word): TDateTime
Объединяет год — Year, месяц — Month и день — Day в значение типа TDateTime.
функция EncodeTime(Hour, Min, Sec, MSec: Word): TDateTime
Объединяет час — Hour, минуты — Min, секунды — Sec и миллисекунды — MSec в значение типа TDateTime.

Наконец, собственно, функции, переводящие дату и время из формата TDateTime в строчный формат:

функция DateTimeToStr(DateTime: TDateTime): String
Преобразует дату и время DateTime в строку.
функция DateToStr(Date: TDateTime): String
Преобразует дату Date в строку.
функция TimeToStr(Time: TDateTime): String
Преобразует время Time в строку.

Следующие функции работают с параметрами возвращаемой строки. Функции с приставкой Ansi работают в том числе и с кириллическими символами. Если символы в строках предполагаются исключительно латинские, то можно использовать аналогичные функции, но без приставки Ansi:

функция AnsiLowerCase(const S: String): String
Возвращает строку S, преобразованную к нижнему регистру.
функция AnsiUpperCase(const S: String): String
Возвращает строку S, преобразованную к верхнему регистру.
функция Length(const S: String): Integer
Возвращает количество символов в строке S.
функция Trim(const S: String): String
Удаляет из строки S начальные и завершающие пробелы и управляющие символы.
функция TrimLeft(const S: String): String
Удаляет из строки S начальные пробелы и управляющие символы.
функция TrimRight(const S: String): String
Удаляет из строки S завершающие пробелы и управляющие символы.

Следующие функции сравнивают две строки между собой:

функция AnsiCompareStr(const S1, S2: String): Integer
Сравнивает две строки S1 и S2 с учётом регистра символов.
Возвращает значение 0 если S1>S2
функция AnsiCompareText(const S1, S2: String): Integer
Сравнивает две строки S1 и S2 без учёта регистра символов.
Возвращает значение 0 если S1>S2

Следующие функции осуществляют поиск в текущей строке подстроки, вставляют, удаляют или заменяют подстроку:

функция Pos(Substr: String; Str: String): Integer
Возвращает позицию (индекс) первого вхождения Substr в строке Str. Если Substr нет в Str, возвращает 0.
функция Insert(Source: String; var S: String; Index: Integer): Integer
Вставляет строку Source в строку S, начиная с номера символа, равного Index
процедура Delete(var S: String; Index, Count: Integer)
Удаляет из строки S подстроку, начинающуюся с номера символа, равного Index, и содержащую до Count символов.
функция StringReplace(const S, OldPattern, NewPattern: string; Flags: TReplaceFlags): String
Заменяет в строке S подстроку OldPattern на строку NewPattern с учётом флага TReplaceFlags. Для работы с этой функцией нужно создать переменную типа TReplaceFlags — это множество, и включить в него одно или оба значения из следующих:
rfReplaceAll — будут заменены все вхождения. Если это значение не будет включено во множество, то будет заменено только первое вхождение;
rfIgnoreCase — замена будет без учёта регистра символов. Если это значение не будет включено во множество, то замена будет чувствительна к регистру символов.

Наконец, функция копирования части строки:

функция Copy(S: String; Index, Count: Integer): String
Возвращает подстроку строки S, начиная с номера символа, равного Index и содержащую до Count символов.

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

function RealToStr(X: Real; Count: Integer): String; //Count — количество цифр после запятой
var S: String;
N: Integer;
begin
S:=FloatToStr(X); //после запятой — длинная последовательность цифр
//DecimalSeparator — константа, содержащая истинный разделитель целой и дробной частей числа N:=Pos(DecimalSeparator, S); //позиция запятой в строке
//вычисляем длину строки с нужным количеством знаков после запятой:
if N=0 //если в строке нет запятой — это целое число, и
then N:=Length(S) //тогда просто выводим это число
else N:=N+Count; //иначе вычисляем длину строки
Result:=Copy(S, 1, N); //копируем часть строки в результат
end;

Или вот, к примеру, текст модуля, обеспечивающего ввод в компонент Edit только чисел.

Справочник по компонентам Delphi. Часть 1
Страница 3. Класс TStrings

Класс TStrings

Многофункциональный класс, предназначенный для хранения текстовых строк и связанных с ними объектов (любых потомков TObject). TStrings — абстракт­ный класс; он только описывает методы работы с наборами строк и сопут­ствующих им объектов, но как именно они хранятся, на его уровне не опре­делено. Его потомки очень многочисленны; они играют основную роль в компонентах-списках (TListBox, TComboBox), редакторе (TMemo) и других. Так что вам чаще всего придется иметь дело с TStrings как со свойством одного из компонентов. В дальнейшем экземпляры этого класса и порожденных от него классов мы-будем называть наборами строк. Для создания собственных наборов строк вне компонентов предназначен потомок TStrings — TStringList, который будет рассмотрен ниже.

К строкам и объектам соответственно можно получить доступ через свойства:

Первое из них является векторным свойством, принимаемым по умолчанию. Общее количество пар в списке равно значению свойства:

Класс TStrings также предназначен для хранения пар вида ‘параметр=значение’, например, в файлах инициализации (.INI). Эту возможность реализует следу­ющее свойство:

При обращении к этому свойству для чтения ищется строка, содержащая подстроку (параметр) Name и символ ‘=’. Если она найдена, возвращается то, что находится в этой строке после ‘=’. Если нет, ValuesfName] равно пустой строке. При записи: если строка, содержащая параметр Name, найдена — ее значение после ‘=’ заменяется новым значением, если нет — строка добавля­ется. Если существующему параметру присваивается пустая строка (Valu-es[Name] := «;), то он удаляется из набора строк.

Методы класса приведены в таблице:

procedure BeginUpdate; procedure EndUpdate;

Пара процедур, которые устанавливают и сбрасывают флаг обновления набора. Между ними, для ускорения работы, нужно заключать все операции по копи­рованию, удалению и т. д. большого количества элементов.

Осуществляет полную очистку набора.

procedure Insert(Index: Integer; const S: string);

Вставляет строку S под индексом Index.

procedure Delete(Index: Integer);

Удаляет строку с индексом Index.

function IndexOf(const S: string): Integer;

Возвращает индекс (номер в наборе) строки S. Если она не найдена, функция возвращает -1.

function IndexOfObject(AObject: TObject): Integer;

Возвращает индекс объекта в наборе. В случае неудачи возвращает -1.

function Equals(Strings: TStrings): Boolean;

Сравнивает строки вызвавшего его объекта со строками объекта Strings и возвращает True в случае равенства (сравниваются число строк и все строки попарно).

function Add(const S: string): Integer-

Добавляет строку S в конец набора и в случае успеха возвращает присвоенный ей индекс (он должен быть равен значению Count до добавления строки).

function AddObject(const S: string; AObject: TObject): Integer;

Добавляет строку в паре с объектом. Возвращает то же, что и метод Add.

procedure Exchange(Indexl, Index2: Integer);

Меняет местами пары строка+объект с индексами Indexl и Index2.

procedure Move(Curlndex, Newlndex: Integer);

Перемещает пару строка+объект с позиции Curlndex в позицию Newlndex.

procedure InsertObject(Index: Integer; const S: string; AObject: TObject);

Вставляет объект AObject и соответствую­щую ему строку S в набор под индексом Index.

Шесть методов предназначены для экспорта/импорта наборов строк:

б) в файл (создавая поток и вызывая два предыдущих метода):

procedure LoadFrornFile (const FileName: strings-procedure SaveToFile(const FileName: string);

в) в данные в формате текстового редактора (подряд расположенные строки, оканчивающиеся парой символов CR/LF (16-ричные коды SOD/SOA)).

procedure AddScrings(Strings: TStrings! ;

Добавляет в конец набора другой набор Strings.

procedure Assign!Source: T’Persisier-t l ;

Уничтожает прежнее содержимое набора и подставляет вместо него Source, если источник имеет тип TStrings. В противном случае возникает исключительная ситуа­ция EConvertError.

выгружает строки в единый массив, где они разделены парами символов CR/LF; в конце такого массива ставится нулевой байт. Размер массива не может превышать 65520 байт; поэтому строки выгружаются до тех пор, пока их суммарная длина не превосходит этого значения.

читает строки из массива Text.Строки в массиве должны быть отделены друг от друга парой символов CR/LF; допускается и один символ LF (16-ричный код $ОА). Символы с кодами 0, $lA(+) воспринимаются как конец текста. При этом прежнее содержимое набора уничтожается.

Илон Маск рекомендует:  Вывод текста
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL