在c++中进行不区分大小写字符串比较而不将字符串转换为全大写或全小写的最佳方法是什么?
请指出这些方法是否对unicode友好,以及它们的可移植性如何。
在c++中进行不区分大小写字符串比较而不将字符串转换为全大写或全小写的最佳方法是什么?
请指出这些方法是否对unicode友好,以及它们的可移植性如何。
当前回答
截至2013年初,由IBM维护的ICU项目是一个很好的答案。
http://site.icu-project.org/
ICU是一个“完整的、可移植的Unicode库,密切跟踪行业标准”。对于字符串比较的特定问题,Collation对象将执行您想要的操作。
2012年年中,Mozilla项目在Firefox中采用了ICU进行国际化;您可以在这里跟踪工程讨论,包括构建系统和数据文件大小的问题:
https://groups.google.com/forum/#!topic/mozilla.dev.platform/sVVpS2sKODw https://bugzilla.mozilla.org/show_bug.cgi?id=724529(跟踪) https://bugzilla.mozilla.org/show_bug.cgi?id=724531(构建系统)
其他回答
仅供参考,strcmp()和stricmp()容易受到缓冲区溢出的影响,因为它们只处理到遇到空结束符为止。使用_strncmp()和_strnicmp()更安全。
可以在Unix上使用strcasecmp,在Windows上使用stricmp。
到目前为止还没有提到的一件事是,如果您使用这些方法使用stl字符串,首先比较两个字符串的长度是有用的,因为这个信息已经在string类中提供给您了。如果您正在比较的两个字符串的长度一开始就不相同,这可以防止进行代价高昂的字符串比较。
你说的是一个愚蠢的不区分大小写的比较还是一个完全标准化的Unicode比较?
哑比较不会找到可能相同但二进制不相等的字符串。
例子:
U212B (ANGSTROM SIGN)
U0041 (LATIN CAPITAL LETTER A) + U030A (COMBINING RING ABOVE)
U00C5 (LATIN CAPITAL LETTER A WITH RING ABOVE).
都是等价的,但它们也有不同的二进制表示。
也就是说,Unicode标准化应该是必读的,特别是如果您计划支持韩文,Thaï和其他亚洲语言。
此外,IBM几乎为大多数优化的Unicode算法申请了专利,并将它们公开提供。它们还维护一个实现:IBM ICU
boost的问题在于,你必须与boost相关联并依赖于boost。在某些情况下并不容易(例如android)。
使用char_traits意味着所有的比较都是不区分大小写的,这通常不是你想要的。
这就足够了。它应该是相当有效的。它不处理unicode或任何东西。
bool iequals(const string& a, const string& b)
{
unsigned int sz = a.size();
if (b.size() != sz)
return false;
for (unsigned int i = 0; i < sz; ++i)
if (tolower(a[i]) != tolower(b[i]))
return false;
return true;
}
更新:c++ 14版本(#include <算法>):
bool iequals(const string& a, const string& b)
{
return std::equal(a.begin(), a.end(),
b.begin(), b.end(),
[](char a, char b) {
return tolower(a) == tolower(b);
});
}
c++ 20版本使用std::ranges:
#include <ranges>
#include <algorithm>
#include <string>
bool iequals(const std::string_view& lhs, const std::string_view& rhs) {
auto to_lower{ std::ranges::views::transform(std::tolower) };
return std::ranges::equal(lhs | to_lower, rhs | to_lower);
}
支持unicode的Visual c++字符串函数:http://msdn.microsoft.com/en-us/library/cc194799.aspx
您可能正在寻找的是_wcsnicmp