Ответ
Unicode — это универсальный стандарт кодирования символов, который ставит в соответствие каждому символу из большинства письменных систем мира уникальный числовой код (кодовую точку, code point). В отличие от ASCII (128 символов), Unicode охватывает более 140 000 символов, включая исторические шрифты, эмодзи и специальные знаки.
Основные кодировки (форматы хранения байтов):
- UTF-8: Переменная длина (1-4 байта). Обратно совместима с ASCII (первые 128 символов кодируются одним байтом). Стандарт для веба и многих систем. Является кодировкой по умолчанию для строковых литералов во многих компиляторах.
- UTF-16: Использует 2 или 4 байта (суррогатные пары для символов за пределами Basic Multilingual Plane). Нативный для Windows API и Java.
- UTF-32: Фиксированная длина (4 байта на кодовую точку). Прост для обработки, но неэффективен по памяти.
Работа с Unicode в современном C++ (C++11 и выше):
#include <iostream>
#include <string>
#include <locale>
#include <codecvt> // Для конвертации (устарело в C++17, но пока используется)
int main() {
// Строковые литералы с префиксами:
std::string utf8_str = u8"Привет, 世界! 😊"; // UTF-8 (char)
std::u16string utf16_str = u"Привет, 世界! 😊"; // UTF-16 (char16_t)
std::u32string utf32_str = U"Привет, 世界! 😊"; // UTF-32 (char32_t)
std::wstring wide_str = L"Привет, 世界! 😊"; // Широкая строка (wchar_t, зависит от платформы)
std::cout << "UTF-8 output: " << utf8_str << std::endl;
// Конвертация UTF-8 в UTF-16 (используя устаревший, но пока распространенный codecvt)
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> converter;
std::u16string converted = converter.from_bytes(utf8_str);
// **Важно:** Для корректного вывода в консоль Windows может потребоваться
// изменить кодовую страницу консоли или использовать API WriteConsoleW.
// На Linux/macOS с UTF-8 локалью вывод обычно работает корректно.
// Итерация по кодовым точкам UTF-8 (упрощенно):
for (char c : utf8_str) {
// Но так мы итерируем по байтам, а не по символам!
// Для посимвольной обработки нужны библиотеки (ICU, Boost.Nowide) или C++20 <text_encoding>.
}
return 0;
}
Проблемы и рекомендации для C++:
std::stringиstd::wstringне знают о кодировке. Они просто хранят последовательностиchar/wchar_t. Ответственность за корректную интерпретацию лежит на программисте.- Консольный ввод/вывод может некорректно отображать Unicode в зависимости от настроек терминала/консоли.
- Для сложных операций (нормализация, разбиение на графемы, сортировка) используйте специализированные библиотеки, такие как International Components for Unicode (ICU).
- C++20 вводит новые типы (
std::u8string) и улучшенную поддержку текста, но полная библиотека пока не реализована во всех компиляторах.
Правило для современных кроссплатформенных проектов: Храните и обрабатывайте текст внутри программы в UTF-8 (используя std::string), конвертируя в другие кодировки только на границах ввода/вывода (файлы, сеть, UI).