比较wstring时忽略大小写

25

我相信这个问题之前肯定已经有人问过,但是我找不到。是否有任何内置的方法(即使用std::wstring的方法或算法)来不区分大小写比较两个wstring对象?


6
请注意,不区分大小写的比较取决于语言环境。 - avakar
1
请查看 https://dev59.com/BHVD5IYBdhLWcg3wWKLc,我建议使用Boost解决方案或提取c_str并使用wcscasecmp/_wcsicmp。 - Hasturkun
@Hasturkun:谢谢你提供的链接。我模糊地记得在 Stack Overflow 上读过这个。 - Naveen
8个回答

33

如果您不介意使用微软的实现,您可以使用在<string.h>中定义的此函数。

int _wcsnicmp(
   const wchar_t *string1,
   const wchar_t *string2,
   size_t count 
);

但如果你想要最佳的性能/兼容性/功能比率,你很可能需要看一下boost库(它的部分内容属于STL)。以下是一个简单的示例(取自不同问题的不同答案):

#include <boost/algorithm/string.hpp>

std::wstring wstr1 = L"hello, world!";
std::wstring wstr2 = L"HELLO, WORLD!";

if (boost::iequals(wstr1, wstr2))
{
    // Strings are identical
}

4
缺少字符串字面量的 L 编码前缀。 - mloskot

6

使用标准库:

bool comparei(wstring stringA , wstring stringB)
{
    transform(stringA.begin(), stringA.end(), stringA.begin(), toupper);
    transform(stringB.begin(), stringB.end(), stringB.begin(), toupper);

    return (stringA == stringB);
}

wstring stringA = "foo";
wstring stringB = "FOO";
if(comparei(stringA , stringB))
{
    // strings match
}

12
如果(stringA == stringB) 强制我留下评论! :) 应该翻译为 return (stringA == stringB)。 (说明:此处涉及程序代码语言,建议在翻译时保持原文的符号和格式,以便更好地传达意思。) - Idan K
4
在一些语言中,将字符串转换为大写然后再转回来,得到的结果可能与原先不同,因此这种解决方案在一些区域上并不适用。 - Stan
3
你不仅仅是比较了两个字符串,而且无论结果如何都将两个字符串全部转换成了大写字母。尝试编写一个参数签名为 bool compare(const wstring stringA, const wstring stringB) 的方法,然后修复这个算法。 - Zak
1
应该使用 towupper。 - Nayan

5

您可以使用std::tolower()将字符串转换为小写,或者使用函数wcscasecmpc_str()进行不区分大小写的比较。

这是一个比较函数对象,您也可以直接使用:

struct ci_less_w
{
  bool operator() (const std::wstring & s1, const std::wstring & s2) const
  {
      #ifndef _WIN32
            return wcscasecmp(s1.c_str(), s2.c_str()) < 0;
      #else
            return _wcsicmp(s1.c_str(), s2.c_str()) < 0;
      #endif
  }
};

1
我认为被要求使用标准库解决方案。 - anon

2
#include <algorithm>
#include <string>
#include <cstdio>


 bool icase_wchar_cmp(wchar_t a, wchar_t b)
{
  return std::toupper(a) == std::toupper(b);
}


bool icase_cmp(std::wstring const& s1, std::wstring const& s2)
{
  return (s1.size() == s2.size()) &&
             std::equal(s1.begin(), s1.end(), s2.begin(),
                              icase_wchar_cmp);
}



int main(int argc, char** argv)
{
  using namespace std;

  wstring str1(L"Hello"), str2(L"hello");

  wprintf(L"%S and %S are %S\n", str1.c_str(), str2.c_str(),
              icase_cmp(str1,str2) ? L"equal" : L"not equal");

  return 0;
}

2
谈到英语?!虽然我更喜欢我的可爱的Boost :)
bool isequal(const std::wstring& first, const std::wstring& second)
{
    if(first.size() != second.size())
        return false;

    for(std::wstring::size_type i = 0; i < first.size(); i++)
    {
        if(first[i] != second[i] && first[i] != (second[i] ^ 32))
            return false;
    }

    return true;
}

4
+1. (second[i] ^ 32) 很有趣。我从来不知道 ASCII 是这样设计的! - Sahas
3
这将认为[{相同,*与换行符相同,以及许多其他不准确的情况。此外,在处理宽字符串时假设为英语几乎肯定是错误的。 - interjay

2

1
如果您需要字符串在使用运算符==或!=进行比较时始终不区分大小写,那么一种可能的优雅解决方案是重新定义char_traits :: compare方法。
定义自己的结构。 例如:
struct my_wchar_traits: public std::char_traits< wchar_t>
{
    static int compare( const char_type* op1, const char_type* op2, std::size_t num) 
    {
       // Implementation here... any of the previous responses might help...
    } 
};

然后,定义您自己的不区分大小写的字符串:

typedef std::basic_string< wchar_t, my_wchar_traits> my_wstring;

-1
你可以使用mismatch()或lexicographical_compare()。这是Scott Meyers在Effective STL中建议的,第35项。

2
能否提供一个没有这本书的人可以看懂的例子? - Stan
2
请注意,这两个函数默认情况下不会进行大小写不敏感的比较。您仍然需要编写一个比较字符大小写不敏感的函数,并将其传递给这些函数。 - Geerad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接