std::toupper 和 std::tolower 仅作用于单个 char,需配合 std::transform 与 lambda 逐字符处理,并显式转为 unsigned char;必须传入 std::locale{} 才能正确支持非 ASCII 字符,但无法处理变长转换。
这两个函数作用于单个 char,不是 std::string。直接传入字符串会编译失败或触发隐式转换陷阱(比如把指针转成 int)。必须逐字符处理。
这是最常用且推荐的方式,避免手动循环出错,也兼容 UTF-8 字节序列(只要 locale 设置正确)。
std::transform 要求目标迭代器和源迭代器类型匹配,所以得用 str.begin() 到 str.end()
std::toupper 或 std::tolower 时,必须显式转成 unsigned char,否则遇到负值 char(如 UTF-8 多字节首字节)会 UB 并指定 std::locale{} 才能正确处理非 ASCII 字符(如 é、ß、中文拼音等)std::string s = "Hello 世界!";
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return std::toupper(c, std::locale{}); });
默认的 C locale 只对 ASCII 字母有效;std::locale{} 依赖系统环境,Linux/macOS 通常生效,Windows 需额外设置(如 std::locale("en_US.UTF-8"))。
std::toupper(c) 等价于 C 函数,只处理 'a'–'z' 和 'A'–'Z'
std::locale{} 时,std::toupper('ß') → 'SS'(德语),但注意:这会改变字符串长度,std::transform 无法处理变长转换
下面这段代码看似合理,实则危险:
立即学习“C++免费学习笔记(深入)”;
for (auto& c : str) {
c = std::toupper(c); // ❌ 缺少 unsigned char 转换,char 为 signed 时可能传入负值
}
更糟的是:
std::string upper = str; std::transform(str.begin(), str.end(), upper.begin(), ::toupper); // ❌ ::toupper 是 C 版本,不支持 locale,且参数类型不安全
static_cast(c) 包裹输入::toupper,它来自 ,C++ 标准不保证其重载安全性'\0'),std::string 仍可正常处理,但某些 C 风格函数会截断std::toupper 和 std::tolower 的“安全用法”其实有三层约束:类型转换、locale 选择、以及对变长结果的无能为力——这些恰恰是开发者最容易跳过的细节。