“字符串减法”实为过滤非中文字符,即从utf-8编码的std::string中仅保留unicode汉字(如0x4e00–0x9fff等区间),需手动解析utf-8字节序列并判断码点范围。

什么是“字符串减法”:实际是过滤非中文字符
“字符串减法”不是 C++ 标准操作,用户真正想做的是:给定一个 std::string(或 std::u8string),从中**只保留 Unicode 中文字符(即汉字)**,丢弃英文字母、数字、标点、空白、Emoji、ASCII 符号等。关键难点在于:C++ 标准库不直接识别“中文字符”,必须靠 Unicode 码点范围判断。
用 UTF-8 编码 + 手动解析字节:最稳妥的方案
如果输入是 std::string 且内容为 UTF-8 编码(常见于 Linux/macOS 文件、HTTP 响应、现代 C++20 u8"..." 字面量),不能按 char 逐个遍历——因为一个汉字占 3 个字节,单字节判断必然错。必须做 UTF-8 解码:
- 检查首字节确定字节数(0xxxxxxx → 1 字节;110xxxxx → 2 字节;1110xxxx → 3 字节;11110xxx → 4 字节)
- 合并后续字节,还原出 Unicode 码点(
uint32_t) - 判断码点是否落在中文常用区间:
0x4E00–0x9FFF(基本汉字)、0x3400–0x4DBF(扩展 A)、0x20000–0x2A6DF(扩展 B,需 4 字节 UTF-8)
示例核心逻辑(不依赖第三方库):
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
std::string keep_chinese(const std::string& s) {
std::string out;
size_t i = 0;
while (i = s.size()) break;
cp = ((b0 & 0x1F) = s.size()) break;
cp = ((b0 & 0x0F) = s.size()) break;
cp = ((b0 & 0x07) = 0x4E00 && cp = 0x3400 && cp = 0x20000 && cp <h3>为什么不用 <code>std::wstring</code> + <code>iswalpha</code>?</h3><p>常见误区:把 <code>std::string</code> 强转成 <code>std::wstring</code>,再用 <code>iswalpha</code> 或区域设置(<code>std::locale</code>)判断。这不可靠:</p>
-
std::wstring在 Windows 是 UTF-16,在 Linux/macOS 通常是 UCS-4,但原始字符串大概率是 UTF-8,强转导致乱码 -
iswalpha依赖当前 locale,中文 locale 下可能包含全角 ASCII、平假名等,不等于“仅汉字” -
std::iswctype(c, std::wctype("han"))非标准,GCC/Clang 不支持
用 ICU 或 Boost.Locale 的前提和代价
若项目已引入 ICU 库,可用 icu::UnicodeString + uscript_getScript 精确识别汉字脚本:
- 准确率高,支持扩展区、兼容汉字、部首等
- 但 ICU 体积大、编译慢、部署复杂,小工具没必要
- Boost.Locale 同样依赖外部构建,且
boost::locale::is<code>utf8仍需手动查码点
真正要兼顾正确性与轻量,手写 UTF-8 解码 + 码点区间判断仍是首选。别忽略 4 字节字符(扩展 B 区),否则会漏掉“?”“?”这类生僻字。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










