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

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


当前回答

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

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

其他回答

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

Boost::iequals在string的情况下不兼容utf-8。 你可以使用boost::locale。

comparator<char,collator_base::secondary> cmpr;
cout << (cmpr(str1, str2) ? "str1 < str2" : "str1 >= str2") << endl;

Primary -- ignore accents and character case, comparing base letters only. For example "facade" and "Façade" are the same. Secondary -- ignore character case but consider accents. "facade" and "façade" are different but "Façade" and "façade" are the same. Tertiary -- consider both case and accents: "Façade" and "façade" are different. Ignore punctuation. Quaternary -- consider all case, accents, and punctuation. The words must be identical in terms of Unicode representation. Identical -- as quaternary, but compare code points as well.

只需使用strcmp()区分大小写,使用strcmpi()或stricmp()进行不区分大小写的比较。它们都在头文件<string.h>

格式:

int strcmp(const char*,const char*);    //for case sensitive
int strcmpi(const char*,const char*);   //for case insensitive

用法:

string a="apple",b="ApPlE",c="ball";
if(strcmpi(a.c_str(),b.c_str())==0)      //(if it is a match it will return 0)
    cout<<a<<" and "<<b<<" are the same"<<"\n";
if(strcmpi(a.c_str(),b.c_str()<0)
    cout<<a[0]<<" comes before ball "<<b[0]<<", so "<<a<<" comes before "<<b;

输出

apple和apple是一样的

A在b之前,所以苹果在球之前