Тип Char
Тип данных System.Char используется для хранения одного символа юникода. В C# есть псевдоним char, который можно использовать при объявлении переменных char:
И, конечно, вы можете сразу присвоить ему значение, если хотите. В C# символ char окружен набором одинарных кавычек:
Поскольку строка (о которой мы поговорим в следующей главе) в основном представляет собой диапазон символов, .NET фактически использует список символов для представления строки. Это также означает, что можно извлечь один символ из строки или выполнить итерацию по строке и получить каждый символ как тип данных char:
Символ — это числовое значение, где каждый символ имеет определенное номер в «алфавите» Юникода. На момент написания, существует более 130.000 различный символов Unicode, начиная с латинского / Западного алфавита до исторических шрифтов. Таким образом, в C# можно очень легко перейти от типа данных char к числовому представлению, как показано в этой слегка расширенной версии предыдущего примера:
Он будет просто выводить символ, сопровождаемый числовым представлением, просто за счет приведения char к целому числу. Это также означает, что вы можете так же легко пойти по другому пути: от числа к основанию. Но зачем вам это? Ну, есть много символов, которые не доступны непосредственно на большинстве клавиатур, например, символ авторского права ( © ). Вместо этого можно использовать Unicode lookup table, найдите числовую версию символа, который вам нужен, а затем просто превратить его в символ:
Вспомогательные методы Char
Класс Char имеет некоторые действительно классные вспомогательные методы, которые могут помочь вам определить тип char, с которым вы в настоящее время имеете дело. Он очень полезен во многих ситуациях, например, при проверке ввода. Вот пример:
Урок №35. Символьный тип данных char
Хоть тип char и относится к целочисленным типам данных (и, таким образом, следует всем их правилам), работа с char несколько отличается от работы с обычными целочисленными типами.
Тип данных char
Переменная типа char занимает 1 байт. Однако вместо конвертации значения типа char в целое число, оно интерпретируется как ASCII-символ.
ASCII (сокр. от «American Standard Code for Information Interchange») — это американский стандартный код для обмена информацией, который определяет способ представления символов английского языка (+ несколько других) в виде чисел от 0 до 127. Например: код буквы ‘а’ — 97, код буквы ‘b’ — 98. Символы всегда помещаются в одинарные кавычки.
Таблица ASCII-символов:
Символы от 0 до 31 в основном используются для форматирования вывода. Большинство из них уже устарели.
Символы от 32 до 127 используются для вывода. Это буквы, цифры, знаки препинания, которые большинство компьютеров использует для отображения текста (на английском языке).
Следующие два стейтмента выполняют одно и то же (присваивают переменным типа char целое число 97 ):
Будьте внимательны при использовании фактических чисел с числами, которые используются для представления символов (из ASCII-таблицы). Следующие два стейтмента выполняют не одно и то же:
Вывод символов
При выводе переменных типа char, объект cout выводит символы вместо цифр:
Также вы можете выводить литералы типа char напрямую:
Оператор static_cast
Если вы хотите вывести символы в виде цифр, а не в виде букв, то вам нужно сообщить cout выводить переменные типа char в виде целочисленных значений. Не очень хороший способ это сделать — присвоить переменной типа int переменную типа char и вывести её:
Лучшим способом является конвертация переменной из одного типа данных в другой с помощью оператора static_cast.
Синтаксис static_cast выглядит следующим образом:
Оператор static_cast принимает значение из (выражения) в качестве входных данных и конвертирует его в указанный вами <новый_тип_данных> .
Пример использования оператора static_cast для конвертации типа char в тип int:
Результат выполнения программы:
Запомните, static_cast принимает (выражение) в качестве входных данных. Если мы используем переменную в (выражении) , то эта переменная изменяет свой тип только в стейтменте с оператором static_cast. Процесс конвертации никак не влияет на исходную переменную с её значением! В вышеприведенном примере, переменная ch остается переменной типа char с прежним значением, чему является подтверждением последний стейтмент с cout.
Также в static_cast нет никакой проверки по диапазону, так что если вы попытаетесь использовать числа, которые будут слишком большие или слишком маленькие для конвертируемого типа, то произойдет переполнение.
Более подробно о static_cast мы еще поговорим на соответствующем уроке.
Ввод символов
Следующая программа просит пользователя ввести символ. Затем она выводит этот символ и его ASCII-код:
Результат выполнения программы:
Input a keyboard character: q
q has ASCII code 113
Обратите внимание, даже если cin позволит вам ввести несколько символов, переменная ch будет хранить только первый символ (именно он и помещается в переменную). Остальная часть пользовательского ввода останется во входном буфере, который использует cin, и будет доступна для использования последующим вызовам cin.
Рассмотрим это всё на практике:
Результат выполнения программы:
Input a keyboard character: abcd
a has ASCII code 97
b has ASCII code 98
Размер, диапазон и знак типа сhar
В языке С++ для переменных типа char всегда выделяется 1 байт. По умолчанию, char может быть как signed, так и unsigned (хотя обычно signed). Если вы используете char для хранения ASCII-символов, то вам не нужно указывать знак переменной (поскольку signed и unsigned могут содержать значения от 0 до 127).
Но если вы используете тип char для хранения небольших целых чисел, то тогда следует уточнить знак. Переменная типа char signed может хранить числа от -128 до 127. Переменная типа char unsigned имеет диапазон от 0 до 255.
Управляющие символы
В языке C++ есть управляющие символы (или «escape-последовательности»). Они начинаются с бэкслеша ( \ ), а затем следует определенная буква или цифра.
Наиболее распространенным управляющим символов в языке С++ является \n , который обозначает символ новой строки:
First line
Second line
Еще одним часто используемым управляющим символом является \t , который заменяет клавишу TAB, вставляя большой отступ:
First part Second part
Таблица всех управляющих символов в языке C++:
| Название | Символ | Значение |
| Предупреждение (alert) | \a | Предупреждение (звуковой сигнал) |
| Backspace | \b | Перемещение курсора на одну позицию назад |
| formfeed | \f | Перемещение курсора к следующей логической странице |
| Символ новой строки (newline) | \n | Перемещение курсора на следующую строку |
| Возврат каретки (carriage return) | \r | Перемещение курсора в начало строки |
| Горизонтальный таб (horizontal tab) | \t | Вставка горизонтального TAB |
| Вертикальный таб (vertical tab) | \v | Вставка вертикального TAB |
| Одинарная кавычка | \’ | Вставка одинарной кавычки (или апострофа) |
| Двойная кавычка | \” | Вставка двойной кавычки |
| Бэкслеш | \\ | Вставка обратной косой черты (бэкслеша) |
| Вопросительный знак | \? | Вставка знака вопроса |
| Восьмеричное число | \(number) | Перевод числа из восьмеричной системы счисления в тип char |
| Шестнадцатеричное число | \x(number) | Перевод числа из шестнадцатеричной системы счисления в тип char |
Рассмотрим пример в коде:
Результат выполнения программы:
«This is quoted text»
This string contains a single backslash \
6F in hex is char ‘o’
Что использовать: ‘\n’ или std::endl?
Вы могли заметить, что в последнем примере мы использовали \n для перемещения курсора на следующую строку. Но мы могли бы использовать и std::endl . Какая между ними разница? Сейчас разберемся.
При использовании std::cout, данные для вывода могут помещаться в буфер, т.е. std::cout может не отправлять данные сразу же на вывод. Вместо этого он может оставить их при себе на некоторое время (в целях улучшения производительности).
И \n , и std::endl оба переводят курсор на следующую строку. Только std::endl еще гарантирует, что все данные из буфера будут выведены, перед тем, как продолжить.
Так когда же использовать \n , а когда std::endl ?
Используйте std::endl , когда нужно, чтобы ваши данные выводились сразу же (например, при записи в файл или при обновлении индикатора состояния какого-либо процесса). Обратите внимание, это может повлечь за собой незначительное снижение производительности, особенно если запись на устройство происходит медленно (например, запись файла на диск).
Используйте \n во всех остальных случаях.
Другие символьные типы: wchar_t, char16_t и char32_t
Тип wchar_t следует избегать практически во всех случаях (кроме тех, когда происходит взаимодействие с Windows API).
Так же, как и стандарт ASCII использует целые числа для представления символов английского языка, так и другие кодировки используют целые числа для представления символов других языков. Наиболее известный стандарт (после ASCII) — Unicode, который имеет в запасе более 110 000 целых чисел для представления символов из разных языков.
Существуют следующие кодировки Unicode:
UTF-32 — требует 32 бита для представления символа.
UTF-16 — требует 16 бит для представления символа.
UTF-8 — требует 8 бит для представления символа.
Типы char16_t и char32_t были добавлены в C++11 для поддержки 16-битных и 32-битных символов Unicode (8-битные символы и так поддерживаются типом char).
В чём разница между одинарными и двойными кавычками при использовании с символами?
Как вы уже знаете, символы всегда помещаются в одинарные кавычки (например, ‘а’ , ‘+’ , ‘5’ ). Переменная типа char представляет только один символ (например, буква а , символ + , число 5 ). Следующий стейтмент не является корректным:
Текст, который находится в двойных кавычках, называется строкой (например, «Hello, world!» ). Строка (тип string) — это набор последовательных символов.
What is a char*?
So I’ve been watching lectures from a University about C++, and I’m learning a lot, but one thing I still cannot understand is this:
Why do you have to do this sometimes?
From what I’ve read/watched, I just don’t understand why you have to put the * . From what I thought I understood, you only use * if you have an address, but maybe I’m just dead wrong.
![]()
7 Answers 7
It can only hold one char acter!
This is a C-string:
It can hold multiple char acters. Another way to write the above is:
The 0 at the end is called the NUL terminator. It denotes the end of a C-string.
A char* stores the starting memory location of a C-string. 1 For example, we can use it to refer to the same array s that we defined above. We do this by setting our char* to the memory location of the first element of s :
The & operator gives us the memory location of s[0] . Here is a shorter way to write the above:
Another common usage of char* is to refer to the memory location of a string literal:
Warning: This string literal should not be changed at runtime. We use const to warn the programmer (and compiler) not to modify myStringLiteral in the following illegal manner:
This is different from the array s above, which we are allowed to modify. This is because the string literal "test" is automatically copied into the array at initialization phase. But with myStringLiteral , no such copying occurs. (Where would we copy to, anyways? There’s no array to hold our data. just a lonely char* !)
1 Technical note: char* merely stores a memory location to things of type char . It can certainly refer to just a single char . However, it is much more common to use char* to refer to C-strings, which are NUL -terminated character sequences, as shown above.
![]()
The char type can only represent a single character. When you have a sequence of characters, they are piled next to each other in memory, and the location of the first character in that sequence is returned (assigned to test). Test is nothing more than a pointer to the memory location of the first character in «testing», saying that the type it points to is a char.
You can do one of two things:
Or, a few variations on those themes like:
I mention this primarily because it’s the one you usually really want.
The bottom line, however, is that char x; will only define a single character. If you want a string of characters, you have to define an array of char or a pointer to char (which you’ll initialize with a string literal, as above, more often than not).
There are real differences between the first two options though. char *test=. defines a pointer named test , which is initialized to point to a string literal. The string literal itself is allocated statically (typically right along with the code for your program), and you’re not supposed to (attempt to) modify it — thus the preference for char const * .
The char test[] = .. allocates an array. If it’s a global, it’s pretty similar to the previous except that it does not allocate a separate space for the pointer to the string literal — rather, test becomes the name attached to the string literal itself.
If you do this as a local variable, test will still refer directly to the string literal — but since it’s a local variable, it allocates «auto» storage (typically on the stack), which gets initialized (usually from a normal, statically allocated string literal) on every entry to the block/scope where it’s defined.
The latter versions (with an array of char) can act deceptively similar to a pointer, because the name of an array will decay to the address of the beginning of the array anytime you pass it to a function. There are differences though. You can modify the array, but modifying a string literal gives undefined behavior. Conversely, you can change the pointer to point at some other char s, so something like:
. is perfectly fine, but trying to do the same with an array won’t work (arrays aren’t assignable).