[英]How can I to get the utf-8 int value of a unicode char from a (w)string?
我需要一个函数,它需要一个字符串并将所有非 ascii 字符编码为 utf-8 作为十六进制数并用它替换它。
例如,像“djvӷdio”这样的词中的ӷ 应替换为“d3b7”,而其余部分保持不变。
Explanation:
ӷ equals int 54199 and in hexadecimal d3b7
djvӷdio --> djvd3b7dio
我已经有一个函数可以返回 int 的十六进制值。
std::string encode_utf8(const std::string &str);
通过使用上面的函数,我遍历包含 unicode 的整个字符串,如果当前字符是非 ascii,我将用它的十六进制值替换它。
问题:
用 unicode 遍历字符串并不聪明,因为 unicode char 由多达 4 个字节组成,与普通 char 不同。 因此,一个unicode 字符可以被视为输出垃圾的多个字符。 简单来说,字符串不能被索引。
std::string encode_utf8(const std::wstring &wstr);
再次,我用 unicode 字符遍历整个字符串,如果当前字符是非 ascii,我用它的十六进制值替换它。
问题:
索引现在可以工作,但它返回一个带有相应 utf-32 数字的 wchar_t,但我绝对需要 utf-8 数字。
如何从字符串中获取字符以获取 utf-8 十进制数?
您的输入字符串是 UTF8 编码的,这意味着每个字符都由 1 到 4 个字节编码。 您不能只是扫描字符串并转换它们,除非您的循环了解 Unicode 字符是如何在 UTF8 中编码的。
您需要一个 UTF8 解码器。
幸运的是,如果您只需要解码,那么您可以使用真正轻量级的。 UTF8-CPP几乎是一个标头,并且具有为您提供单个 Unicode 字符的功能。 utf8::next
将为您提供uint32_t
(“最大”字符的代码点适合这种类型的对象)。 现在您可以简单地查看该值是否小于 128:如果是,则转换为char
并追加; 如果不是,请以您认为合适的任何方式序列化整数。
不过,我恳请您考虑这是否真的是您想做的。 你的输出将是模棱两可的。 无法确定其中的一堆数字是实际数字,还是某些非 ASCII 字符的表示。 为什么不坚持使用原始的 UTF8 编码,或者使用 HTML 实体编码或引用打印之类的东西? 这些编码被广泛理解和广泛支持。
我刚刚解决了这个问题:
std::string Tools::encode_utf8(const std::wstring &wstr)
{
std::string utf8_encoded;
//iterate through the whole string
for(size_t j = 0; j < wstr.size(); ++j)
{
if(wstr.at(j) <= 0x7F)
utf8_encoded += wstr.at(j);
else if(wstr.at(j) <= 0x7FF)
{
//our template for unicode of 2 bytes
int utf8 = 0b11000000'10000000;
//get the first 6 bits and save them
utf8 += wstr.at(j) & 0b00111111;
/*
* get the last 5 remaining bits
* put them 2 to the left so that the 10 from 10xxxxxx (first byte) is not overwritten
*/
utf8 += (wstr.at(j) & 0b00000111'11000000) << 2;
//append to the result
std::string temp = Tools::to_hex(utf8);
utf8_encoded.append(temp.insert(0, "\\x").insert(4, "\\x"));
}
else if(wstr.at(j) <= 0xFFFF)
{
//our template for unicode of 3 bytes
int utf8 = 0b11100000'10000000'10000000;
//get the first 6 bits and save them
utf8 += wstr.at(j) & 0b00111111;
/*
* get the next 6 bits
* put them 2 to the left so that the 10 from 10xxxxxx (first byte) is not overwritten
*/
utf8 += (wstr.at(j) & 0b00001111'11000000) << 2;
/*
* get the last 4 remaining bits
* put them 4 to the left so that the 10xx from 10xxxxxx (second byte) is not overwritten
*/
utf8 += (wstr.at(j) & 0b11110000'00000000) << 4;
//append to the result
std::string temp = Tools::to_hex(utf8);
utf8_encoded.append(temp.insert(0, "\\x").insert(4, "\\x").insert(8, "\\x"));
}
else if(wstr.at(j) <= 0x10FFFF)
{
//our template for unicode of 4 bytes
int utf8 = 0b11110000'10000000'10000000'10000000;
//get the first 6 bits and save them
utf8 += wstr.at(j) & 0b00111111;
/*
* get the next 6 bits
* put them 2 to the left so that the 10 from 10xxxxxx (first byte) is not overwritten
*/
utf8 += (wstr.at(j) & 0b00001111'11000000) << 2;
/*
* get the next 6 bits
* put them 4 to the left so that the 10xx from 10xxxxxx (second byte) is not overwritten
*/
utf8 += (wstr.at(j) & 0b00000011'11110000'00000000) << 4;
/*
* get the last 3 remaining bits
* put them 6 to the left so that the 10xxxx from 10xxxxxx (third byte) is not overwritten
*/
utf8 += (wstr.at(j) & 0b00011100'00000000'00000000) << 4;
//append to the result
std::string temp = Tools::to_hex(utf8);
utf8_encoded.append(temp.insert(0, "\\x").insert(4, "\\x").insert(8, "\\x").insert(12, "\\x"));
}
}
return utf8_encoded;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.