如何在 C++ 中通过表情符号拆分字符串
How to split a string by emojis in C++
我正在尝试获取一串表情符号并将它们拆分为每个表情符号的向量
给定字符串:
std::string emojis = "";
我正在尝试获取:
std::vector<std::string> splitted_emojis = {"", "", "", "", "", "", "", ""};
编辑
我试过:
std::string emojis = "";
std::vector<std::string> splitted_emojis;
size_t pos = 0;
std::string token;
while ((pos = emojis.find("")) != std::string::npos)
{
token = emojis.substr(0, pos);
splitted_emojis.push_back(token);
emojis.erase(0, pos);
}
但它似乎在几秒钟后抛出了 terminate called after throwing an instance of 'std::bad_alloc'
。
尝试使用以下命令检查字符串中有多少表情符号时:
std::string emojis = "";
std::cout << emojis.size() << std::endl; // returns 32
它 returns 一个更大的数字,我认为是 unicode 数据。我不太了解 unicode 数据,但我想弄清楚如何检查表情符号的数据何时开始和结束,以便能够将字符串拆分为每个表情符号
我肯定会建议您使用具有更好 unicode 支持的库(所有大型框架都支持),但在紧要关头,您可以知道 UTF-8 编码将 Unicode 字符分布在多个字节上,并且第一个字节的第一位决定一个字符由多少字节组成。
我从 boost 偷了一个函数。 split_by_codepoint 函数对输入字符串使用迭代器并使用前 N 个字节(其中 N 由字节计数函数确定)构造一个新字符串并将其推送到 ret 向量。
// Taken from boost internals
inline unsigned utf8_byte_count(uint8_t c)
{
// if the most significant bit with a zero in it is in position
// 8-N then there are N bytes in this UTF-8 sequence:
uint8_t mask = 0x80u;
unsigned result = 0;
while(c & mask)
{
++result;
mask >>= 1;
}
return (result == 0) ? 1 : ((result > 4) ? 4 : result);
}
std::vector<std::string> split_by_codepoint(std::string input) {
std::vector<std::string> ret;
auto it = input.cbegin();
while (it != input.cend()) {
uint8_t count = utf8_byte_count(*it);
ret.emplace_back(std::string{it, it+count});
it += count;
}
return ret;
}
int main() {
std::string emojis = u8"";
auto split = split_by_codepoint(emojis);
std::cout << split.size() << std::endl;
}
请注意,此函数只是将一个字符串拆分为每个包含一个代码点的 UTF-8 字符串。确定字符是否为表情符号留作练习:UTF-8-解码任何 4 字节字符并查看它们是否在正确的范围内。
我正在尝试获取一串表情符号并将它们拆分为每个表情符号的向量
给定字符串:
std::string emojis = "";
我正在尝试获取:
std::vector<std::string> splitted_emojis = {"", "", "", "", "", "", "", ""};
编辑
我试过:
std::string emojis = "";
std::vector<std::string> splitted_emojis;
size_t pos = 0;
std::string token;
while ((pos = emojis.find("")) != std::string::npos)
{
token = emojis.substr(0, pos);
splitted_emojis.push_back(token);
emojis.erase(0, pos);
}
但它似乎在几秒钟后抛出了 terminate called after throwing an instance of 'std::bad_alloc'
。
尝试使用以下命令检查字符串中有多少表情符号时:
std::string emojis = "";
std::cout << emojis.size() << std::endl; // returns 32
它 returns 一个更大的数字,我认为是 unicode 数据。我不太了解 unicode 数据,但我想弄清楚如何检查表情符号的数据何时开始和结束,以便能够将字符串拆分为每个表情符号
我肯定会建议您使用具有更好 unicode 支持的库(所有大型框架都支持),但在紧要关头,您可以知道 UTF-8 编码将 Unicode 字符分布在多个字节上,并且第一个字节的第一位决定一个字符由多少字节组成。
我从 boost 偷了一个函数。 split_by_codepoint 函数对输入字符串使用迭代器并使用前 N 个字节(其中 N 由字节计数函数确定)构造一个新字符串并将其推送到 ret 向量。
// Taken from boost internals
inline unsigned utf8_byte_count(uint8_t c)
{
// if the most significant bit with a zero in it is in position
// 8-N then there are N bytes in this UTF-8 sequence:
uint8_t mask = 0x80u;
unsigned result = 0;
while(c & mask)
{
++result;
mask >>= 1;
}
return (result == 0) ? 1 : ((result > 4) ? 4 : result);
}
std::vector<std::string> split_by_codepoint(std::string input) {
std::vector<std::string> ret;
auto it = input.cbegin();
while (it != input.cend()) {
uint8_t count = utf8_byte_count(*it);
ret.emplace_back(std::string{it, it+count});
it += count;
}
return ret;
}
int main() {
std::string emojis = u8"";
auto split = split_by_codepoint(emojis);
std::cout << split.size() << std::endl;
}
请注意,此函数只是将一个字符串拆分为每个包含一个代码点的 UTF-8 字符串。确定字符是否为表情符号留作练习:UTF-8-解码任何 4 字节字符并查看它们是否在正确的范围内。