8.1. Класс char
В
C# есть символьный
класс Char, основанный на классе System.Char и использующий
двухбайтную кодировку Unicode представления
символов. Для этого типа в языке определены символьные константы - символьные
литералы. Константу можно задавать:
-
символом, заключенным в одинарные кавычки;
- escape-последовательностью,
задающей код символа;
- Unicode-последовательностью,
задающей Unicode-код символа.
Вот
несколько примеров объявления символьных переменных и работы с ними:
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 и string отсутствуют, но,
благодаря методу ToString, переменные типа
char стандартным
образом преобразуются в тип string. Как отмечалось
выше, существуют неявные преобразования типа char в целочисленные
типы, начиная с типа ushort. Обратные
преобразования целочисленных типов в тип char также
существуют, но они уже явные.
В
результате работы процедуры TestChar строка s, полученная
сцеплением трех символов, преобразованных в строки, имеет значение BZX, переменная ch равна A, а ее код -
переменная code - 65.
Не
раз отмечалось, что семантика присваивания справедлива при вызове методов и
замене формальных аргументов на фактические. Приведем две процедуры,
выполняющие взаимно-обратные операции - получение по коду символа и получение
символа по его коду:
public
int SayCode(char sym) {
return
sym;
}//SayCode
public
char SaySym(object code) {
return (char)((int)code);
}// SaySym
Как видите, в первой процедуре
преобразование к целому типу выполняется неявно. Во второй - преобразование
явное. Ради универсальности она слегка усложнена. Формальный параметр имеет тип
Object, что позволяет
передавать ей в качестве аргумента код, заданный любым целочисленным типом.
Платой за это является необходимость выполнять два явных преобразования.
Класс Char, как и все классы
в C#, наследует
свойства и методы родительского класса Object. Но у него есть и
собственные методы и свойства, и их немало. Сводка этих методов приведена в
таблице 5.
Таблица 5. Статические
методы и свойства класса 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, крайне полезные
при разборе строки. Приведем примеры, в которых используются многие из
перечисленных методов:
public void TestCharMethods() {
Console.WriteLine("Статические
методы класса char:");
char
ch =
'a',
ch1 =
'1', lim
=
';', chc
=
'xA';
double
d1, d2;
d1 = char.GetNumericValue(ch);
d2 = char.GetNumericValue(ch1);
Console.WriteLine("Метод GetNumericValue:");
Console.WriteLine("sym
'a' -
value
{0}",
d1);
Console.WriteLine("sym
'1'
- value
{0}",
d2);
System.Globalization.UnicodeCategory
cat1, cat2;
cat1 = char.GetUnicodeCategory(ch1);
cat2 = char.GetUnicodeCategory(lim);
Console.WriteLine("Метод GetUnicodeCategory:");
Console.WriteLine("sym
'1'
- category
{0}",
cat1);
Console.WriteLine("sym
';'
- category
{0}",
cat2);
Console.WriteLine("Метод IsControl:");
Console.WriteLine("sym
'xA' -
IsControl
-
{0}", char.IsControl(chc));
Console.WriteLine("sym
';'
- IsControl
-
{0}", char.IsControl(lim));
Console.WriteLine("Метод IsSeparator:");
Console.WriteLine("sym
'
' - IsSeparator
-
{0}", char.IsSeparator(' '));
Console.WriteLine("sym
';'
- IsSeparator
-
{0}", char.IsSeparator(lim));
Console.WriteLine("Метод IsSurrogate:");
Console.WriteLine("sym
'u10FF' - IsSurrogate -
{0}", char.IsSurrogate('u10FF'));
Console.WriteLine("sym
'\' -
IsSurrogate
-
{0}", char.IsSurrogate('\'));
string
str =
"U00010F00";
//Символы Unicode
в интервале [0x10000,0x10FFF]
//представляются двумя 16-битными суррогатными символами
Console.WriteLine("str
=
{0}, str[0]
=
{1}", str, str[0]);
Console.WriteLine("str[0]
IsSurrogate - {0}", char.IsSurrogate(str,
0));
Console.WriteLine("Метод IsWhiteSpace:");
str =
"пробелы, пробелы!"
+ "xD"
+
"xA"
+
"Всюду пробелы!";
Console.WriteLine("sym
'xD '
- IsWhiteSpace
-
{0}", char.IsWhiteSpace('xD'));
Console.WriteLine("str:
{0}",
str);
Console.WriteLine(“и ее пробелы - символ 8
{0},символ 17
{1}",
char.IsWhiteSpace(str,
8),
char.IsWhiteSpace(str,
17));
Console.WriteLine("Метод Parse:");
str = "A";
ch = char.Parse(str);
Console.WriteLine("str:{0}
char: {1}",
str,
ch);
Console.WriteLine("Минимальное
и максимальное значение:{0}, {1}",
char.MinValue.ToString(),
char.MaxValue.ToString());
Console.WriteLine("Их коды:
{0}, {1}", SayCode(char.MinValue),
SayCode(char.MaxValue));
}//TestCharMethods
Результаты
консольного вывода, порожденного выполнением метода, изображены на рис. 26.
Рисунок 26. Вызовы статических методов класса char
Кроме
статических методов, у класса Char есть и
динамические. Большинство из них - это методы родительского класса Object, унаследованные и
переопределенные в классе Char. Из собственных
динамических методов стоит отметить метод CompareTo, позволяющий
проводить сравнение символов. Он отличается от метода Equal тем, что для
несовпадающих символов выдает «расстояние» между символами в соответствии с их
упорядоченностью в кодировке Unicode.
Приведем пример.
public void
testCompareChars() {
char
ch1,ch2;
int
dif;
Console.
WriteLine("Метод CompareTo");
ch1 = 'A';
ch2 = 'Z';
dif = ch1.CompareTo(ch2);
Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif);
ch1 = 'а';
ch2 = 'А';
dif = ch1.CompareTo(ch2);
Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif);
ch1 = 'Я';
ch2 = 'А';
dif = ch1.CompareTo(ch2);
Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif);
ch1 = 'A';
ch2 = 'A';
dif = ch1.CompareTo(ch2);
Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif);
ch1 = 'А';
ch2 = 'A';
dif = ch1.CompareTo(ch2);
Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif);
ch1 = 'Ё';
ch2 = 'А';
dif = ch1.CompareTo(ch2);
Console.WriteLine("Расстояние между символами {0},
{1} = {2}", ch1, ch2, dif);
} //TestCompareChars
Результаты
сравнения изображены на рис. 27.
Рисунок 27. Сравнение символов
Анализируя
эти результаты, можно понять, что в кодировке Unicode как латиница,
так и кириллица плотно упакованы. Исключение составляет буква Ё - заглавная и
малая - они выпадают из плотной кодировки. Малые буквы в кодировке непосредственно
следуют за заглавными буквами. Расстояние между алфавитами в кодировке довольно
большое - русская буква А на 975 символов правее в кодировке, чем
соответствующая буква в латинском алфавите.