Russian Belarusian English German Japanese Ukrainian

3.385

В C++ Builder тип строк AnsiString реализован как класс, объявленный в файле vcl/dstring.h и аналогичный типу длинных строк в Delphi. Это строки с нулевым символом в конце. При объявлении переменные типа AnsiString инициализируются пустыми строками.
Для AnsiString определены операции отношения ==, !=, >, <, >=, <=. Сравнение производится с учетом регистра. Сравниваются коды символов, начиная с первого, и если очередные символы не одинаковы, строка, содержащая символ с меньшим кодом, считается меньше. Если все символы совпали, но одна строка длиннее и в ней имеются еще символы, то она считается больше, чем более короткая.

Для AnsiString определены операции присваивания =, += и операция склеивания строк (конкатенации) +. Определена также операция индексации []. Индексы начинаются с 1. Например, если S1 = "Привет", то S1[1] вернет 'П', S1[2] вернет 'р' и т.д.

Тип AnsiString используется для ряда свойств компонентов C++ Builder. Например, для таких, как свойства Text окон редактирования, свойства Caption меток и разделов меню и т.д. Этот же тип используется для отображения отдельных строк в списках строк типа TStrings. Таким образом, постоянно имея дело с этими свойствами, вы постоянно работаете с AnsiString.

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

Label1->Caption = Edit1->Text + ' ' + Edit2->Text;

В данном случае в свойстве Label1->Caption отображается текст, введенный пользователем в окне редактирования Edit1, затем записывается символ пробела, а за тем текст, введенный в окне редактирования Edit2. Склеивание строк типа AnsiString легко осуществляется перегруженной операцией сложения "+".

Рассмотренный ниже пример реализует поиск в строке S1 фрагмента, заданного строкой S2, и замену его текстом строки S3. Код, осуществляющий эти операции, может иметь вид:

AnsiString S1, S2, S3; // операторы занесения текста в S1, S2, S3
int i = S1.Pos(S2);
if(i) Label1->Caption = S1.substring(1,i-1) + S3 + S1.substring(i+S2.Length(),255);
else Label1->Caption = "Текст не найден";

В этом коде использован ряд функций-элементов класса AnsiString: Pos, SubString, Length. Обратите внимание на то, что доступ к ним осуществляется операцией точка (.), вместо более привычной в C++ Builder операции доступа к методам компонентов стрелка (->). Дело в том, что к методам компонентов доступ осуществляется через указатель на объект, а в данном случае к методам AnsiString доступ осуществляется через сами объекты - строки.

Первый выполняемый оператор приведенного кода использует функцию Pos. Эта функция ищет в строке, к которой она применена (в нашем случае в S1), первое вхождение подстроки, заданной ее параметром (в нашем случае S2). Если поиск успешный, функция возвращает индекс первого символа найденного вхождения подстроки. Индексы начинаются с 1. Если подстрока не найдена, возвращается 0.

Следующий оператор с помощью структуры if...else проверяет, не равно ли нулю (false) возвращенное функцией Pos значение. Если не равно, то производится формирование строки с заменой найденной подстроки. Строка формируется склеиванием трех строк: начальной части строки S1, расположенной до найденного вхождения подстроки, строки S3, заменяющей найденное вхождение, и заключительной чисти строки S1, расположенной после найденного вхождения. Для получения фрагментов строки S1 использована функция SubString. Эта функция возвращает подстроку, начинающуюся с символа в позиции, заданной первым параметром функции, и содержащую число символов, не превышающее значение, заданное вторым параметром функции. Таким образом, выражение S1.SubString(1, i-1) возвращает подстроку строки S1, начинающуюся с первого символа и содержащую i-1 символов, т.е. часть строки S1, расположенную до найденного вхождения подстроки S2. Аналогично, выражение S1.SubString(i+S2.Length(), 255) возвращает подстроку строки S1, расположенную после найденного вхождения подстроки S2. При этом для определения начала этой подстроки использована функция Length, возвращающая число символов в строке (в нашем случае в строке S2, содержащей заменяемый фрагмент). В приведенном выражении в качестве второго параметра функции SubString задано число 255, которое, как ожидается, превышает длину подстроки. В действительности будет возвращено менее 255 символов, столько, сколько имеется до завершающего S1 нулевого символа.

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

int i = S1.Pos(S2);
S1 = S1.substring(1,i-1) + S3 + S1.substring(i+S2.Length(),255);

Подобная задача для строк (char *) была бы более сложной и потребовала бы объявления дополнительного буфера для временного хранения формируемой строки.

Пусть в строке S1 надо заменить все вхождения S2 на строку S3. Эту задачу можно было бы решить следующим кодом:

int iO = 0, i = S1.Pos(S2);
while(i)
{
S1 = S1.substring(1,i + iO - 1) + S3 + S1.substring(i + iO + S2.Length(), 255);
iO += i - 1 + S3.Length();
i = S1.substring(iO + 1, 255).Pos(S2);
}

Приведенный код мало отличается от рассмотренного ранее и не содержит каких-то новых функций. Основные отличия заключаются в следующем. Во-первых, вводится переменная iO - индекс, предшествующий первому символу еще не обработанной части строки S1. Значение iO изменяется после обработки очередной части строки. Во-вторых, очередное вхождение строки S2 в S1 определяется не по всей строке S1, а только по ее еще не обработанной части:

S1.SubString(iO + 1, 255).

Рассмотренную задачу контекстного поиска и замены в строке можно было бы решить иначе, воспользовавшись функциями Delete и Insert класса AnsiString.

Функция Delete удаляет из строки, начиная с позиции, заданной первым параметром функции, число символов, заданное вторым параметром функции.

Функция Insert вставляет в строку подстроку, заданную первым параметром функции, в позицию, заданную вторым параметром функции.

Применение этих функций позволяет выполнить контекстную замену с помощью, например, следующего кода:

int iO = 1, i = S1.Pos(S2);
while (i > iO)
{
S1.Delete(i, S2.Length()); // удаление вхождения S2
S1.Insert(S3,i); // вставка S3
iO = i + S3.Length();
i = iO - 1 + S1.substring(iO, 255).Pos(S2);
}

Выше приведено применение только малой части методов, имеющихся в классе AnsiString. В заключение отметим только метод, позволяющий переходить от типа AnsiString к типу (char *). Несмотря на то, что применение AnsiString практически всегда удобнее (char *), такие переходы приходится делать при передаче параметров в некоторые функции, требующие тип параметра (char *). Чаще всего это связано с вызовом функций API Windows или функций C++ Builder, инкапсулирующих такие функции. Например, функция Application->MessageBox, требующая в качестве двух своих первых параметров (сообщения и заголовка окна) тип (char *). Аналогичные преобразования требуются для функции PlaySound для передачи в нее имени файла и для многих других функций.

Преобразование строки AnsiString в строку (char *) осуществляется функцией c_str() без параметров, возвращающей строку с нулевым символом в конце, содержащую текст той строки AnsiString, к которой она применена. Например, если есть строки S1 и S2 типа AnsiString, которые нужно передать в функцию Application->MessageBox в качестве сообщения и заголовка окна, то вызов Application->MessageBox может иметь вид:

Application->MessageBox(S1.c_str(), S2.c_str(), MB_OK);

Возможно и обратное преобразование строки (char *) в строку AnsiString. Для этого используется функция:

AnsiString(char *S)

которая возвращает строку типа AnsiString, содержащую текст, записанной в строке S, являющейся аргументом функции.

Если заметили ошибку, выделите фрагмент текста и нажмите Ctrl+Enter

  Комментарии

0 favicon 26.06.2019 23:24 #1
Спасибо за полезный материал))

Добавить комментарий


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