如何在C++中删除 UTF-8 字符串的最后一个字符



文本存储在std::string中。

如果文本是 8 位 ASCII,那么它真的很容易:

text.pop_back();

但是,如果是 UTF-8 文本呢?
据我所知,标准库中没有我可以使用的 UTF-8 相关函数。

如果您要使用 UTF-8 库,

您确实需要一个 UTF-8 库 UTF-8 .但是,对于此任务,我认为这样的事情可能就足够了:

void pop_back_utf8(std::string& utf8)
{
    if(utf8.empty())
        return;
    auto cp = utf8.data() + utf8.size();
    while(--cp >= utf8.data() && ((*cp & 0b10000000) && !(*cp & 0b01000000))) {}
    if(cp >= utf8.data())
        utf8.resize(cp - utf8.data());
}
int main()
{
    std::string s = "κόσμε";
    while(!s.empty())
    {
        std::cout << s << 'n';
        pop_back_utf8(s);
    }
}

输出:

κόσμε
κόσμ
κόσ
κό
κ

它依赖于这样一个事实,即 UTF-8 编码有一个起始字节,后跟几个延续字节。可以使用提供的按位运算符检测这些继续字节

您可以做的是弹出字符,直到到达代码点的前导字节。UTF8 中码位的前导字节是模式0xxxxxxx11xxxxxx,所有非前导字节的形式都是 10xxxxxx 。这意味着您可以检查第一位和第二位以确定是否有前导字节。

bool is_leading_utf8_byte(char c) {
    auto first_bit_set = (c & 0x80) != 0;
    auto second_bit_set = (c & 0X40) != 0;
    return !first_bit_set || second_bit_set;
}
void pop_utf8(std::string& x) {
    while (!is_leading_utf8_byte(x.back()))
        x.pop_back();
    x.pop_back();
}

这当然不会进行错误检查,并假设您的字符串是有效的 utf-8。

最新更新