

新闻资讯
技术学院std::string.length() 返回字节数而非字符数,UTF-8 中文占3字节,导致长度误判;应使用 std::mbrtowc、utf8::distance 或 C++20 std::u8string 配合 UTF-8 工具计算真实字符数。
std::string.length() 算不准中文字符串长度因为 std::string 是字节容器,.length() 返回的是字节数,不是字符数。UTF-8 编码下,一个中文字符占 3 字节(如 "你好" 的 .length() 是 6),而 GBK 下占 2 字节。直接用它当“字符长度”会出错,尤其在截断、对齐、UI 显示等场景。
std::wstring + std::wcslen() 前必须确保编码正确把多字节字符串(如 UTF-8)直接 reinterpret_cast 成 wchar_t* 是常见错误。Windows 默认 wchar_t 是 UTF-16(2 字节),Linux/macOS 通常是 UTF-32(4 字节),但 std::mbstowcs() 行为依赖当前 locale。不设对 locale,转换会失败或乱码。
MultiByteToWideChar(CP_UTF8, ...)
std::from_chars(C++17+)或第三方库(如 ICU、utf8cpp)std::setlocale(LC_ALL, "zh_CN.UTF-8"); // Linux std::setlocale(LC_ALL, "Chinese_China.936"); // Windows GBK(慎用)
std::mbrtowc() 是安全计算 UTF-8 字符数的底层方法它逐字节解析 UTF-8 序列,返回每个字符对应的 wchar_t
宽度(实际是字节数),适合手动计数。比全量转 wstring 更轻量,也避开了 locale 依赖。
size_t utf8_char_count(const char* s) {
if (!s) return 0;
size_t count = 0;
mbstate_t state = {};
const char* p = s;
while (*p) {
wchar_t wc;
size_t r = std::mbrtowc(&wc, p, MB_CUR_MAX, &state);
if (r == static_cast(-1) || r == static_cast(-2)) break; // 无效序列
if (r > 0) {
count++;
p += r;
} else {
p++; // 单字节 ASCII
}
}
return count;
} 注意:MB_CUR_MAX 在 UTF-8 环境下是 4,但实际中文最多 3 字节;mbrtowc 要求 state 初始化为零,否则多字节字符跨调用会出错。
立即学习“C++免费学习笔记(深入)”;
std::u8string(C++20)配合第三方 UTF-8 工具
std::u8string 语义上明确是 UTF-8 字符串,但标准库仍未提供原生字符计数函数。目前最稳妥的做法仍是:
utf8::distance()(轻量头文件):int len = utf8::distance(str.begin(), str.end());
utf8::distance() 更健壮真正容易被忽略的点:字符串是否以 null 结尾?是否含嵌入的 boost::text::utf8_length()?\0 和 mbrtowc 都按首个 utf8::distance 截断,生产环境需先确认数据来源可信。