如何从 UTF-8 字符串的每个字符中获取 UNICODE 代码?

Posted

技术标签:

【中文标题】如何从 UTF-8 字符串的每个字符中获取 UNICODE 代码?【英文标题】:How to get the UNICODE code from each character of a UTF-8 string? 【发布时间】: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 为这项任务提供了哪些标准库工具?

【问题讨论】:

【参考方案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 许可代码中提取的。

【讨论】:

以上是关于如何从 UTF-8 字符串的每个字符中获取 UNICODE 代码?的主要内容,如果未能解决你的问题,请参考以下文章

如何从数组中的字符串数组中获取每个值

JAVA:从字符串中获取 UTF-8 十六进制值?

如何随机从数组中获取随机字符串项,并将字符串单词的每个字符随机放入li标签中

如何在 Ruby 2.1 中获取给定 UTF-8 代码的字符

PHP:simplexml_load_file 从使用 UTF-8 编码的 XML 文件中获取奇怪的字符

如何在php中解析soap xml响应并从字符串中获取信息