在 C++ 中将字符串转换为 UTF-8

string to UTF-8 conversion in C++

我有一个字符串 Test\xc2\xae,用十六进制表示为 0x54 0x65 0x73 0x74 0x5c 0x78 0x63 0x32 0x5c 0x78 0x61 0x65。 该字符串中的字符集\xc2\xae就是®(注册商标)的UTF-8编码。

我想编写一个 c++ 函数,它可以将 \xc2(十六进制 0x5c 0x78 0x63 0x32)字符集转换为十六进制值 0xc2

例如我想写一个 c++ 函数,它可以将 Test\xc2\xae [0x54 0x65 0x73 0x74 0x5c 0x78 0x63 0x32 0x5c 0x78 0x61 0x65] 转换为 Test® [0x54 0x65 0x73 0x74 0xc2 0xae]

据我了解您的问题,我认为您尝试将每个 \x?? 序列(四个字符)(其中 ?? 是两个十六进制数字的序列)转换为唯一的字符以十六进制表示的值。

如果您不必为此使用庞大的库,也许这个简单的算法可以解决问题。

/**
  g++ -std=c++17 -o prog_cpp prog_cpp.cpp \
      -pedantic -Wall -Wextra -Wconversion -Wno-sign-conversion \
      -g -O0 -UNDEBUG -fsanitize=address,undefined
**/

#include <iostream>
#include <string>
#include <cctype>

std::string
convert_backslash_x(const std::string &str)
{
  auto result=std::string{};
  for(auto start=std::string::size_type{0};;)
  {
    const auto pos=str.find("\x", start);
    if((pos==str.npos)||  // not found
       (pos+4>size(str))) // too near from the end
    {
      // keep the remaining of the string
      result.append(str, start);
      break;
    }
    // keep everything until this position
    result.append(str, start, pos-start);
    const auto c1=std::tolower(str[pos+2]), c2=std::tolower(str[pos+3]);
    if(std::isxdigit(c1)&&std::isxdigit(c2))
    {
      // convert two hex digits to a char with this value
      const auto h1=std::isalpha(c1) ? 10+(c1-'a') : (c1-'0');
      const auto h2=std::isalpha(c2) ? 10+(c2-'a') : (c2-'0');
      result+=char(h1*16+h2);
      // go on after this \x?? sequence
      start=pos+4; 
    }
    else
    {
      // keep this incomplete \x sequence as is
      result+="\x";
      // go on after this \x sequence
      start=pos+2;
    }
  }
  return result;
}

int
main()
{
  for(const auto &s: {"Test\xc2\xae",
                      "Test\xc2\xae Test\xc2\xae",
                      "Test\xc2\xa",
                      "Test\x\xc2\xa"})
  {
    std::cout << '(' << s << ") --> (" << convert_backslash_x(s) << ")\n";
  }
  return 0;
}