Типы char16_t и char32_t

Стандарт C++11 ввел в язык C++ два новых типа char16_t и char32_t.

Тип char16_t описывает символ в кодировке UTF-16. При инициализации символа или строки перед литералом указывается строчная буква u:

std::setlocale(LC_ALL, "Russian_Russia.1251");
char16_t ch = u'я';
std::cout << ch << std::endl;                 // 1103
char16_t str[] = u"строка";
size_t size = sizeof(char16_t);
std::cout << size << std::endl;               // 2
size_t size_str = sizeof(str);
std::cout << size_str << std::endl;           // 14
int len = static_cast<int>(size_str / size);
std::cout << len << std::endl;                // 7
for (int i = 0; i < len; ++i) {
   std::cout << str[i] << ' ';
} // 1089 1090 1088 1086 1082 1072 0

Тип char32_t описывает символ в кодировке UTF-32. При инициализации символа или строки перед литералом указывается прописная буква U:

std::setlocale(LC_ALL, "Russian_Russia.1251");
char32_t ch = U'я';
std::cout << ch << std::endl;                 // 1103
char32_t str[] = U"строка";
size_t size = sizeof(char32_t);
std::cout << size << std::endl;               // 4
size_t size_str = sizeof(str);
std::cout << size_str << std::endl;           // 28
int len = static_cast<int>(size_str / size);
std::cout << len << std::endl;                // 7
for (int i = 0; i < len; ++i) {
   std::cout << str[i] << ' ';
} // 1089 1090 1088 1086 1082 1072 0

Начиная со стандарта C++11, язык C++ поддерживает raw-строки, внутри которых специальные символы трактуются как комбинации обычных символов, поэтому их экранировать не нужно. Форматы raw-строк:

uR"(текст строки UTF-16)"
UR"(текст строки UTF-32)"
uR"символы(текст строки UTF-16)символы"
UR"символы(текст строки UTF-32)символы"

При использовании первых двух форматов текст строки указывается между отрывающей комбинацией символов uR"( (или UR"( для строк в кодировке UTF-32) и закрывающей комбинацией символов )":

char16_t str[] = uR"(текст \n)";
// char32_t str[] = UR"(текст \n)";
int len = static_cast<int>(sizeof(str) / sizeof(str[0]));
for (int i = 0; i < len; ++i) {
   std::cout << str[i] << ' ';
} // 1090 1077 1082 1089 1090 32 92 110 0
std::cout << std::endl;

Обратите внимание, символ перевода строки \n трактуется как комбинация двух символов \ и n, а не как специальный символ.

Последние два формата позволяют дополнительно указать произвольные символы-разделители, например, три точки. Благодаря этим символам мы можем в тексте строки использовать любые символы без опасения, что они случайно станут закрывающей строку комбинацией символов:

char16_t str[] = uR"...(текст \n)...";

Для преобразования типов предназначены следующие функции:

  • c16rtomb() — преобразует символ c16 из кодировки UTF-16 в кодировку, указанную с помощью локали, и записывает результат в символьный массив buf. Нулевой символ в массив не добавляется. Функция возвращает число байтов, записанных в массив, или значение (size_t)(–1) в случае ошибки. Прототип функции:
#include <cuchar> /* или #include <uchar.h> */
size_t c16rtomb(char *buf, char16_t c16, mbstate_t *state);
typedef int mbstate_t;

Пример преобразования символа в кодировку windows-1251:

std::setlocale(LC_ALL, "Russian_Russia.1251");
char buf[10] = {0};
char16_t ch = u'я';
mbstate_t state = 0;
size_t count = std::c16rtomb(buf, ch, &state);
std::cout << count << std::endl;       // 1
std::cout << state << std::endl;       // 0
std::cout << buf[0] << std::endl;      // я
std::cout << (int)buf[0] << std::endl; // -1
  • mbrtoc16() — преобразует многобайтовый символ, записанный в строку str, в кодировку UTF-16 и сохраняет его в переменной pc16. Кодировка указывается с помощью локали. Максимально просматривается n символов строки str. Функция возвращает число байтов, представляющих символ, 0 или значения (size_t)(–1), (size_t)(–2) или (size_t)(–3) в случае ошибки. Прототип функции:
#include <cuchar> /* или #include <uchar.h> */
size_t mbrtoc16(char16_t *pc16, const char *str, size_t n,
                mbstate_t *state);

Пример:

std::setlocale(LC_ALL, "Russian_Russia.1251");
char16_t pc16 = 0;
char str[10] = "я";
mbstate_t state = 0;
size_t count = std::mbrtoc16(&pc16, str, 10, &state);
std::cout << count << std::endl; // 1
std::cout << state << std::endl; // 0
std::cout << pc16 << std::endl;  // 1103
  • c32rtomb() — преобразует символ c32 и записывает результат в символьный массив buf. Нулевой символ в массив не добавляется. Функция возвращает число байтов, записанных в массив, или значение (size_t)(–1) в случае ошибки. Прототип функции:
#include <cuchar> /* или #include <uchar.h> */
size_t c32rtomb(char *buf, char32_t c32, mbstate_t *state);
  • mbrtoc32() — преобразует многобайтовый символ, записанный в строку str, в символ в кодировке UTF-32 и сохраняет его в переменной pc32. Прототип функции:
#include <cuchar> /* или #include <uchar.h> */
size_t mbrtoc32(char32_t *pc32, const char *str, size_t n,
                mbstate_t *state);

В Windows функции c32rtomb() и mbrtoc32() работают с многобайтовыми символами в кодировке UTF-8, а не используют настройки кодировки из локали:

char buf[10] = {0};
char32_t ch = U'я';
mbstate_t state = 0;
size_t count = std::c32rtomb(buf, ch, &state);
std::cout << count << std::endl;       // 2
std::cout << state << std::endl;       // 0
std::cout << (int)buf[0] << std::endl; // -47
std::cout << (int)buf[1] << std::endl; // -113
char32_t ch32 = 0;
count = std::mbrtoc32(&ch32, buf, 10, &state);
std::cout << count << std::endl;       // 2
std::cout << state << std::endl;       // 0
std::cout << ch32 << std::endl;        // 1103
Примечание

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов