【问题标题】:How to get the UNICODE code from each character of a UTF-8 string?如何从 UTF-8 字符串的每个字符中获取 UNICODE 代码?
【发布时间】:2014-02-11 19:51:01
【问题描述】:

使用 C++11,我如何从 UTF-8 编码的std::string 将文本中每个字符的 Unicode 值转换为uint32_t

类似:

void f(const std::string &utf8_str)
{
    for(???) {
       uint32_t code = ???;

       /* Do my stuff with the code... */
    }
}

假设主机系统语言环境是 UTF-8 有帮助吗? C++11 为这项任务提供了哪些标准库工具?

【问题讨论】:

    标签: c++ c++11 unicode encoding utf-8


    【解决方案1】:

    您可以简单地将字符串转换为 UTF-32 编码的字符串,使用提供的转换方面和来自<locale>std::wstring_convert

    #include <codecvt>
    #include <locale>
    #include <string>
    
    void foo(std::string const & utf8str)
    {
         std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> conv;
         std::u32string utf32str = conv.from_bytes(utf8str);
    
         for (char32_t u : utf32str)  { /* ... */ }
    }
    

    【讨论】:

    • 你知道如何获取系统原生编码的codecvt,而不是UTF-8吗?
    • @lvella:您可以使用mbrtoc32 将系统的窄编码转换为UTF32。链接页面底部的表格显示了所有可用的组合。 (不过,I'm not sure 如果 &lt;cuchar&gt; 已被广泛实施。)
    • @lvella 系统的本机编码而不是 UTF-8?如果您的意思是 GB18030(另一种 8 位 Unicode 格式),那么您可以使用 codecvt_byname 或使用 use_facet 将其从语言环境中提取出来。 This example 展示了如何使用它构建 wstring_convert。
    • ...您可能需要调用std::setlocale(LC_CTYPE, "") 或其他适合相关流的方式来获取实际的系统区域设置...
    • mbrtoc32 是一个很奇怪的东西……它记录了负返回值,但返回了一个 size_t,它是无符号的。
    【解决方案2】:

    使用来自http://utfcpp.sourceforge.net/&lt;utf8.h&gt; 你可以编码:

     static inline void fix_utf8_string(std::string& str)
     {
       std::string temp;
       utf8::replace_invalid(str.begin(), str.end(), back_inserter(temp));
       str = temp;
     }
    
     static inline bool valid_utf8_cstr(const char*s)
     {
       if (!s) return false;
       const char* e = s+strlen(s);
       return utf8::is_valid(s,e);
     }
    
     static inline size_t
     utf8_length(const char*s)
     {
       if (!s) return 0;
       const char* e = s+strlen(s);
       return utf8::distance(s,e);
     }
    
    
     // apply a function to every code point, exiting if that function
     // gives true and return the number of visited code points
     static inline size_t
     utf8_foreach_if(const char*s, 
                     std::function<bool(uint32_t,size_t)>f)
     {
       if (!s) return 0;
       size_t ix=0;
       const char*pc = s;
       while(*pc)
         {
           const char*epc
             = (pc[1]==0)?(pc+1):(pc[2]==0)
                  ?(pc+2):(pc[3]==0)?(pc+3):(pc+4);
           uint32_t c = utf8::next(pc,epc);
           if (f(c,ix)) break;
           ix++;
         };
       return ix;
     }
    
     static inline size_t
     utf8_foreach_if(const std::string& s, 
                     std::function<bool(uint32_t,size_t)>f)
     {
       if (s.empty()) return 0;
       size_t ix=0;
       const char*pc = s.c_str();
       const char*epc = pc + s.size();
       while(*pc)
         {
           uint32_t c = utf8::next(pc,epc);
           if (f(c,ix)) break;
           ix++;
         };
       return ix;
     }
    

    这是从我将在几周或几个月内发布的一些 GPLv3 许可代码中提取的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-28
      • 1970-01-01
      相关资源
      最近更新 更多