std::regex_replace 将不起作用,因为它使用存储的实际数据。 "\\u" 字符改变文本在数据中的存储方式。简单地更换它是行不通的——为时已晚。
你可以玩一点编码。很确定肯定有一个库(我写了一个parser,它接受一个原始的UTF-8文件并输出多字节字符的代码点,但它现在真的受到限制,加上它没有经过适当的测试),但我们可以尝试实现我们自己的有限版本,以了解里面发生了什么。
首先,为什么是 UTF-8?真的没有很好的理由不这样做。这取决于您的local encoding,但您可以根据需要进行调整。
使用 UTF-8 编辑器编写的代码示例:
#include <iostream>
#include <string>
#include <bitset>
int main() {
std::string str = "\u1234";
for(char c : str) {
std::cout << std::bitset<8>(static_cast<uint8_t>(c)) << ' ';
}
}
将产生11100001 10001000 10110100。
您可以阅读有关std::bitset here 的信息。如果您对结果感到惊讶(您不熟悉 UTF-8 的工作原理),我鼓励您watch 一个很棒的视频。
回到主题。目标是计算 hex 值,将其转换为 UTF-8 字节序列(characters)并将其存储到std::string。
伪代码:
string := input;
hex := convertToHex(string);
sequence := hexToUTF8(hex);
output := seqToString(sequence);
我们假设input 将作为十六进制字符串提供。要将十六进制字符串转换为十进制值,我们可以使用std::stringstream:
std::string input = "0x1234";
std::stringstream stream{};
stream << std::hex << input;
int val;
stream >> val;
val 将等于 4660。
现在,我们需要在给定该值的情况下构造一个 UTF-8 字节序列。我们可以使用现有的库std::wstring_convert,但注意,从C++17 开始,它被认为已弃用。您最好使用different library,但我们将坚持使用这个来演示示例:
#include <string>
#include <locale>
#include <codecvt>
int main()
{
int val = 4660; // 0x1234
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
std::string u8str = converter.to_bytes(val);
}
u8str 现在等于 "\u1234"。
完整示例:
#include <cassert>
#include <codecvt>
#include <iostream>
#include <locale>
#include <sstream>
#include <string>
int hex_value(const std::string_view str) {
std::stringstream stream{};
stream << std::hex << str;
int parsed;
stream >> parsed;
return parsed;
}
std::string map_to_utf8(const int val) {
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
return converter.to_bytes(static_cast<char32_t>(val));
}
int main() {
std::string input = "0x1234"; // read from file, let's assume...
const auto value = hex_value(input);
const auto str = map_to_utf8(value);
using namespace std::literals;
assert(str == "\u1234"s && "\u1234"s == "ሴ"s); // passes
}