不能直接用 substr 截断字符串,因为它只按字节截取、不处理 UTF-8 多字节字符,易切在中文或 emoji 中间导致乱码;应按 Unicode 字符数或显示宽度截断并补全,且需手动解析 UTF-8。

截断字符串时为什么不能直接用 substr?
因为 substr 只截取、不补全,且遇到中文或 UTF-8 多字节字符容易切在中间,导致乱码。比如 "你好world" 按字节长度 6 截取,可能得到 "你好wor" 这种破损字符串。
真正需要的是:按「显示宽度」或「字符数」截断 + 补全(空格/点/省略号),且兼容 Unicode。
- 若按字节数截断 → 必须先做 UTF-8 解码校验,否则踩坑
- 若按 Unicode 码点数截断 → 简单但不等于视觉宽度(如 emoji 占 2 个终端列)
- 若按显示宽度(如
wcwidth)→ 更准,但需引入<cwchar></cwchar>和平台支持
用 std::string + 手动 UTF-8 解码实现安全截断
标准库不直接提供 UTF-8 字符计数,得自己跳过前导字节。下面函数按「Unicode 字符个数」截断,并右补空格:
std::string truncate_utf8(const std::string& s, size_t max_chars, char pad = ' ') {
if (s.empty()) return std::string(max_chars, pad);
<pre class="brush:php;toolbar:false;">size_t chars = 0;
size_t i = 0;
while (i <p>}</p>注意:i 是字节偏移,chars 是实际字符数。补全是按「缺几个字符就填几个 pad」,不是按字节补。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
用 std::wstring_convert(C++11/14)还是别用了
std::wstring_convert<:codecvt_utf8>></:codecvt_utf8> 在 C++17 被弃用,且 Windows 上 wchar_t 是 UTF-16,Linux 是 UCS-4,行为不一致。实测在 macOS 或某些 glibc 版本下会崩溃或漏解码。
- 不要依赖
std::wstring做中间转换 —— 兼容性差、开销大 - 第三方库如
utf8cpp更稳,但仅需截断时,手写 UTF-8 解码更轻量 - 如果项目已用
boost::locale,可用boost::locale::conv::utf_to_utf<char32_t></char32_t>,但引入依赖不划算
终端显示宽度补全要用 wcwidth 而非字符数
比如 "??"(程序员 emoji)是 1 个 Unicode 字符,但终端占 2 列;"一" 占 2 列,"a" 占 1 列。此时该用 wcwidth(POSIX)或跨平台封装:
#include <cwchar>
int display_width(wchar_t wc) {
return wcwidth(wc); // 返回 -1(控制字符)、0(不可见)、1 或 2
}</cwchar>
但 wcwidth 接收 wchar_t,你得先把 UTF-8 转成 char32_t 再 cast —— 这步容易出错。实际项目中,若只面向英文+中文混合文本,按字符数截断+固定宽度补全已够用;真要精确对齐表格列,建议用成熟库如 icu 或 utf8proc。
最易被忽略的点:补全字符本身也有显示宽度。用空格补可以,但用 "…" 就得预留 1 或 2 列 —— 它是 1 个字符、1 列宽,但视觉上常替代 2~3 字符,需业务层约定。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










