Как получить символ utf8 из std::string?

144
15 декабря 2016, 16:03

Допустим есть std::string. Кодировка utf8. Значит один реальный символ, может кодироваться несколькими типами char(1-4). Как в цикле определить:

  1. Где начинается этот реальный символ, где заканчивается?
  2. Получить сам этот символ в wchar_t?

.

std::string utf8_text = "Здесь лежит utf8";
wchar_t symbol; 
for(auto IT = utf8_text.begin(); IT != utf8_text.end(); IT++)
{
    unsigned char symbol= *IT;
    if(symbol>225){}
}
Answer 1

я думаю, что Вы прекрасно понимаете, что условие symbol>255 будет всегда ложно, если тип char - один байт. Но допишем программу и распечатаем вывод

#include <iostream>
using namespace std;
int main() {
    std::string utf8_text = "Здесь лежит utf8";
    wchar_t symbol; 
    for(auto IT = utf8_text.begin(); IT != utf8_text.end(); IT++)
    {
      unsigned char symbol= *IT;
      cout << hex << (int) symbol << " ";
    }
    cout << endl;
    return 0;
}

Вывод будет таким

d0 97 d0 b4 d0 b5 d1 81 d1 8c 20 d0 bb d0 b5 d0 b6 d0 b8 d1 82 20 75 74 66 38

Заметили кучу d0 и d1? Правильно. Это это один из признаков, что в utf есть кириллица (точнее - для двухбайтовых кодировок). Теперь самое время сходить на wikipedia и почитать о том, как на низком уровне реализован utf-8. Я пересказывать не буду. Скажу только, что нужно читать первый байт, и считаем слева на право единички до первого нуля. Это и будет ответом, сколько байт нужно прочитать. Смотрим d0 => 11010000, два байта. Один байт мы уже прочитали, значит нужно дочитать ещё один. В всех последующих байтах будет одна первая единичка и ноль. Следующий байт - 97 => 10010111. Готово, теперь вычленяем результат

11010000 10010111 => 100 0001 0111 => 0417(hex)

идем на любой сайт с юникодными таблицами и вбиваем код символа для поиска - U+0417 и видим - "Кириллическая заглавная буква зэ" - что соответствует действительности.

Что бы не делать это "вручную", можно использовать библиотек codecvt, но ее как то плохо реализовали в gcc/clang - мне не удалось завести нормально.

READ ALSO
Ключевое слово `auto`

Ключевое слово `auto`

Что значит ключевое слово auto в с++ и где оно применяется?

157
Не компилируется драйвер RT5572 на Raspberry PI

Не компилируется драйвер RT5572 на Raspberry PI

Не получается скомпилировать драйвер для WI-Fi usb: rt5572stako

258
Алгоритмическая сложность операций с NSMutableArray

Алгоритмическая сложность операций с NSMutableArray

Как ответить на следующих вопрос? Он будет на собеседовании на работу

183