Строки в С#
11.Console.WriteLine( "ж - буква" );
12.if( Char.IsNumber( x3 ) )
13.Console.WriteLine( "7 - цифра" );
14.}
15.}
16.}
Запускаем программу и видим, кого «признают за своих» статические методы
IsWhiteSpace(), IsLetter() и IsNumber() (см. рис. 4).
Рисунок 4: Результат работы программы Листинг 4
Итак, служебный управляющий символ \n трактуется как пробельный (white space), ну а символы ' ж' и '7' трактуются, естественно, как буква и цифра, соответственно. Имеется также иметодIsLetterOrDigit(), одинаково «приветствующий» и буквы, ицифры.
2 Массивы типа char и строки языка С#
Поскольку одиночные переменные типа char удобны для хранения символов (в смысле, UNICODE-кодовсимволов), томассивы элементов типа char пригодны для хранения наборов символов, в роли которых могут выступать слова естественного языка (иллюстрируем все для русскогоязыка) и сочетания слов изнаков препинания:
Листинг 5.
1.namespace string_app
2.{
3.class Program
4.{
5.static void Main(string[] args)
6.{
7. |
char[] myT = { 'П', 'р', 'и', 'в', 'е', 'т', ',', ' ', 'М', 'и', 'р', |
|
|
'!' }; |
|
8. |
Console.WriteLine( "Слова как массив символов"); |
|
9. |
Console.WriteLine( "------------------------- |
"); |
10.foreach( char el in myT )
11. |
Console.Write( "{0}", el ); |
12.Console.WriteLine();
13.}
14.}
15.}
Данная программа, создав массив myT с элементами типа char, хранящими символы 'П',
7
Строки в С#
'р', 'и', 'в', 'е', 'т', ',', ' ', 'М', 'и', 'р', '!' затем в цикле с помощью метода
Write() библиотечного класса Console выводит в консольное окно фразу "Привет, Мир!", что ипоказанонарис. 5.
Использованный в Листинге 5 метод Write() библиотечного класса Console, в отличие от постоянно нами применяющегося метода WriteLine(), автоматического перевода строки не осуществляет, в результате чего буквы из фразы "Привет, Мир!" располагаются в одной и той же физическойстрокеконсольногоокна(что итребовалось получить).
Рисунок 5
Хранение фраз естественного языка в массивах типа char [ ] открывает потенциально неограниченные возможности их обработки, из которых мы сейчас, не мудрствуя лукаво, выберемпростейшую задачу ореверсированиибукв в тексте:
Листинг 6.
1.namespace string_app
2.{
3.class Program
4.{
5.static void Main(string[] args)
6.{
7. |
char[] myT = { 'П', 'р', 'и', 'в', 'е', 'т', ',', ' ', 'М', 'и', 'р', |
|
|
'!' }; |
|
8. |
Console.WriteLine( "Строка в обратном порядке" ); |
|
9. |
Console.WriteLine( "------------------------- |
" ) ; |
10./*-----------------------------*/
11.Array.Reverse( myT );
12./*-----------------------------*/
13.foreach( char el in myT )
14.Console.Write( "{0}", el );
15.Console.WriteLine();
16.}
17.}
18.}
Реверсирование фразы, содержащейся в массиве символов тут, в языке С# легко выполняется с помощью известного нам метода Reverse() библиотечного класса Array (см. выше Листинг 6), в то время как в языке С нам пришлось для этого писать собственную функция ReversePhrase ().
8
Строки в С#
Рисунок 6
Как видно из рис. 6 метод Reverse() из фразы "Привет, Мир!" сделал анаграмму "! риМ , тевирП".
В целом можно констатировать, что имитировать работу с фразами естественных языков при помощи символьных массивов (массивов элементов типа char) вполне возможно. Однако, как и в языке С, имеется принципиальная возможность упростить такого рода работу. Вспоминаем, что в языке С для этого вводится соглашение о терминальном нуле, послечеготакие специфическиемассивы элементов типа char называются строками языка С, и еще дополнительно предоставляется богатый набор строковых библиотечных функций. Кроме того, строки языка С «подкрепляются» специальными строковыми константами, представляющими из себя текст, заключенный с двухсторонв двойныекавычки:
"Hello, world" или "Something else"
итак далее.
В языке С# пошли намного дальше и помимо строковых констант подкрепили строковый тип данных этого языка базированием на библиотечном классе String, определённом в пространстве имён System.
Итак, строкиязыка С# - этофактически объекты класса String.
Являясь встроенным типом языка С#, строки имеют и свой индивидуальный синтаксис, жёстко закреплённый в языке.
Например, вместо имени библиотечного класса String можно (и желательно) использовать ключевое слово string (фактически, это синоним для имениString).
Вот пример того, как в языке С# можно создать строку на базе существующего массива типа char [ ]:
1.char [ ] myT ={ 'П' , 'р' , 'и' , 'в' , 'е' , 'т' };
2.string str = new string( myT );
Как и в случае любых классов языка С# здесь идентификатором str обозначена ссылка на объект типа String, память под который выделяется операцией new. Допустимость показанной формы создания строк обуславливается наличием в классе String конструктора,
9
Строки в С#
принимающего в качестве параметра массив типа char [ ].
Обязательно стоит отметить, что в классе String конструктор поумолчанию не определён, ипоэтому в языке С# припопытке создать строку следующимобразом:
string str = new string( ); // error
возникает ошибкакомпиляции.
Строки языка С# являются чрезвычайно важным, можно сказать инфраструктурным типом данных, и поэтому для них в синтаксисе языка предусмотрены всякого рода упрощающие исключения (это делается даже для строк языков C/C++), являющиеся отклонением от синтаксиса создания классовыхобъектов в языке С#.
Самым важным таким исключением (упрощением), чаще всего применяемым на практике, является следующая формасоздания строк
string str = "Привет";
использующая строковую константу, и не использующая операцию new. При этом str по- прежнему имеет смысл ссылки на объект типа String в памяти компьютера. Всюду далее в нашей лекции мы для упрощения будем говорить о переменной str как о строке, так как точный смысл вам теперь должен быть уже полностью ясен. Например, вам наверняка понятно, что оператор
string str;
никакой реальной строки текста не создаёт, а лишь ссылку на тип string. И только в результатепоследующегооператора
str = "Привет";
(без явного использования операции new) ссылка str принимает и хранит адрес объекта типа String в памяти компьютера (этот объект и содержит в себе текст "Привет").
Применение строковых констант и операции «=» для строк языка С# более чем характерно:
string str = "Привет";
str = str + ", " + "Мир" + "!";
Из этого примера, формирующего для строки str значение "Привет, Мир!", прекрасно видно, что для класса String перегружаются операции «=» и «+», так что работа со строками языка С# становится простой и удобной. Можно даже ещеукоротить запись представленного фрагмента, если воспользоваться перегруженной операцией комбинированного (составного)
10
Строки в С#
присваивания «+=»:
string str = "Привет"; str += ", " + "Мир" + "!
Но самое главное, конечно, что мы при этом вообще не думаем про размеры буферов в памяти, что в языке С является серьезнейшей проблемой в работе со строками, чреватой, помимо прочего, возникновением трудноуловимых ошибок, связанных с выходом за границу буферов итяжелыми последствиями во время работы программы.
Уже во время изучения массивов языка С# мы узнали, что выход за границу массива не дает столь же тяжелых последствий во время работы программы, как это бывает в программах на языке С, ибо здесь классовая природа массивов обеспечивает генерацию исключений.
Но классовая природа строк языка С# позволяет продвинуться еще дальше - здесь даже проблемы выхода за границы буферов невозникает, так как объекты класса String динамически управляют своими внутренними буферами, осуществляя во время работы программы их увеличение в случае необходимости.
При этом всегда можно запросить строку str на предмет ее длины (количества содержащихся в ней символов в UNICODE-кодировке) с помощью выражения str.Length. Это может пригодиться, например, в программе, гдеуже сформированную строку «разбирают» на отдельные символы:
Листинг 7.
1.namespace string_app
2.{
3.class Program
4.{
5.static void Main(string[] args)
6.{
7.string strl = "Привет";
8.string str2 = new string( '3', 2 );
9.strl += "," + str2;
10.int len = strl.Length;
11.for( int i = 0; i < len; ++i )
12.{
13.char ch = strl[i];
14.Console.WriteLine( "Символ на {0} позиции есть {1}",i, ch );
15.}
16.}
17.}
18.}
Результат разборастроки strl насоставляющиееесимволы показаннарис. 7.
11
Строки в С#
Рисунок 7
В Листинге 7 можно обратить внимание на следующие два момента. Во-первых, доступ к отдельным символам строки с помощью операции индексации (операции «[]») осуществляется в режиме «по чтению», то есть с его помощью нельзя заменять символы строки.
Во-вторых, из содержимого строки strl, показанного на рис. 7, становится понятно, как работает конструктор
string str2 = new string( '3', 2 );
Этот конструктор формирует строку, повторяя заданный символ (первыйпараметр) заданноечислораз (второйпараметр).
Ну и, наконец, строки можно формировать не только конструкторами класса String или на основе строковых констант, но и с помощью их ввода с клавиатуры. В принципе, мы с этим уже знакомы, нолишний наглядный примернепомешает:
Листинг 8
1. |
namespace string_app |
|
1. |
{ |
|
2. |
class Program |
|
3. |
{ |
|
4. |
static void Main(string[] args) |
|
5. |
{ |
|
6. |
string strl = Console.ReadLine(); |
/*!*/ |
7. |
string str2 = Console.ReadLine(); |
/*2*/ |
8. |
string str3 = strl + "\n" + str2; |
/*3*/ |
9. |
Console.WriteLine( str3 ); |
|
10. |
} |
|
11. |
} |
|
12. }
Здесь показаны три новых момента. Во-первых, это анонсированный выше ввод значений строк языка С# с клавиатуры (физические строки /*1*/-/*2*/ Листинга 8). Во-вторых, показано, что «складывать» можно не только одни лишь строки между собой, но и строки с отдельными символами (строка /*3*/ кодапрограммы).
А в-третьих, в Листинге 8 продемонстрирован вызов метода WriteLine() с единственным
12
