如何拆分包含表情符号与拉丁字母的字符串,将每个表情作为独立单词
C++ 混合普通单词与表情字符串拆分方案
需求定义
- 输入:UTF-8编码的字符串,混合普通单词、空格、Unicode表情
- 输出:
std::vector<std::string>,规则如下:- 空格分隔的普通单词作为单个元素
- 每个表情单独作为一个元素,连续多个表情各自独立拆分
- 示例效果:
输入:
"The Quick 🙂 Brown Fox Jumps 🙂🙂🙂 Over Lazy Dog"
输出:["The", "Quick", "🙂", "Brown", "Fox", "Jumps", "🙂", "🙂", "🙂", "Over", "Lazy", "Dog"]
轻量无依赖实现方案(C++11及以上支持)
无需引入第三方库,直接通过UTF-8码点识别实现,代码如下:
#include <vector> #include <string> #include <utility> #include <cstdint> // 判断Unicode码点是否属于常见表情范围 bool is_emoji(uint32_t cp) { return (cp >= 0x1F600 && cp <= 0x1F64F) // 面部表情 || (cp >= 0x1F300 && cp <= 0x1F5FF) // 通用象形符号 || (cp >= 0x1F680 && cp <= 0x1F6FF) // 交通与标识符号 || (cp >= 0x2600 && cp <= 0x26FF) // 杂项符号 || (cp >= 0x2700 && cp <= 0x27BF) // 装饰符号 || (cp >= 0x1F900 && cp <= 0x1F9FF); // 补充表情符号 } // 读取UTF-8字符串中当前位置的Unicode码点,返回码点值和占用字节数 std::pair<uint32_t, int> parse_next_codepoint(const char* str_ptr) { uint8_t first_byte = static_cast<uint8_t>(*str_ptr); if (first_byte < 0x80) { return {static_cast<uint32_t>(first_byte), 1}; } else if (first_byte < 0xE0) { uint32_t cp = ((first_byte & 0x1F) << 6) | (static_cast<uint8_t>(*(str_ptr + 1)) & 0x3F); return {cp, 2}; } else if (first_byte < 0xF0) { uint32_t cp = ((first_byte & 0x0F) << 12) | ((static_cast<uint8_t>(*(str_ptr + 1)) & 0x3F) << 6) | (static_cast<uint8_t>(*(str_ptr + 2)) & 0x3F); return {cp, 3}; } else { uint32_t cp = ((first_byte & 0x07) << 18) | ((static_cast<uint8_t>(*(str_ptr + 1)) & 0x3F) << 12) | ((static_cast<uint8_t>(*(str_ptr + 2)) & 0x3F) << 6) | (static_cast<uint8_t>(*(str_ptr + 3)) & 0x3F); return {cp, 4}; } } std::vector<std::string> split_string_with_emoji(const std::string& input) { std::vector<std::string> result; std::string current_plain_word; int pos = 0; const int str_len = input.size(); while (pos < str_len) { auto [codepoint, byte_count] = parse_next_codepoint(input.c_str() + pos); if (is_emoji(codepoint)) { // 先存入之前积攒的普通单词 if (!current_plain_word.empty()) { result.push_back(current_plain_word); current_plain_word.clear(); } // 单独存入当前表情 result.push_back(input.substr(pos, byte_count)); } else if (codepoint == ' ') { // 空格作为普通单词分隔符 if (!current_plain_word.empty()) { result.push_back(current_plain_word); current_plain_word.clear(); } } else { // 普通字符追加到当前单词 current_plain_word.append(input, pos, byte_count); } pos += byte_count; } // 存入最后剩余的普通单词 if (!current_plain_word.empty()) { result.push_back(current_plain_word); } return result; }
编译与使用说明
直接使用支持C++11及以上标准的编译器编译即可,编译命令示例:g++ your_file.cpp -o split_demo -std=c++11
如果需要支持带肤色、联合类的多码点表情,可以扩展is_emoji的判断范围,或者引入ICU Unicode库做更专业的边界识别。
内容的提问来源于stack exchange,提问作者green123
相关产品推荐
相关产品推荐

