文本存储在std::string
中。
如果文本是 8 位 ASCII,那么它真的很容易:
text.pop_back();
但是,如果是 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 中码位的前导字节是模式0xxxxxxx
或11xxxxxx
,所有非前导字节的形式都是 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。