9
void
main()
{
    std::string str1 = "abracadabra";
    std::string str2 = "AbRaCaDaBra";

    if (!str1.compare(str2)) {
        cout << "Compares"
    }
}

How can I make this work? Bascially make the above case insensitive. Related question I Googled and here

http://msdn.microsoft.com/en-us/library/zkcaxw5y.aspx

there is a case insensitive method String::Compare(str1, str2, Bool). Question is how is that related to the way I am doing.

Santhosh Kumar
  • 381
  • 1
  • 5
  • 13
  • Thanks, but there they use boost. My question is is there a way to do the above work without using boost? str1.compare(str2) works and a logical extension to it is to support case insensitive. Is there a simple easy way out? – Santhosh Kumar May 29 '14 at 22:27
  • David your example appears appealing. I might use it. Thanks – Santhosh Kumar May 29 '14 at 22:30
  • 2
    The link you gave is to a .NET function which is emphatically *not* part of standard C++ and has no relation to it. – Mark Ransom May 29 '14 at 22:32
  • Got it, thanks pardon my ignorance – Santhosh Kumar May 29 '14 at 22:52
  • I think that the right way of doing this is to define a trait like in [this answer](https://stackoverflow.com/questions/11635/case-insensitive-string-comparison-in-c#answer-2886589). That allows you to create a map or a set with case insensitive strings without much work. If you just need to compare two strings in one place, you can always use the `strcasecmp()` function which will also handle the locale properly. – Alexis Wilke Mar 13 '22 at 19:24

2 Answers2

26

You can create a predicate function and use it in std::equals to perform the comparison:

bool icompare_pred(unsigned char a, unsigned char b)
{
    return std::tolower(a) == std::tolower(b);
}

bool icompare(std::string const& a, std::string const& b)
{
    if (a.length()==b.length()) {
        return std::equal(b.begin(), b.end(),
                           a.begin(), icompare_pred);
    }
    else {
        return false;
    }
}

Now you can simply do:

if (icompare(str1, str)) {
    std::cout << "Compares" << std::endl;
}
Herman Schaaf
  • 46,821
  • 21
  • 100
  • 139
David G
  • 94,763
  • 41
  • 167
  • 253
  • This has the advantage that you can set locale and `std::tolower` respects that ; as mentioned elsewhere you're still out of luck if you try to use this on UTF-8 – M.M May 29 '14 at 22:57
  • @0x499602D2: There's a _HUGE_ difference between non-ASCII and non-BMP. Your code works for ASCII, but not for any codepoints above 127. BMP doesn't come into this (though it fails for BMP too) – Mooing Duck May 29 '14 at 23:05
  • This isn't a criticism btw, it's not easy to handle UTF-8 properly – M.M May 29 '14 at 23:06
  • Thanks to all I learnt a lot and finally ended up using this:void main() { std::string str1 = "abracadabra"; std::string str2 = "AbRaCaDaBra"; std::transform(str2.begin(), str2.end(), str2.begin(), tolower); if (!str1.compare(str2)) { std::cout << "compares"; } } – Santhosh Kumar May 30 '14 at 00:15
  • 3
    I'm not sure this code correctly answers the question. Shouldn't this use `std::equal` instead of `std::lexicographical_compare`? `std::lexicographical_compare` returns `true` if the first argument is __less__ than the second and requires a predicate with the same semantics. – Blastfurnace Mar 14 '15 at 18:01
  • @Blastfurnace seems to be correct here. When implemented as-is, you'll get all kinds of fun results. Like "cow" == "house", or "car" == "cat". – Brian McFarland Oct 12 '15 at 23:06
  • Trying to compile this in Visual Studio 2015 and getting error: no instance of function template "std::tolower" matches the argument list argument types are: (unsigned char) What am I doing wrong? – Дмитрий Кутейко Aug 12 '16 at 14:35
  • @ДмитрийКутейко Include `` – David G Aug 12 '16 at 17:24
2

Covert both to lower case and then compare them.

Converting to lower:

for(int i = 0; i < str1.size(); i++)
{
  str[i] = tolower(str[i]);
}

Comparing strings:

if (str1.compare(str2) == 0) { ... }

A zero value indicates that both strings are equal.

EDIT

This can be used to avoid for loop: http://www.cplusplus.com/reference/algorithm/transform/

std::transform(in.begin(),in.end(),std::back_inserter(out),tolower);
Andro
  • 2,232
  • 1
  • 27
  • 40