【问题标题】:How to convert a codepoint 32bit integer array (UTF-32?) to Windows native string?如何将代码点 32 位整数数组(UTF-32?)转换为 Windows 本机字符串?
【发布时间】:2015-06-08 14:22:20
【问题描述】:

如何将代码点 32 位整数数组 (UTF-32?) 转换为 Windows 本机字符串?在 API 级别处理 Unicode 的 Windows 原生字符串类型是什么?它能正确处理 'u65535' 以外的字符吗?

【问题讨论】:

  • 它使用 utf-16,一种可变长度编码。通常在您的程序中使用 LPWCSTR 或 WCHAR[]。是的。

标签: c windows winapi visual-c++ unicode


【解决方案1】:

Windows 使用UTF-16 作为其本机字符串类型。 UTF-16 处理高达U+10FFFF 的代码点,使用代理对U+FFFF 以上的代码点进行编码。

Windows 没有UTF-32 的概念,因此您必须:

  1. 如果您使用的是 C++11 或更高版本,它具有原生的 std::u16stringstd::u32string 类型,以及用于在 UTF-8、UTF-16 和 UTF-32 之间转换数据的 std::codecvt 类。

    #include <string>
    #include <locale>
    
    std::u16string Utf32ToUtf16(const u32string &codepoints)
    {
        std::wstring_convert<
            std::codecvt_utf16<char32_t, 0x10ffff, std::little_endian>
            char32_t> conv;
        std::string bytes = conv.to_bytes(codepoints);
        return std::u16string(reinterpret_cast<char16_t*>(bytes.c_str()), bytes.length() / sizeof(char16_t));
    }
    
  2. 如果您使用的是较早的 C/C++ 版本,则必须手动将 UTF-32 转换为 UTF-16:

    // on Windows, wchar_t is 2 bytes, suitable for UTF-16
    std::wstring Utf32ToUtf16(const std::vector<uint32_t> &codepoints)
    {
        std::wstring result;
        int len = 0;
    
        for (std::vector<uint32_t>::iterator iter = codepoints.begin(); iter != codepoints.end(); ++iter)
        {
            uint32_t cp = *iter;
            if (cp < 0x10000) {
                ++len;
            }
            else if (cp <= 0x10FFFF) {
                len += 2;
            }
            else {
                // invalid code_point, do something !
                ++len;
            }
        }
    
        if (len > 0)
        {
            result.resize(len);
            len = 0;
    
            for (std::vector<uint32_t>::iterator iter = codepoints.begin(); iter != codepoints.end(); ++iter)
            {
                uint32_t cp = *iter;
                if (cp < 0x10000) {
                    result[len++] = static_cast<wchar_t>(cp);
                }
                else if (cp <= 0x10FFFF) {
                    cp -= 0x10000;
                    result[len++] = static_cast<wchar_t>((cp >> 10) + 0xD800);
                    result[len++] = static_cast<wchar_t>((cp & 0x3FF) + 0xDC00);
                }
                else {
                    result[len++] = static_cast<wchar_t>(0xFFFD);
                }
            }
        }
    
        return result;
    }
    
  3. 使用 3rd 方库,例如 libiconvICU

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 2011-10-25
    • 1970-01-01
    • 2017-01-18
    • 2018-12-11
    • 1970-01-01
    相关资源
    最近更新 更多