В этом уроке вы будете хранить отдельные символы в переменных char, узнаете их числовые коды и научитесь преобразовывать символ в число и обратно.
Один символ и строка
Тип char в C# хранит одну кодовую единицу UTF-16 стандарта Unicode. Для обычных латинских букв, цифр и многих других символов этого достаточно, чтобы представить один символ.
Символ записывают в одинарных кавычках ('), а строку — в двойных ("): char ch = 'b'; и string text = "b"; имеют разные типы.
char letter = 'A';
char digit = '9';
char sign = '%';
string word = "Hello";
'9' — символ цифры, а 9 — целое число. Числовой код символа '9' равен 57, а не 9.
Ввод одного символа
Console.ReadLine() возвращает строку. Чтобы получить из неё значение char, используйте char.Parse:
Console.Write("Введите одну латинскую букву: ");
char ch = char.Parse(Console.ReadLine());
Console.WriteLine("Вы ввели: " + ch);
Введите, например, A и нажмите Enter. Метод char.Parse требует строку ровно из одной кодовой единицы UTF-16: пустая строка или несколько букв вызовут ошибку. В этих упражнениях вводите один простой символ, например латинскую букву, цифру или знак.
Почему преобразование автоматически работает только в одну сторону
Представьте char как маленькую коробку, а int — как большую. Значения char находятся в диапазоне от 0 до 65 535. Тип int вмещает и отрицательные числа, и положительные до 2 147 483 647. Поэтому любой код из char помещается в int, и преобразование выполняется автоматически.
В обратном направлении целое число, например 1 000 000, может не поместиться в char. Поэтому нужно явно написать (char). Само приведение не гарантирует, что исходное число лежит в допустимом диапазоне.
Из char в int — автоматическое преобразование. Из переменной int в char — явное приведение. Перед преобразованием числа в символ убедитесь, что число находится в диапазоне 0–65 535.
Например, код символа 'c' равен 99. Запись int num = 'c'; сохранит число 99, а (char)(num + 1) даст символ 'd' с кодом 100.
Пример преобразований char и int
Фрагменты с Main в этом уроке заменяют метод Main внутри класса Program вашей консольной программы.
1
2
3
4
5
6
7
8
9
10
11
static void Main(string[] args)
{
int num;
char ch;
ch = 'c'; // Сохраняем символ c
num = ch; // Автоматически получаем его числовой код Unicode
Console.WriteLine("num = " + num); // 99
Console.WriteLine("ch = " + ch); // c
ch = (char)(num + 1); // Явно преобразуем код 100 в символ
Console.WriteLine("ch = " + ch); // d
}
Результат:
num = 99
ch = c
ch = d
ASCII и Unicode
ASCII — стандарт кодирования, в котором каждому из 128 символов соответствует число от 0 до 127. Он включает английские буквы, цифры, знаки и управляющие коды. Например:
| Символ | Код |
|---|---|
'A' |
65 |
'B' |
66 |
'a' |
97 |
'b' |
98 |
'0' |
48 |
'9' |
57 |
Unicode охватывает гораздо больше символов. Для символов основной таблицы ASCII числовые значения совпадают с их значениями в Unicode.
При преобразовании char в int вы получаете числовое значение кодовой единицы Unicode. При явном преобразовании подходящего int в char получается кодовая единица с этим значением:
int num = 65;
char ch = (char)num;
Console.WriteLine(ch); // A
Почему некоторые символы не помещаются в один char
В C# тип char занимает 16 бит и хранит одну кодовую единицу UTF-16. В этот диапазон входят латинские и русские буквы, многие другие письменности и знаки валют, например € и £.
Символы Unicode с кодовыми точками выше U+FFFF, например эмодзи 😀, представляются в UTF-16 парой кодовых единиц, которую называют суррогатной парой. Одного char для них недостаточно, зато их можно хранить в string:
// Ошибка: для этого эмодзи нужны две кодовые единицы UTF-16.
// char emoji = '😀';
// Допустимо: строка содержит последовательность кодовых единиц.
string emoji = "😀";
Поэтому утверждение «один char — всегда один видимый символ» неточно. В основных упражнениях этого урока используются простые символы ASCII.
Практика: запустите два варианта
Сначала предскажите вывод, затем запустите:
1
2
3
4
5
6
7
8
9
static void Main(string[] args)
{
int num;
char ch;
ch = 'c'; // Код Unicode равен 99; он совпадает с ASCII
num = ch; // Автоматическое преобразование char в int
Console.WriteLine("num=" + num);
Console.WriteLine("ch=" + ch);
}
В следующем варианте есть ошибка. Скопируйте его, попробуйте запустить и найдите причину по сообщению среды разработки:
1
2
3
4
5
6
7
8
9
static void Main(string[] args)
{
int num;
char ch;
num = 99;
ch = num;
Console.WriteLine("num=" + num);
Console.WriteLine("ch=" + ch);
}
Объяснение и исправление
Ошибка находится в ch = num;: значение переменной int нельзя автоматически присвоить переменной char. Для кода 99, который находится в допустимом диапазоне, используйте:
ch = (char)num;
После исправления вывод будет:
num=99
ch=c
Проверьте себя
- Чем отличаются
char digit = '5';иint digit = 5;? - Что выведет
Console.WriteLine((int)'A');? - Что выведет
Console.WriteLine((char)66);? - Какой символ получится после
char ch = 'a'; ch = (char)(ch + 2);?
Ответы
- Первая переменная содержит символ с кодом 53, вторая — целое число 5. Это два отдельных примера: не объявляйте обе переменные с одним именем в одном блоке.
65.B.c, потому что код'a'равен 97, а код'c'— 99.
Полная справочная таблица ASCII
Dec — десятичный код, Hex — шестнадцатеричный. Коды 0–31 и 127 служат для управления и обычно не отображаются как обычные печатные символы.
| Dec | Hex | Символ | Название | Dec | Hex | Символ | Название |
|---|---|---|---|---|---|---|---|
| 0 | 0x00 | NUL | Нулевой символ | 64 | 0x40 | @ | Знак «at» |
| 1 | 0x01 | SOH | Начало заголовка | 65 | 0x41 | A | Заглавная A |
| 2 | 0x02 | STX | Начало текста | 66 | 0x42 | B | Заглавная B |
| 3 | 0x03 | ETX | Конец текста | 67 | 0x43 | C | Заглавная C |
| 4 | 0x04 | EOT | Конец передачи | 68 | 0x44 | D | Заглавная D |
| 5 | 0x05 | ENQ | Запрос | 69 | 0x45 | E | Заглавная E |
| 6 | 0x06 | ACK | Подтверждение | 70 | 0x46 | F | Заглавная F |
| 7 | 0x07 | BEL | Звуковой сигнал | 71 | 0x47 | G | Заглавная G |
| 8 | 0x08 | BS | Возврат на один символ | 72 | 0x48 | H | Заглавная H |
| 9 | 0x09 | TAB | Горизонтальная табуляция | 73 | 0x49 | I | Заглавная I |
| 10 | 0x0A | LF | Перевод строки | 74 | 0x4A | J | Заглавная J |
| 11 | 0x0B | VT | Вертикальная табуляция | 75 | 0x4B | K | Заглавная K |
| 12 | 0x0C | FF | Перевод страницы | 76 | 0x4C | L | Заглавная L |
| 13 | 0x0D | CR | Возврат каретки | 77 | 0x4D | M | Заглавная M |
| 14 | 0x0E | SO | Сдвиг наружу | 78 | 0x4E | N | Заглавная N |
| 15 | 0x0F | SI | Сдвиг внутрь | 79 | 0x4F | O | Заглавная O |
| 16 | 0x10 | DLE | Экранирование канала данных | 80 | 0x50 | P | Заглавная P |
| 17 | 0x11 | DC1 | Управление устройством 1 | 81 | 0x51 | Q | Заглавная Q |
| 18 | 0x12 | DC2 | Управление устройством 2 | 82 | 0x52 | R | Заглавная R |
| 19 | 0x13 | DC3 | Управление устройством 3 | 83 | 0x53 | S | Заглавная S |
| 20 | 0x14 | DC4 | Управление устройством 4 | 84 | 0x54 | T | Заглавная T |
| 21 | 0x15 | NAK | Отрицательное подтверждение | 85 | 0x55 | U | Заглавная U |
| 22 | 0x16 | SYN | Синхронизация | 86 | 0x56 | V | Заглавная V |
| 23 | 0x17 | ETB | Конец блока передачи | 87 | 0x57 | W | Заглавная W |
| 24 | 0x18 | CAN | Отмена | 88 | 0x58 | X | Заглавная X |
| 25 | 0x19 | EM | Конец носителя | 89 | 0x59 | Y | Заглавная Y |
| 26 | 0x1A | SUB | Замена | 90 | 0x5A | Z | Заглавная Z |
| 27 | 0x1B | ESC | Экранирование | 91 | 0x5B | [ | Открывающая квадратная скобка |
| 28 | 0x1C | FS | Разделитель файлов | 92 | 0x5C | \ | Обратная косая черта |
| 29 | 0x1D | GS | Разделитель групп | 93 | 0x5D | ] | Закрывающая квадратная скобка |
| 30 | 0x1E | RS | Разделитель записей | 94 | 0x5E | ^ | Знак циркумфлекса |
| 31 | 0x1F | US | Разделитель единиц | 95 | 0x5F | _ | Подчёркивание |
| 32 | 0x20 | (пробел) | Пробел | 96 | 0x60 | ` | Обратная кавычка |
| 33 | 0x21 | ! | Восклицательный знак | 97 | 0x61 | a | Строчная a |
| 34 | 0x22 | " | Двойная кавычка | 98 | 0x62 | b | Строчная b |
| 35 | 0x23 | # | Решётка | 99 | 0x63 | c | Строчная c |
| 36 | 0x24 | $ | Знак доллара | 100 | 0x64 | d | Строчная d |
| 37 | 0x25 | % | Процент | 101 | 0x65 | e | Строчная e |
| 38 | 0x26 | & | Амперсанд | 102 | 0x66 | f | Строчная f |
| 39 | 0x27 | ’ | Одинарная кавычка | 103 | 0x67 | g | Строчная g |
| 40 | 0x28 | ( | Открывающая круглая скобка | 104 | 0x68 | h | Строчная h |
| 41 | 0x29 | ) | Закрывающая круглая скобка | 105 | 0x69 | i | Строчная i |
| 42 | 0x2A | * | Звёздочка | 106 | 0x6A | j | Строчная j |
| 43 | 0x2B | + | Плюс | 107 | 0x6B | k | Строчная k |
| 44 | 0x2C | , | Запятая | 108 | 0x6C | l | Строчная l |
| 45 | 0x2D | - | Дефис | 109 | 0x6D | m | Строчная m |
| 46 | 0x2E | . | Точка | 110 | 0x6E | n | Строчная n |
| 47 | 0x2F | / | Косая черта | 111 | 0x6F | o | Строчная o |
| 48 | 0x30 | 0 | Цифра ноль | 112 | 0x70 | p | Строчная p |
| 49 | 0x31 | 1 | Цифра один | 113 | 0x71 | q | Строчная q |
| 50 | 0x32 | 2 | Цифра два | 114 | 0x72 | r | Строчная r |
| 51 | 0x33 | 3 | Цифра три | 115 | 0x73 | s | Строчная s |
| 52 | 0x34 | 4 | Цифра четыре | 116 | 0x74 | t | Строчная t |
| 53 | 0x35 | 5 | Цифра пять | 117 | 0x75 | u | Строчная u |
| 54 | 0x36 | 6 | Цифра шесть | 118 | 0x76 | v | Строчная v |
| 55 | 0x37 | 7 | Цифра семь | 119 | 0x77 | w | Строчная w |
| 56 | 0x38 | 8 | Цифра восемь | 120 | 0x78 | x | Строчная x |
| 57 | 0x39 | 9 | Цифра девять | 121 | 0x79 | y | Строчная y |
| 58 | 0x3A | : | Двоеточие | 122 | 0x7A | z | Строчная z |
| 59 | 0x3B | ; | Точка с запятой | 123 | 0x7B | { | Открывающая фигурная скобка |
| 60 | 0x3C | < | Знак «меньше» | 124 | 0x7C | | | Вертикальная черта |
| 61 | 0x3D | = | Знак равенства | 125 | 0x7D | } | Закрывающая фигурная скобка |
| 62 | 0x3E | > | Знак «больше» | 126 | 0x7E | ~ | Тильда |
| 63 | 0x3F | ? | Вопросительный знак | 127 | 0x7F | DEL | Удаление |