std::字符串 在安全位置截断 UTF-8 的最佳方法
std::string optimal way to truncate utf-8 at safe place
我在 std::string 中有一个有效的 utf-8 编码字符串。我有字节限制。我想截断字符串并添加...at MAX_SIZE - 3 - x
- 其中x
是防止剪切 UTF-8 字符的值。
是否有函数可以根据MAX_SIZE确定x
而无需从字符串的开头开始?
如果您在字符串中有一个位置,并且想要向后查找 UTF-8 字符的开头(因此是一个有效的剪切位置(,这很容易完成。
从序列中的最后一个字节开始。如果最后一个字节的前两位10
,那么它是 UTF-8 序列的一部分,因此请继续备份,直到前两位未10
(或直到您到达起点(。
UTF-8 的工作方式是,基于字节的上位,字节可以是三种情况之一。如果最上面的位是 0
,则字节是 ASCII 字符,接下来的 7 位是 Unicode 码位值本身。如果最上面的位是10
,那么后面的 6 位是多字节序列的额外位。但是多字节序列的开头在前 2 位中使用11
进行编码。
因此,如果一个字节的顶部位不10
,那么它要么是 ASCII 字符,要么是多字节序列的开头。无论哪种方式,它都是一个有效的切割场所。
但请注意,虽然此算法将在代码点边界处中断字符串,但它会忽略 Unicode 字形簇。这意味着可以剔除组合字符,远离它们组合的基本字符;例如,字符中的重音可能会丢失。进行正确的字形聚类分析需要访问 Unicode 表,该表指示代码点是否为组合字符。
但它至少是一个有效的 Unicode UTF-8 字符串。所以这比大多数人做的要好;)
代码如下所示(在 C++14 中(:
auto FindCutPosition(const std::string &str, size_t max_size)
{
assert(str.size() >= max_size, "Make sure stupidity hasn't happened.");
assert(str.size() > 3, "Make sure stupidity hasn't happened.");
max_size -= 3;
for(size_t pos = max_size; pos > 0; --pos)
{
unsigned char byte = static_cast<unsigned char>(str[pos]); //Perfectly valid
if(byte & 0xC0 != 0x80)
return pos;
}
unsigned char byte = static_cast<unsigned char>(str[0]); //Perfectly valid
if(byte & 0xC0 != 0x80)
return 0;
//If your first byte isn't even a valid UTF-8 starting point, then something terrible has happened.
throw bad_utf8_encoded_text(...);
}
相关文章:
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- 通过方法访问结构
- 最小硬币更换问题(自上而下方法)
- C++为构建时间获取QDateTime的可靠方法
- 在C#中处理C++指针而不使用unsafe的最佳方法
- HEX值到wchar_t字符(UTF-8)的转换
- 处理多个异常集合的C++方法
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 有什么方法可以遍历结构吗
- 当类在C++中定义时,有什么方法可以"register"类吗?
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- 使用std::函数映射对象方法
- 有符号的int和int-有没有一种方法可以在C++中区分它们
- C++从另一个类访问公共静态向量的正确方法是什么
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 一种从内存中删除 UTF 字节的方法?
- 有关读取 UTF-8 编码文本时 Ifstream get() 方法行为的说明 (C++)
- 有没有一种简单的方法可以在Visual Studio中编写UTF-8八位字节
- std::字符串 在安全位置截断 UTF-8 的最佳方法