logo search
[ТП]Lektsii / Лекции по С#

Класс char[] - массив символов

В языке C# определен класс Char[], и его можно использовать для представления строк постоянной длины, как это делается в С++. Более того, поскольку массивы в C# динамические, то расширяется класс задач, в которых можно использовать массивы символов для представления строк. Так что имеет смысл разобраться, насколько хорошо C# поддерживает работу с таким представлением строк.

Прежде всего, ответим на вопрос, задает ли массив символов C# строку С, заканчивающуюся нулем? Ответ: нет, не задает. Массив char[] - это обычный массив. Более того, его нельзя инициализировать строкой символов, как это разрешается в С++. Константа, задающая строку символов, принадлежит классу String, а в C# не определены взаимные преобразования между классами String и Char[], даже явные. У класса String есть, правда, динамический метод ToCharArray, задающий подобное преобразование. Возможно также посимвольно передать содержимое переменной string в массив символов. Приведу пример:

public void TestCharArAndString()

{

//массивы символов

//char[] strM1 = "Hello, World!";

//ошибка: нет преобразования класса string в класс char[]

string hello = "Здравствуй, Мир!";

char[] strM1 = hello.ToCharArray();

PrintCharAr("strM1",strM1);

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

char[] World = new char[3];

Array.Copy(strM1,12,World,0,3);

PrintCharAr("World",World);

Console.WriteLine(CharArrayToString(World));

}//TestCharArAndString

Закомментированные операторы в начале этой процедуры показывают, что прямое присваивание строки массиву символов недопустимо. Однако метод ToCharArray, которым обладают строки, позволяет легко преодолеть эту трудность. Еще одну возможность преобразования строки в массив символов предоставляет статический метод Copy класса Array.

В нашем примере часть строки strM1 копируется в массив World. По ходу дела в методе вызывается процедура PrintCharAr класса Testing, печатающая массив символов как строку. Вот ее текст:

void PrintCharAr(string name,char[] ar)

{

Console.WriteLine(name);

for(int i=0; i < ar.Length; i++)

Console.Write(ar[i]);

Console.WriteLine();

}//PrintCharAr

Метод ToCharArray позволяет преобразовать строку в массив символов. К сожалению, обратная операция не определена, поскольку метод ToString, которым, конечно же, обладают все объекты класса Char[], печатает информацию о классе, а не содержимое массива. Ситуацию легко исправить, написав подходящую процедуру. Вот текст этой процедуры CharArrayToString, вызываемой в нашем тестирующем примере:

string CharArrayToString(char[] ar)

{

string result="";

for(int i = 0; i< ar.Length; i++) result += ar[i];

return(result);

}//CharArrayToString

Класс Char[], как и всякий класс-массив в C#, является наследником не только класса Object, но и класса Array, и, следовательно, обладает всеми методами родительских классов, подробно рассмотренных в предыдущей главе. А есть ли у него специфические методы, которые позволяют выполнять операции над строками,

представленными массивами символов? Таких специальных операций нет. Но некоторые перегруженные методы класса Array можно рассматривать как операции над строками. Например, метод Copy дает возможность выделять и заменять подстроку в теле строки. Методы IndexOf, LastIndexOf позволяют определить индексы первого и последнего вхождения в строку некоторого символа. К сожалению, их нельзя использовать для более интересной операции - нахождения индекса вхождения подстроки в строку. При необходимости такую процедуру можно написать самому. Вот как она выглядит:

int IndexOfStr( char[]s1, char[] s2)

{

//возвращает индекс первого вхождения подстроки s2 в

//строку s1

int i =0, j=0, n=s1.Length-s2.Length; bool found = false;

while( (i<=n) && !found)

{

j = Array.IndexOf(s1,s2[0],i);

if (j <= n)

{

found=true; int k = 0;

while ((k < s2.Length)&& found)

{

found =char.Equals(s1[k+j],s2[k]); k++;

}

}

i=j+1;

}

if(found) return(j); else return(-1);

}//IndexOfStr

В реализации используется метод IndexOf класса Array, позволяющий найти начало совпадения строк, после чего проверяется совпадение остальных символов. Реализованный здесь алгоритм является самым очевидным, но далеко не самым эффективным.

А теперь рассмотрим процедуру, в которой определяются индексы вхождения символов и подстрок в строку:

public void TestIndexSym()

{

char[] str1, str2;

str1 = "рококо".ToCharArray();

//определение вхождения символа

int find, lind;

find= Array.IndexOf(str1,'о');

lind = Array.LastIndexOf(str1,'о');

Console.WriteLine("Индексы вхождения о в рококо:{0},{1};

", find, lind);

//определение вхождения подстроки

str2 = "рок".ToCharArray();

find = IndexOfStr(str1,str2);

Console.WriteLine("Индекс первого вхождения рок в

рококо:{0}", find);

str2 = "око".ToCharArray();

find = IndexOfStr(str1,str2);

Console.WriteLine("Индекс первого вхождения око в

рококо:{0}", find);

}//TestIndexSym

В этой процедуре вначале используются стандартные методы класса Array для определения индексов вхождения символа в строку, а затем созданный метод

IndexOfStr для определения индекса первого вхождения подстроки. Корректность работы метода проверяется на разных строках. Вот результаты ее работы.

Рис. 13.3. Индексы вхождения подстроки в строку

Существует ли в C# тип char*

В языке C# указатели допускаются в блоках, отмеченных как небезопасные. Теоретически в таких блоках можно объявить переменную типа Char*, но все равно не удастся написать столь же короткую, как в С++, процедуру копирования строк. Правильно считать, что в C# строки типа char* использовать не рекомендуется.

14. Лекция: Строки C#. Классы String и StringBuilder

Класс String

В предыдущей лекции мы говорили о символьном типе char и строках постоянной длины, задаваемых массивом символов. Основным типом при работе со строками является тип string, задающий строки переменной длины. Класс String в языке C# относится к ссылочным типам. Над строками - объектами этого класса - определен широкий набор операций, соответствующий современному представлению о том, как должен быть устроен строковый тип.

Объявление строк. Конструкторы класса string

Объекты класса String объявляются как все прочие объекты простых типов - с явной или отложенной инициализацией, с явным или неявным вызовом конструктора класса. Чаще всего, при объявлении строковой переменной конструктор явно не вызывается, а инициализация задается строковой константой. Но у класса Sring достаточно много конструкторов. Они позволяют сконструировать строку из:

  1. • символа, повторенного заданное число раз;

  2. • массива символов char[];

  3. • части массива символов.

Некоторым конструкторам в качестве параметра инициализации можно передать строку, заданную типом char*. Но все это небезопасно, и подобные примеры приводиться и обсуждаться не будут. Приведу примеры объявления строк с вызовом разных конструкторов:

public void TestDeclStrings()

{

//конструкторы

string world = "Мир";

//string s1 = new string("s1");

//string s2 = new string();

string sssss = new string('s',5);

char[] yes = "Yes".ToCharArray();

string stryes = new string(yes);

string strye = new string(yes,0,2);

Console.WriteLine("world = {0}; sssss={1}; stryes={2};"+

" strye= {3}", world, sssss, stryes, strye);

}

Объект world создан без явного вызова конструктора, а объекты sssss, stryes, strye созданы разными конструкторами класса String.

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