在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(构建系统)

其他回答

迟来的派对,但这里有一个变种,使用std::locale,因此正确处理土耳其语:

auto tolower = std::bind1st(
    std::mem_fun(
        &std::ctype<char>::tolower),
    &std::use_facet<std::ctype<char> >(
        std::locale()));

提供一个函子,使用活动区域设置将字符转换为小写,然后可以通过std::transform生成小写字符串:

std::string left = "fOo";
transform(left.begin(), left.end(), left.begin(), tolower);

这也适用于基于wchar_t的字符串。

Boost包含一个方便的算法:

#include <boost/algorithm/string.hpp>
// Or, for fewer header dependencies:
//#include <boost/algorithm/string/predicate.hpp>

std::string str1 = "hello, world!";
std::string str2 = "HELLO, WORLD!";

if (boost::iequals(str1, str2))
{
    // Strings are identical
}

仅供参考,strcmp()和stricmp()容易受到缓冲区溢出的影响,因为它们只处理到遇到空结束符为止。使用_strncmp()和_strnicmp()更安全。

我正试图从所有的帖子中拼凑出一个好的答案,所以帮我编辑一下:

这里有一个这样做的方法,虽然它转换字符串,并不是Unicode友好的,它应该是可移植的,这是一个加:

bool caseInsensitiveStringCompare( const std::string& str1, const std::string& str2 ) {
    std::string str1Cpy( str1 );
    std::string str2Cpy( str2 );
    std::transform( str1Cpy.begin(), str1Cpy.end(), str1Cpy.begin(), ::tolower );
    std::transform( str2Cpy.begin(), str2Cpy.end(), str2Cpy.begin(), ::tolower );
    return ( str1Cpy == str2Cpy );
}

从我所读到的,这比stricmp()更可移植,因为stricmp()实际上不是std库的一部分,而只是由大多数编译器供应商实现。

要获得真正的Unicode友好实现,似乎必须跳出std库。一个很好的第三方库是IBM ICU (Unicode国际组件)

此外,boost::iequals为进行这种比较提供了一个相当好的实用程序。

支持unicode的Visual c++字符串函数:http://msdn.microsoft.com/en-us/library/cc194799.aspx

您可能正在寻找的是_wcsnicmp