- •7. Лекция: Символы и строки
- •Общий взгляд
- •Класс char
- •Класс char[] - массив символов
- •Существует ли в c# строки типа char*
- •Класс String
- •Объявление строк. Конструкторы класса string
- •Операции над строками
- •Строковые константы
- •Неизменяемый класс string
- •Статические свойства и методы класса string
- •Метод Format
- •Методы Join и Split
- •Динамические методы класса string
- •Класс StringBuilder - построитель строк
- •Объявление строк. Конструкторы класса StringBuilder
- •Операции над строками
- •Основные методы
- •Емкость буфера
- •Архитектура Решения
- •Алгоритмы и задачи
- •Проекты
- •Поиск и Сортировка
- •Линейный поиск
- •Поиск с барьером
- •Бинарный поиск
- •Сортировка
- •Методы сортировки за время порядка o(n2)
- •Сортировка SortMin (SortMax)
- •Сортировка SortMinMax
- •Сортировка SortBubble (SortBall)
- •Сортировка SortShaker
- •Сортировка SortInsert - сортировка вставками
- •Сортировка SortShell - улучшенный вариант сортировки вставками
- •Проекты
- •Рекурсивные методы сортировки за время порядка o(n*log2(n))
- •Сортировка за линейное время
- •Задача "Красные и белые"
- •Задача Дейкстры "о голландском национальном флаге"
- •Задача Гарри Поттера "Сортировочная шляпа"
- •Сортировка массивов с элементами m типов
- •Сортировка черпаками
- •Проекты
-
Класс char
В C# есть символьный класс char, основанный на классе System.Char и использующий двухбайтную кодировку Unicode представления символов. Для этого типа в языке определены символьные константы - символьные литералы. Константу можно задавать:
-
символом, заключенным в одинарные кавычки;
-
escape-последовательностью;
-
Unicode-последовательностью, задающей Unicode код символа.
Вот несколько примеров объявления символьных переменных и работы с ними:
/// <summary>
/// Символы, коды, строки
/// </summary>
public void TestChar()
{
char ch1='A', ch2 ='\x5A', ch3='\u0058';
char ch = new Char();
int code; string s;
ch = ch1;
//преобразование символьного типа в тип int
code = ch; ch1=(char) (code +1);
//преобразование символьного типа в строку
//s = ch;
s = ch1.ToString()+ch2.ToString()+ch3.ToString();
Console.WriteLine("s= {0}, ch= {1}, code = {2}",
s, ch, code);
}//TestChar
Три символьные переменные инициализированы константами, значения которых заданы тремя разными способами. Переменная ch объявляется в объектном стиле, используя new и вызов конструктора класса. Тип char, как и все типы C#, является классом. Этот класс наследует свойства и методы класса object и имеет большое число собственных методов.
Существуют ли преобразования между классом char и другими классами? Явные или неявные преобразования между классами char и string отсутствуют, но, благодаря методу ToString, переменные типа char стандартным образом преобразуются в тип string. Поскольку у каждого символа есть свой код, существуют неявные преобразования типа char в целочисленные типы, начиная с типа ushort. Обратные преобразования целочисленных типов в тип char также существуют, но они уже явные.
В результате работы процедуры TestChar строка s, полученная сцеплением трех символов, преобразованных в строки, имеет значение BZX, переменная ch равна A в латинском алфавите, а ее код - переменная code - 65. Хотя преобразования символа в код и обратно просты, полезно иметь процедуры, выполняющие взаимно-обратные операции, - получение по коду символа и получение символа по его коду:
/// <summary>
/// Код символа
/// </summary>
/// <param name="sym">символ</param>
/// <returns>его код</returns>
public static int SayCode(char sym)
{
return sym;
}//SayCode
/// <summary>
/// Символ
/// </summary>
/// <param name="code">Код символа</param>
/// <returns>символ</returns>
public static char SaySym(int code)
{
return (char)code;
}// SaySym
В первой процедуре преобразование к целому типу выполняется неявно. Во второй - преобразование явное.
Говоря о символах и их кодировке, следует помнить, что для символов алфавитов естественных языков (латиницы, кириллицы) применяется плотная кодировка. Это означает, что поскольку буква z в латинице следует за буквой y, код z на единицу больше кода y. Только буква "Ё" в кириллице не подчиняется этому правилу. Для цифр также используется плотная кодировка, и их коды предшествуют кодам букв. Заглавные буквы в кодировке предшествуют строчным. Ряд символов воспринимаются как управляющие, выполняя при их появлении определенное действие. К подобным относятся такие символы, как "перевод строки" (new line), "возврат каретки" (carriage return), "звонок". Эти символы не имеют видимого образа, а их коды задаются escape последовательностями ('\n', '\r'). Поскольку алфавит, задаваемый Unicode-кодировкой, содержит более 65000 символов, большинство кодов зарезервировано и им пока не соответствуют реальные символы. Рассмотрим пример, демонстрирующий коды некоторых символов.
// <summary>
/// Преобразования код <-> символ
/// </summary>
public void SymToFromCode()
{
char sym1 = '0', sym2 = 'a',
sym3 = 'A', sym4 = '\r',
sym5 = 'а', sym6 = 'А';
PrintCode(sym1); PrintCode(sym2);
PrintCode(sym3); PrintCode(sym4);
PrintCode(sym5); PrintCode(sym6);
int code1 = 13, code2 = 122,
code3 = 1071, code4 = 70000;
PrintSym(code1); PrintSym(code2);
PrintSym(code3); PrintSym(code4);
}
Процедуры печати PrintCode и PrintSym достаточно просты, так что код их не приводится. Результат работы этого метода показан на рис. 7.1.
Рис. 7.1. Символы и их коды
Класс char, как и все классы в C#, наследует свойства и методы родительского класса object. Но у него есть и собственные методы и свойства, и их немало. Приведу сводку этих методов.
Таблица 7.1. Статические методы и свойства класса char |
|
Метод |
Описание |
GetNumericValue |
Возвращает численное значение символа, если он является цифрой, и (-1) в противном случае. |
GetUnicodeCategory |
Все символы разделены на категории. Метод возвращает Unicode категорию символа. Ниже приведен пример. |
IsControl |
Возвращает true, если символ является управляющим. |
IsDigit |
Возвращает true, если символ является десятичной цифрой. |
IsLetter |
Возвращает true, если символ является буквой. |
IsLetterOrDigit |
Возвращает true, если символ является буквой или цифрой. |
IsLower |
Возвращает true, если символ задан в нижнем регистре. |
IsNumber |
Возвращает true, если символ является числом (десятичной или шестнадцатеричной цифрой). |
IsPunctuation |
Возвращает true, если символ является знаком препинания. |
IsSeparator |
Возвращает true, если символ является разделителем. |
IsSurrogate |
Некоторые символы Unicode с кодом в интервале [0x1000, 0x10FFF] представляются двумя 16-битными "суррогатными" символами. Метод возвращает true, если символ является суррогатным. |
IsUpper |
Возвращает true, если символ задан в верхнем регистре. |
IsWhiteSpace |
Возвращает true, если символ является "белым пробелом". К белым пробелам, помимо пробела, относятся и другие символы, например, символ конца строки и символ перевода каретки. |
Parse |
Преобразует строку в символ. Естественно, строка должна состоять из одного символа, иначе возникнет ошибка. |
ToLower |
Приводит символ к нижнему регистру. |
ToUpper |
Приводит символ к верхнему регистру. |
MaxValue, MinValue |
Свойства, возвращающие символы с максимальным и минимальным кодом. Возвращаемые символы не имеют видимого образа. |
Большинство статических методов перегружены. Они могут применяться как к отдельному символу, так и к строке, для которой указывается номер символа для применения метода. Основную группу составляют методы Is, крайне полезные при разборе строки. Приведу примеры, в которых используются многие из перечисленных методов:
/// <summary>
/// Свойства символов
/// </summary>
public void TestCharMethods()
{
Console.WriteLine("Метод GetUnicodeCategory:");
System.Globalization.UnicodeCategory cat1, cat2;
cat1 = char.GetUnicodeCategory('A');
cat2 = char.GetUnicodeCategory(';');
Console.WriteLine("'A' - category {0}", cat1);
Console.WriteLine("';' - category {0}", cat2);
Console.WriteLine("Метод IsLetter:");
Console.WriteLine("'z' - IsLetter - {0}",
char.IsLetter('z'));
Console.WriteLine("'Я' - IsLetter - {0}",
char.IsLetter('Я'));
Console.WriteLine("Метод IsLetterOrDigit:");
Console.WriteLine("'7' - IsLetterOrDigit - {0}",
char.IsLetterOrDigit('7'));
Console.WriteLine("'Я' - IsLetterOrDigit - {0}",
char.IsLetterOrDigit('Я'));
Console.WriteLine("Метод IsControl:");
Console.WriteLine("';' - IsControl - {0}",
char.IsControl(';'));
Console.WriteLine(@"'\r' - IsControl - {0}",
char.IsControl('\r'));
Console.WriteLine("Метод IsSeparator:");
Console.WriteLine("' ' - IsSeparator - {0}",
char.IsSeparator(' '));
Console.WriteLine("';' - IsSeparator - {0}",
char.IsSeparator(';'));
Console.WriteLine("Метод IsWhiteSpace:");
Console.WriteLine("' ' - IsWhiteSpace - {0}",
char.IsWhiteSpace(' '));
Console.WriteLine(@"'\r' - IsWhiteSpace - {0}",
char.IsWhiteSpace('\r'));
}//TestCharMethods
Вот как выглядят результаты консольного вывода, порожденного выполнением метода.
Рис. 7.2. Свойства символов
Обратите внимание: буквенными символами являются как символы латиницы, так и кириллицы, символ возврата каретки относится к белым пробелам и к управляющим символам, а символ точки с запятой к разделителям не относится.
Кроме статических методов, у класса char есть и динамические методы. Большинство из них - это методы родительского класса object, унаследованные и переопределенные в классе char. Из собственных динамических методов стоит отметить метод CompareTo, позволяющий проводить сравнение символов. Он отличается от метода Equal тем, что для несовпадающих символов выдает "расстояние" между символами в соответствии с их упорядоченностью в кодировке Unicode.