Не обнаружил проекты, которые используются в примерах в лекции, также не увидел список задач. |
Строки C#. Классы String и StringBuilder
Класс String
В предыдущей лекции мы говорили о символьном типе char и строках постоянной длины, задаваемых массивом символов. Основным типом при работе со строками является тип string, задающий строки переменной длины. Класс String в языке C# относится к ссылочным типам. Над строками - объектами этого класса - определен широкий набор операций, соответствующий современному представлению о том, как должен быть устроен строковый тип.
Объявление строк. Конструкторы класса string
Объекты класса String объявляются как все прочие объекты простых типов - с явной или отложенной инициализацией, с явным или неявным вызовом конструктора класса. Чаще всего, при объявлении строковой переменной конструктор явно не вызывается, а инициализация задается строковой константой. Но у класса String достаточно много конструкторов. Они позволяют сконструировать строку из:
- символа, повторенного заданное число раз;
- массива символов char[] ;
- части массива символов.
Некоторым конструкторам в качестве параметра инициализации можно передать строку, заданную типом 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.
Заметьте, не допускается явный вызов конструктора по умолчанию - конструктора без параметров. Нет также конструктора, которому в качестве аргумента можно передать обычную строковую константу. Соответствующие операторы в тексте закомментированы.
Операции над строками
Над строками определены следующие операции:
- присваивание ( = );
- две операции проверки эквивалентности ( == ) и ( != );
- конкатенация или сцепление строк ( + );
- взятие индекса ( [] ).
Начну с присваивания, имеющего важную особенность. Поскольку string - это ссылочный тип, то в результате присваивания создается ссылка на константную строку, хранимую в "куче". С одной и той же строковой константой в "куче" может быть связано несколько переменных строкового типа. Но эти переменные не являются псевдонимами - разными именами одного и того же объекта. Дело в том, что строковые константы в "куче" не изменяются (о неизменяемости строкового типа будем далее говорить подробно), поэтому когда одна из переменных получает новое значение, она связывается с новым константным объектом в "куче". Остальные переменные сохраняют свои связи. Для программиста это означает, что семантика присваивания строк аналогична семантике значимого присваивания.
В отличие от других ссылочных типов, операции, проверяющие эквивалентность, сравнивают значения строк, а не ссылки. Эти операции выполняются как над значимыми типами.
Бинарная операция " + " сцепляет две строки, приписывая вторую строку к хвосту первой.
Возможность взятия индекса при работе со строками отражает тот приятный факт, что строку можно рассматривать как массив и получать без труда каждый ее символ. Каждый символ строки имеет тип char, доступный только для чтения, но не для записи.
Вот пример, в котором над строками выполняются данные операции:
public void TestOpers() { //операции над строками string s1 ="ABC", s2 ="CDE"; string s3 = s1+s2; bool b1 = (s1==s2); char ch1 = s1[0], ch2=s2[0]; Console.WriteLine("s1={0}, s2={1}, b1={2}," + "ch1={3}, ch2={4}", s1,s2,b1,ch1,ch2); s2 = s1; b1 = (s1!=s2); ch2 = s2[0]; Console.WriteLine("s1={0}, s2={1}, b1={2}," + "ch1={3}, ch2={4}", s1,s2,b1,ch1,ch2); //Неизменяемые значения s1= "Zenon"; //s1[0]='L'; }
Строковые константы
Без констант не обойтись. В C# существуют два вида строковых констант:
- обычные константы, которые представляют строку символов, заключенную в кавычки;
- @-константы, заданные обычной константой c предшествующим знаком @.
В обычных константах некоторые символы интерпретируются особым образом. Связано это прежде всего с тем, что необходимо уметь задавать в строке непечатаемые символы, такие, как, например, символ табуляции. Возникает необходимость задавать символы их кодом - в виде escape-последовательностей. Для всех этих целей используется комбинация символов, начинающаяся символом " \ " - обратная косая черта. Так, пары символов: " \n ", " \t ", " \\ ", " \ "" задают соответственно символ перехода на новую строку, символ табуляции, сам символ обратной косой черты, символ кавычки, вставляемый в строку, но не сигнализирующий о ее окончании. Комбинация " \xNNNN " задает символ, определяемый шестнадцатеричным кодом NNNN. Хотя такое решение возникающих проблем совершенно естественно, иногда возникают неудобства: например, при задании констант, определяющих путь к файлу, приходится каждый раз удваивать символ обратной косой черты. Это одна из причин, по которой появились @-константы.
В @-константах все символы трактуются в полном соответствии с их изображением. Поэтому путь к файлу лучше задавать @-константой. Единственная проблема в таких случаях: как задать символ кавычки, чтобы он не воспринимался как конец самой константы. Решением является удвоение символа. Вот соответствующие примеры:
//Два вида констант s1= "\x50"; s2=@"\x50"""; b1= (s1==s2); Console.WriteLine("s1={0}, s2={1}, b1={2}", s1,s2,b1); s1 = "c:\\c#book\\ch5\\chapter5.doc"; s2 = @"c:\c#book\ch5\chapter5.doc"; b1= (s1==s2); Console.WriteLine("s1={0}, s2={1}, b1={2}", s1,s2,b1); s1= "\"A\""; s2=@"""A"""; b1= (s1==s2); Console.WriteLine("s1={0}, s2={1}, b1={2}", s1,s2,b1);
Взгляните на результаты работы приведенных фрагментов кода, полученные при вызове процедур TestDeclStrings и TestOpers.