从char类型转换为char16_t类型

4

我的配置:

  • 编译器:gnu gcc 4.8.2
  • 我使用C++11进行编译
  • 平台/操作系统:Linux 64位 Ubuntu 14.04.1 LTS

我有这个方法:

static inline std::u16string StringtoU16(const std::string &str) {
    const size_t si = strlen(str.c_str());
    char16_t cstr[si+1];
    memset(cstr, 0, (si+1)*sizeof(char16_t));
    const char* constSTR = str.c_str();
    mbstate_t mbs;
    memset (&mbs, 0, sizeof (mbs));//set shift state to the initial state
    size_t ret = mbrtoc16 (cstr, constSTR, si, &mbs);
    std::u16string wstr(cstr);
    return wstr;
}

我希望能够实现 char 到 char16_T 的转换(通过 std::string 和 std::u16string 以方便内存管理),但无论输入变量 str 的大小如何,它只返回第一个字符。如果 str = "Hello",则返回 "H"。我不确定我的方法有什么问题。ret 的值为 1。


3
strlen(str.c_str())... - T.C.
2
char16_t cstr[si+1]; - VLA 不是有效的 C++。 - T.C.
@JDS:不幸的是,没有任何方面将“系统”和“UTF”世界连接起来。(但是,如果您愿意执行一些类设计的杂技动作,您可以在“系统”世界内转换,在UTF世界内使用wstring_convert实现转换。) - Kerrek SB
最后,mbrtoc16 仅转换单个字符。 - T.C.
@JDS:“当你的系统是UTF8时”,很多事情变得更容易,这是真的。然而,如果你想编写通用的C++代码,你需要跨越更多的障碍。 - Kerrek SB
显示剩余3条评论
2个回答

3

我以前不知道mbrtoc16()只能一次处理一个字符.. 太慢了。这里是我生成的代码,它像魔法一样运行:

static inline std::u16string StringtoU16(const std::string &str) {
    std::u16string wstr = u"";
    char16_t c16str[3] = u"\0";
    mbstate_t mbs;
    for (const auto& it: str){
        memset (&mbs, 0, sizeof (mbs));//set shift state to the initial state
        memmove(c16str, u"\0\0\0", 3);
        mbrtoc16 (c16str, &it, 3, &mbs);
        wstr.append(std::u16string(c16str));
    }//for
    return wstr;
}

对于它的同伴(当需要单向操作时,迟早会需要双向操作):

static inline std::string U16toString(const std::u16string &wstr) {
    std::string str = "";
    char cstr[3] = "\0";
    mbstate_t mbs;
    for (const auto& it: wstr){
        memset (&mbs, 0, sizeof (mbs));//set shift state to the initial state
        memmove(cstr, "\0\0\0", 3);
        c16rtomb (cstr, it, &mbs);
        str.append(std::string(cstr));
    }//for
    return str;
}

请注意,如果无法将char16_t转换为char(根据您的系统可能会打印一堆“?”),则c16rtomb将有损失,但它将无声地工作。

1

mbrtoc16()函数将单个字符转换为char16_t类型,并返回转换所需的多字节字符数。

为了进行此转换,一般的方法是:

A)调用mbrtoc16()函数。

B)保存转换后的字符,跳过已消耗的字符数。

C)您是否已经消耗完要转换的整个字符串?如果没有,请返回步骤A。

此外,可能会出现转换错误。您必须检查mbrtoc16()函数的返回值,并根据需要处理转换错误(原始的多字节字符串无效)。

最后,您不应该假设char16_t字符串的最大大小等于或小于多字节字符串的大小。它可能是;但是,在某些奇怪的语言环境中,理论上可能更大。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接