【问题标题】:convert from char to char16_t从 char 转换为 char16_t
【发布时间】:2014-11-08 16:20:26
【问题描述】:

我的配置:

  • 编译器: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。

【问题讨论】:

  • 看wstring_convert和codecvt的en.cppreference.com/w/cpp/locale/wstring_convert
  • strlen(str.c_str())...
  • char16_t cstr[si+1]; - VLA 不是有效的 C++。
  • @JDS:不幸的是,没有任何方面可以连接“系统”和“UTF”世界。 (但是,您可以转换 within the "system" world 并在 UTF 世界中使用 wstring_convert,如果您愿意执行一些类设计杂技。)
  • ...最后,mbrtoc16 只转换一个字符。

标签: c++ c++11 char16-t


【解决方案1】:

我不知道 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 将是有损的(可能最终会打印一堆“?”,具体取决于您的系统),但它会毫无问题地工作。

【讨论】:

    【解决方案2】:

    mbrtoc16() 转换单个字符,并返回用于转换 char16_t 的多字节字符数。

    为了实现这种转换,一般的方法是:

    A) 调用 mbrtoc16()。

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

    C) 您是否已使用了要转换的整个字符串?如果否,则返回步骤 A。

    此外,可能存在转换错误。您必须检查 mbrtoc16() 的返回值并执行您想做的任何事情,以处理转换错误(原始多字节字符串是有效的)。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多