Допустим есть файл сохранённый в UTF8. Читать я его могу исключительно std::ifstream (без std::wifstream).
После прочтения файла, я хочу иметь возможность итерироваться по utf-8 символам, и даже сравнивать их
for (size_t i = 0; i < utf8String.size(); i++) {
if (utf8String[i] == 'ф') {
//...
}
}
Т.е. я хочу чтобы была возможность работать с каждым utf-8 символом, в независимости от того какой он длинны как с одним символом.
Что мне для этого нужно?
Я думал что wchar_t. Но есть такие два источника: 1. https://ru.wikipedia.org/wiki/Широкий_символ 2. https://stackoverflow.com/questions/17871880/should-i-use-wchar-t-when-using-...
Которые вроде как говорят что это не очень хорошо.
Еще я заметил (да на ++ уже пишу и не первый год), но заметил только сейчас, т.к.раньше просто не думал про это ибо не было нужно:
что std::wstring wstr = L"добро"; //да, система дебиан 8, x86-64, исходник сохранен в utf8.
в общем wstr==«добро» в оперативной памяти будет представлено не в utf-8 а в неведомой кодировке. Но по которой можно итерироваться и сравнивать.
Буква 'д' из этой строки будет иметь следующий байт-код 00110100 00000100 00000000 00000000 (wchar_t)
При этом если бы 'д' была в utf8 то она должна была бы иметь такие байты 11010000 10110100 {00000000 00000000} - в скобках хвост который как бы не имеет отношение к коду 'д', но заполняет тип wchar_t.
Вопросы: Можно ли как-то сделать так чтобы компилятор (g++) видя wchar_t c = L'д' или whchar_t c = 'д' - конструировал utf8 букву в wchar_t типе, а не в непонятной кодировке. И кстати в какой кодировке он её кодирует по умолчанию?
Есть ли какой-то способ прочитать преобразовать utf-8 строку, хранимую в std::string в std::wstring так чтобы после такого преобразования содержимое этой wstring можно было бы корректно вывести в std::wcout?
Я нашел такой способ Преобразование std::string в std::wstring
Но во первых он какой-то страншный и не очень понятный, какие-то шаблоны актуализируются...
А самое главное в моём debian8 и gcc4.3 нет такого хедера include <codecvt>
Поэтому у кого поновее пакетная база, и кому не лень, пожалуйста из ссылки выше запустите пример. Сделайте std::string str(«добро») и преобразуйте её в std::wstring Нужно чтобы после преобразования wstring строка корректно выводилась в std::wcout и можно было побуквенно (а не побайтово) итерироваться по ней, и посимвольно сравнивать.
В общем, т.к. у меня нет этого codecvt я сделал преобразование руками (да можно красивее, переносимее (учитывать порядок байт), при вызове из main не выходить за границы строки и т.д. и т.п. - не суть): https://pastebin.com/4E3nuNcM
и вот если приблизительно таким методом конструировать std::wstring которая содержит utf-8 можно будет итерироваться по ней (да, я знаю что utf8 может быть длиннее чем размер wchar_t, но у меня будет набор латиницы и кириллицы из utf8 документа), можно будет сравнивать с символами, но к сожалению не так wstr[0] = 'ы' а только с заранее созданными символами, подобным методом как строка создавалась. wstr[0] == wcharSymbol.
Это не удобно, а еще такая строка не может корректно выводится на std::wcout.
Т.е. заключительный вопрос - можно ли как-то пользуя нативный wchar_t работать посимвольно с utf-8 в c++ в линукс, имея полный ф-л такой как итерации, посимвольное сравнение, корректный вывод в std::wcout.
Если нельзя - есть ли возможно какие-то сторонние (причем легковесные библиотеки, код которых можно включить в проект, и собрать статически, и чтобы места не много тратили) которые предоставляют некий тип wideChar, полностью совместимый и с std::wcout и со всей stl(конейнерами, алгоритмами) и при этом желательно кросплатформенная?
Кстати в презренной винде на этом же наборе символов utf8 (латиница и кириллица) - всё очень хорошо (плохо там будет когда потребуется символ длиннее 2 байт) - т.к. там wchar_t это 2 байта, т.е. он как раз отлично соотвествует, и в wcout тоже выводится :)
Просьба не флудить а по конкретике писать :)