Строковый тип StringBuilder определен в пространстве имен System.Text и предназначен для создания строк, значение которых можно изменять. Объекты данного класса всегда создаются с помощью явного вызова конструктора класса, т.е. через операцию new. Создать объект класса StringBuilder возможно одним из следующих способов:
1) //создание пустой строки, размер которой по умолчанию 16 символов
StringBuilder a = new StringBuilder();
2) //инициализация строки и выделение памяти под 4 символа
StringBuilder b = new StringBuilder("abcd");
3) //создание пустой строки и выделение памяти под 100 символов
StringBuilder с = new StringBuilder(100);
4) //инициализация строки и выделение памяти под 100 символов
StringBuilder d = new StringBuilder("abcd", 100);
5) //инициализация подстрокой "bcd", и выделение памяти под 100 символов
StringBuilder d = new StringBuilder("abcdefg", 1, 3,100);
С объектами класса StringBuilder можно работать посимвольно:
using System;
//подключили пространство имен для работы с классом StringBuilder
using System.Text;
namespace Example
{
class Program
{
static void Main()
{
StringBuilder a = new StringBuilder("кол около колокола");
Console.WriteLine("Дана строка: {0}", a);
char b = 'о';
int k = 0;
for (int x = 0; x < a.Length; x++)
{
if (a[x] == b)
{
k++;
}
}
Console.WriteLine("Символ {0} содержится в ней {1} раз", b, k);
}
}
}
|
Результат работы программы:
Дана строка: кол около колокола
Символ о содержится в ней 7 раз
Результат работы программы ничем не отличается от аналогичного примера для работы с типом string. А вот если теперь мы попытаемся заменить в данной строке вес буквы o на точки, то такая проблема, как со строкой типа string, уже не возникнет:
static void Main()
{
StringBuilder a = new StringBuilder("кол около колокола");
Console.WriteLine("Дана строка: {0}", a);
char b = 'о';
char c = '.';
for (int x = 0; x < a.Length; x++)
{
if (a[x] == b)
{
a[x] = c;
}
}
Console.WriteLine("Преобразованная строка: {0}", a);
}
|
Результат работы программы:
Дана строка: кол около колокола
Преобразованная строка: к.л .к.л. к.л.к.ла
Для класса StringBuilder реализованы собственные члены, которые приведены в следующей таблице:
Название |
Член класса |
Описание |
Append |
Экземплярный метод |
Производит добавление данных в конец строки. Разные варианты метода позволяют добавлять в строку величины любых встроенных типов, массивы символов, строки и подстроки string. |
AppendFormat |
Экземплярный метод |
Производит добавление форматированной строки в конец данной строки. |
Capacity |
Свойство |
Позволяет получить и установить емкость буфера. Если устанавливаемое значение меньше текущей длины строки или больше максимального, то генерируется исключение ArgumentOutOfRangeException |
Insert |
Экземплярный метод |
Производит вставку подстроки в заданную позицию |
Length |
Изменяемое свойство |
Возвращает длину строки. Присвоение ему значения 0 сбрасывает содержимое и очищает строку |
MaxCapacity |
Неизменное свойство |
Возвращает наибольшее количество символов, которое может быть размещено в строке |
Remove |
Экземплярный метод |
Производит удаление подстроки из заданной позиции |
Replace |
Экземплярный метод |
Производит замену всех вхождений заданной подстроки или символа новой подстрокой или символом |
ToString |
Экземплярный метод |
Преобразование в строку типа string |
Chars |
Изменяемое свойство |
Позволяет обратиться к элементу строки по его номеру. Вместо него можно пользоваться квадратными скобками []. |
Equals |
Экземплярный метод |
Используется для сравнения значения двух строк - возвращает true, только тогда, когда строки имеют одну и ту же длину и состоят из одних и тех же символов |
CopyTo |
Экземплярный метод |
Копирует подмножество символов строки в массив char |
Рассмотрим примеры использования данных членов класса.
class Program
{
static void Main()
{
StringBuilder str = new StringBuilder("Площадь");
Console.WriteLine("Максимальный объем буфера: {0} \n ", str.MaxCapacity);
Print(str);
str.Append(" треугольника равна");
Print(str);
str.AppendFormat(" {0:f2} см ", 123.456);
Print(str);
str.Insert(8, "данного ");
Print(str);
str.Remove(7, 21);
Print(str);
str.Replace("а", "…");
Print(str);
str.Length = 0;
Print(str);
}
static void Print(StringBuilder a)
{
Console.WriteLine("Строка: {0} ", a);
Console.WriteLine("Текущая длина строки: {0} ", a.Length);
Console.WriteLine("Объем буфера: {0} ", a.Capacity);
Console.WriteLine();
}
}
|
Результат работы программы:
Максимальный объем буфера: 2147483647
Строка: Площадь
Текущая длина строки: 7
Объем буфера: 16
Строка: Площадь треугольника равна
Текущая длина строки: 26
Объем буфера: 32
Строка: Площадь треугольника равна 123,46 см
Текущая длина строки: 37
Объем буфера: 64
Строка: Площадь данного треугольника равна 123,46 см
Текущая длина строки: 45
Объем буфера: 64
Строка: Площадь равна 123,46 см
Текущая длина строки: 24
Объем буфера: 64
Строка: Площ…дь р…вн… 123,46 см
Текущая длина строки: 30
Объем буфера: 64
Строка:
Текущая длина строки: 0
Объем буфера: 64
Все выполняемые действия относились только к одному объекту str. Никаких дополнительных объектов не создавалось. Таким образом, класс StringBuilder применяется тогда, когда необходимо модифицировать исходную строку.
Следует обратить внимание на то, что при увеличении текущей длины строки возможно изменение объема буфера, отводимого для хранения значения строки. А именно, если длина строки превышает объем буфера, то он увеличивается в два раза. Обратное не верно, т.е. при уменьшении длины строки буфер остается неизменным.
Члены класса StringBuilder не содержат методы IndexOf, LastIndexOf, реализованные для класса string. Попробуем разработать их самостоятельно, взяв за основу алгоритм последовательного поиска.
//Метод IndexOf возвращает индекс первого вхождения подстроки str2 в строке str1
//начиная с данной позиции. Если подстрока str2 в строке str1не найдена, то метод
//возвращает -1.
static int IndexOf(StringBuilder str1, StringBuilder str2, int n)
{
int i, j;
for (i = n; i < str1.Length; )
{
if (str1[i] == str2[0])
{
for (j = 1; j < str2.Length && i + j < str1.Length; j++)
{
if (str2[j] != str1[i + j])
{
break;
}
}
if (j == str2.Length)
{
return i;
}
else
{
i++;
}
}
else
{
i++;
}
}
return -1;
}
|
Теперь используя данный метод можно после каждого вхождения подстроки x в строку str вставить подстроку y. Например, это можно сделать с помощью следующего фрагмента программы:
StringBuilder str = new StringBuilder("кол около колокола");
StringBuilder x = new StringBuilder("кол");
StringBuilder y = new StringBuilder("!!!");
int n = IndexOf(str, x, 0);
while (n != -1)
{
str.Insert(n + x.Length, y);
n = IndexOf(str, x, n + x.Length + y.Length);
}
Console.WriteLine(str);
|
Результат работы:
кол!!! окол!!!о кол!!!окол!!!а
На практике часто комбинируют работу с изменяемыми и неизменяемыми строками. В качестве примера рассмотрим решение следующей задачи: дана строка, в которой содержится осмысленное текстовое сообщение. Слова сообщения разделяются пробелами и знаками препинания. Вывести все слова сообщения, которые начинаются и заканчиваются на одну и ту же букву.
static void Main()
{
Console.WriteLine("Введите строку: ");
StringBuilder a = new StringBuilder(Console.ReadLine());
for (int i = 0; i < a.Length;) //удаляем из строк все знаки пунктуации
{
if (char.IsPunctuation(a[i]))
{
a.Remove(i, 1);
}
else ++i;
}
//преобразуем объект StringBuilder к типу string, и разбиваем его на массив слов
string[] s = a.ToString().Split(' ');
Console.WriteLine("Искомые слова: ");
//перебираем все слова в массиве слов и выводим на экран те, которые начинаются и заканчиваются на одну и туже букву
foreach (string str in s)
{
if (str[0] == str[str.Length - 1])
{
Console.WriteLine(str);
}
}
}
|
Результат работы программы:
Введите строку:
кол около колокола, а шалаш у ручья.
искомые слова:
около
а
шалаш
у
|