26

I am sure this would have been asked before but couldn't find it. Is there any built in (i.e. either using std::wstring's methods or the algorithms) way to case insensitive comparison the two wstring objects?

3
  • 6
    Note, that case-insensitive comparisons are locale-dependent. Commented Jul 1, 2009 at 9:24
  • 1
    see stackoverflow.com/questions/11635/… , I'd recommend either the Boost solution or extracting c_str and using wcscasecmp/_wcsicmp Commented Jul 1, 2009 at 9:35
  • @Hasturkun: Thanks for the link. I vaguely remembered reading this on SO. Commented Jul 1, 2009 at 10:04

8 Answers 8

34

If you don't mind being tied to Microsoft implementation you can use this function defined in <string.h>

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

But if you want best performance/compatibility/functionality ratio you will probably have to look at boost library (part of it is stl anyway). Simple example (taken from different answer to different question):

#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 } 
Sign up to request clarification or add additional context in comments.

1 Comment

The L encoding-prefix is missing from the string literals
6

Using the standard library:

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 } 

4 Comments

that if(stringA == stringB) forces me to leave a comment! :) should be return (stringA == stringB)
This solution will not work in several locales, in some languages when you convert to uppercase and then back you get different strings.
You didn't just compare the strings, you have actually made both strings UPPERCASE regardless of the outcome. Try writing a method with the signature bool compare(const wstring stringA, const wstring stringB), then fix this algorithm.
Should have used towupper.
5

You can use std::tolower() to convert the strings to lowercase or use the function wcscasecmp to do a case insensitive compare on the c_str()'s.

Here is a comparison functor you can use directly as well:

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 Comment

I think a Standard Library solution was asked for.
2

You could use the boost string algorithms library. Its a header only library as long as you're not going to do regex. So you can do that very easily.

http://www.boost.org/doc/libs/1_39_0/doc/html/string_algo.html

Comments

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; } 

Comments

2

Talking about English right ?! though I would go with my lovely 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; } 

2 Comments

+1. (second[i] ^ 32) is interesting. I never knew this was how ascii was designed!
This will consider [ to be the same as {, and * to be the same as a newline, along with many other such inaccuracies. Besides, assuming English when dealing with wide strings is almost certainly wrong.
1

If you need that the string will always make case insensitive comparation (when using operators == or !=), then a possible elegant solution is to redefine char_traits::compare method.

Define your own structure. Example

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... } }; 

Then, define your own case insensitive string:

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

Comments

-1

You can use mismatch() or lexicographical_compare(). This is suggested by Scott Meyers in Effecitve STL, item 35.

2 Comments

Example for those of us that do not have that book would be nice.
Note that neither of these functions will compare case-insensitively by default. You would still have to write a function that compares characters case-insensitively and pass it to those functions.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.