在c++中进行不区分大小写字符串比较而不将字符串转换为全大写或全小写的最佳方法是什么?

请指出这些方法是否对unicode友好,以及它们的可移植性如何。


当前回答

如果是在POSIX系统上,可以使用strcasecmp。不过,这个函数不是标准C语言的一部分,在Windows上也不可用。这将对8位字符执行不区分大小写的比较,只要区域设置为POSIX。如果区域设置不是POSIX,则结果是未定义的(因此它可能进行本地化比较,也可能不进行)。没有宽字符的等效版本。

如果做不到这一点,大量历史上的C库实现都有stricmp()和strnicmp()函数。Windows上的Visual c++通过在它们前面加上下划线来重命名它们,因为它们不是ANSI标准的一部分,所以在那个系统中它们被称为_stricmp或_strnicmp。一些库可能还具有宽字符或多字节等效函数(通常命名为wcsicmp, mbcsicmp等)。

C和c++在很大程度上都不了解国际化问题,所以除了使用第三方库之外,这个问题没有好的解决方案。如果需要用于C/ c++的健壮库,请参阅IBM ICU (Unicode国际组件)。ICU适用于Windows和Unix系统。

其他回答

在c++中比较两个字符串的一个简单方法是使用_stricmp

// Case insensitive (could use equivalent _stricmp)  
result = _stricmp( string1, string2 );  

如果你想使用std::string,一个例子:

std::string s1 = string("Hello");
if ( _stricmp(s1.c_str(), "HELLO") == 0)
   std::cout << "The string are equals.";

更多信息请访问:https://msdn.microsoft.com/it-it/library/e0z9k731.aspx

如果是在POSIX系统上,可以使用strcasecmp。不过,这个函数不是标准C语言的一部分,在Windows上也不可用。这将对8位字符执行不区分大小写的比较,只要区域设置为POSIX。如果区域设置不是POSIX,则结果是未定义的(因此它可能进行本地化比较,也可能不进行)。没有宽字符的等效版本。

如果做不到这一点,大量历史上的C库实现都有stricmp()和strnicmp()函数。Windows上的Visual c++通过在它们前面加上下划线来重命名它们,因为它们不是ANSI标准的一部分,所以在那个系统中它们被称为_stricmp或_strnicmp。一些库可能还具有宽字符或多字节等效函数(通常命名为wcsicmp, mbcsicmp等)。

C和c++在很大程度上都不了解国际化问题,所以除了使用第三方库之外,这个问题没有好的解决方案。如果需要用于C/ c++的健壮库,请参阅IBM ICU (Unicode国际组件)。ICU适用于Windows和Unix系统。

看到std:: lexicographical_compare:

// lexicographical_compare example
#include <iostream>  // std::cout, std::boolalpha
#include <algorithm>  // std::lexicographical_compare
#include <cctype>  // std::tolower

// a case-insensitive comparison function:
bool mycomp (char c1, char c2) {
    return std::tolower(c1) < std::tolower(c2);
}

int main () {
    char foo[] = "Apple";
    char bar[] = "apartment";

    std::cout << std::boolalpha;

    std::cout << "Comparing foo and bar lexicographically (foo < bar):\n";

    std::cout << "Using default comparison (operator<): ";
    std::cout << std::lexicographical_compare(foo, foo + 5, bar, bar + 9);
    std::cout << '\n';

    std::cout << "Using mycomp as comparison object: ";
    std::cout << std::lexicographical_compare(foo, foo + 5, bar, bar + 9, mycomp);
    std::cout << '\n';

    return 0;
}

Demo

假设您正在寻找一个方法,而不是一个已经存在的神奇函数,坦率地说,没有更好的方法。对于有限的字符集,我们都可以使用聪明的技巧编写代码片段,但在一天结束时,你必须转换字符。

这种转换的最佳方法是在比较之前进行转换。当涉及到编码方案时,这为您提供了很大的灵活性,而实际的比较操作符应该忽略这一点。

当然,你可以在你自己的字符串函数或类后面“隐藏”这个转换,但你仍然需要在比较之前转换字符串。

可以在Unix上使用strcasecmp,在Windows上使用stricmp。

到目前为止还没有提到的一件事是,如果您使用这些方法使用stl字符串,首先比较两个字符串的长度是有用的,因为这个信息已经在string类中提供给您了。如果您正在比较的两个字符串的长度一开始就不相同,这可以防止进行代价高昂的字符串比较。