Какие-нибудь хорошие решения для C++ строкового кода и единицы кода?

В Java строка имеет методы:

length()/charAt(), codePointCount()/codePointAt()

C++ 11 имеет std::string a = u8"很烫烫的一锅汤";

но a.size() длина массива char, не может индексировать символ unicode.

Есть ли решения для Unicode в строке C++?

1 ответ

Решение

Я вообще конвертирую UTF-8 струна на широкую UTF-32/UCS-2 строка перед выполнением символьных операций. C++ на самом деле дает нам функции, чтобы сделать это, но они не очень удобны для пользователя, поэтому я написал здесь несколько приятных функций преобразования:

// This should convert to whatever the system wide character encoding 
// is for the platform (UTF-32/Linux - UCS-2/Windows)
std::string ws_to_utf8(std::wstring const& s)
{
    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;
    std::string utf8 = cnv.to_bytes(s);
    if(cnv.converted() < s.size())
        throw std::runtime_error("incomplete conversion");
    return utf8;
}

std::wstring utf8_to_ws(std::string const& utf8)
{
    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cnv;
    std::wstring s = cnv.from_bytes(utf8);
    if(cnv.converted() < utf8.size())
        throw std::runtime_error("incomplete conversion");
    return s;
}

int main()
{
    std::string s = u8"很烫烫的一锅汤";

    auto w = utf8_to_ws(s); // convert to wide (UTF-32/UCS-2)

    // now we can use code-point indexes on the wide string

    std::cout << s << " is " << w.size() << " characters long" << '\n';
}

Выход:

很烫烫的一锅汤 is 7 characters long

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

std::string utf32_to_utf8(std::u32string const& utf32)
{
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> cnv;
    std::string utf8 = cnv.to_bytes(utf32);
    if(cnv.converted() < utf32.size())
        throw std::runtime_error("incomplete conversion");
    return utf8;
}

std::u32string utf8_to_utf32(std::string const& utf8)
{
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> cnv;
    std::u32string utf32 = cnv.from_bytes(utf8);
    if(cnv.converted() < utf8.size())
        throw std::runtime_error("incomplete conversion");
    return utf32;
}

ПРИМЕЧАНИЕ: по состоянию на C++17std::wstring_convert устарела.

Однако я все же предпочитаю использовать ее над третьей библиотекой Arty, потому что она переносима, она избегает внешних зависимостей, не будет удалена до тех пор, пока не будет предоставлена ​​замена, и во всех случаях она востребована, чтобы заменить реализации этих функций без необходимости изменить весь код, который их использует.

Другие вопросы по тегам