c++中如何实现字符串的大小写转换_c++ string转大写与小写

std::toupper 和 std::tolower 仅作用于单个 char,需配合 std::transform 与 lambda 逐字符处理,并显式转为 unsigned char;必须传入 std::locale{} 才能正确支持非 ASCII 字符,但无法处理变长转换。

std::toupper 和 std::tolower 不能直接处理 std::string

这两个函数作用于单个 char,不是 std::string。直接传入字符串会编译失败或触发隐式转换陷阱(比如把指针转成 int)。必须逐字符处理。

用 std::transform + lambda 实现安全大小写转换

这是最常用且推荐的方式,避免手动循环出错,也兼容 UTF-8 字节序列(只要 locale 设置正确)。

  • std::transform 要求目标迭代器和源迭代器类型匹配,所以得用 str.begin()str.end()
  • lambda 中调用 std::toupperstd::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{}); });

区分 locale 与 C locale 的行为差异

默认的 C locale 只对 ASCII 字母有效;std::locale{} 依赖系统环境,Linux/macOS 通常生效,Windows 需额外设置(如 std::locale("en_US.UTF-8"))。

  • 不带 locale 参数的 std::toupper(c) 等价于 C 函数,只处理 'a'–'z''A'–'Z'
  • std::locale{} 时,std::toupper('ß')'SS'(德语),但注意:这会改变字符串长度,std::transform 无法处理变长转换
  • 真正需要 Unicode 大小写转换(如处理 emoji、中文拼音、土耳其语 İ)应使用 ICU 或 utf8cpp 库

避免 in-place 转换时的常见错误

下面这段代码看似合理,实则危险:

立即学习“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++ 标准不保证其重载安全性
  • 如果原字符串含 null 字节('\0'),std::string 仍可正常处理,但某些 C 风格函数会截断
C++ 标准库不提供开箱即用的 Unicode 大小写转换,std::toupperstd::tolower 的“安全用法”其实有三层约束:类型转换、locale 选择、以及对变长结果的无能为力——这些恰恰是开发者最容易跳过的细节。