最稳妥的做法是用std::equal配合std::tolower逐字符比较:必须对每个char先static_cast<unsigned char>再调用std::tolower,否则负值字符会导致未定义行为;长度不等时std::equal自动返回false。

std::equal 配合 std::tolower 比较两个字符串
直接用 == 或 std::strcmp 都区分大小写,C++ 标准库没提供原生忽略大小写的比较函数。最稳妥的做法是逐字符转换为小写再比,std::equal + std::tolower 是推荐方案:
- 必须对每个字符都调用
static_cast<unsigned char></unsigned>再传给std::tolower,否则遇到负值char(如某些 locale 下的非 ASCII 字符)会触发未定义行为 - 两个字符串长度不等时,
std::equal会自动返回false,无需提前检查长度 - 示例:
bool icase_equal(const std::string& a, const std::string& b) { if (a.size() != b.size()) return false; return std::equal(a.begin(), a.end(), b.begin(), [](char ca, char cb) { return std::tolower(static_cast<unsigned char>(ca)) == std::tolower(static_cast<unsigned char>(cb)); }); }
Windows 下用 _stricmp 或 strcasecmp
跨平台代码里要小心:Windows 的 _stricmp 和 POSIX 的 strcasecmp 行为基本一致,但头文件和链接要求不同:
-
_stricmp在<string.h>或<cstring>中声明,仅 Windows 可用;strcasecmp在<strings.h>(注意不是<string.h>)中,Linux/macOS 支持 - 两者都不处理 Unicode,只适用于单字节编码(如 ASCII、GBK),遇到 UTF-8 多字节序列会出错
- 若项目已限定 Windows 平台,用
_stricmp(a.c_str(), b.c_str()) == 0最快,但别在跨平台代码里硬写
std::locale 与 std::toupper 的陷阱
有人试图用 std::use_facet<:ctype>>(std::locale()).toupper()</:ctype>,这其实更危险:
- 默认
std::locale()依赖系统环境,同一份代码在中文 Windows 和英文 Linux 上可能表现不同 -
std::toupper的 facet 版本不接受char直接调用,必须用std::vector<char></char>批量转换,开销大且易写错 - 真正需要 locale 感知(比如土耳其语的 I/i 规则)时才考虑它,普通 ASCII 场景纯属过度设计
std::ranges::equal(C++20)简化写法
C++20 引入 std::ranges::equal,语法更干净,但底层逻辑没变:
立即学习“C++免费学习笔记(深入)”;
- 仍需手动转小写,例如:
std::ranges::equal(a, b, {}, [](char x, char y) { return std::tolower(static_cast<unsigned char>(x)) == std::tolower(static_cast<unsigned char>(y)); }); - 不支持
std::string_view与const char*直接混用,传参前得统一成相同类型 - 编译器需开启 C++20(如
g++ -std=c++20),老项目慎用
std::equal 方案就够了。真正容易被忽略的是 static_cast<unsigned char></unsigned> 这一步——漏掉它,只要字符串里有非 ASCII 字符(比如用户输入带中文、德语变音符号),就可能崩溃或误判。


















