Case insensitive string comparison C++

69,444

Solution 1

usually what I do is just compare a lower-cased version of the string in question, like:

if (foo.make_this_lowercase_somehow() == "stack overflow") {
  // be happy
}

I believe boost has built-in lowercase conversions, so:

#include <boost/algorithm/string.hpp>    

if (boost::algorithm::to_lower(str) == "stack overflow") {
  //happy time
}

Solution 2

why don't you you make everything lower case and then compare?

tolower()

  int counter = 0;
  char str[]="HeLlO wOrLd.\n";
  char c;
  while (str[counter]) {
    c = str[counter];
    str[counter] = tolower(c);
    counter++;
  }

  printf("%s\n", str);

Solution 3

I just wrote this, maybe it can be useful to somebody:

int charDiff(char c1, char c2)
{
    if ( tolower(c1) < tolower(c2) ) return -1;
    if ( tolower(c1) == tolower(c2) ) return 0;
    return 1;
}

int stringCompare(const string& str1, const string& str2)
{
    int diff = 0;
    int size = std::min(str1.size(), str2.size());
    for (size_t idx = 0; idx < size && diff == 0; ++idx)
    {
        diff += charDiff(str1[idx], str2[idx]);
    }
    if ( diff != 0 ) return diff;

    if ( str2.length() == str1.length() ) return 0;
    if ( str2.length() > str1.length() ) return 1;
    return -1;
}

Solution 4

You can write a simple function to convert the existing string to lower case as follows:

#include <string>
#include <ctype.h>
#include <algorithm>
#include <iterator>
#include <iostream>

std::string make_lowercase( const std::string& in )
{
  std::string out;

  std::transform( in.begin(), in.end(), std::back_inserter( out ), ::tolower );
  return out;
}

int main()
{
  if( make_lowercase( "Hello, World!" ) == std::string( "hello, world!" ) ) {
    std::cout << "match found" << std::endl;
  }

  return 0;
}
Share:
69,444
CoffeeRain
Author by

CoffeeRain

I breath periodically

Updated on September 22, 2020

Comments

  • CoffeeRain
    CoffeeRain almost 4 years

    I know there are ways to do case ignore comparison that involve iterating through strings or one good one on SO needs another library. I need to put this on other computers that might not have it installed. Is there a way to use the standard libraries to do this? Right now I am just doing...

    if (foo == "Bar" || foo == "bar")
    {
    cout << "foo is bar" << endl;
    }
    
    else if (foo == "Stack Overflow" || foo == "stack Overflow" || foo == "Stack overflow" || foo == "etc.")
    {
    cout << "I am too lazy to do the whole thing..." << endl;
    }
    

    This could drastically improve the readability and usability of my code. Thanks for reading this far.

  • CoffeeRain
    CoffeeRain over 12 years
    I was trying that, but it wasn't working very well. Could you provide an example? I'll try to post my error code...
  • CoffeeRain
    CoffeeRain over 12 years
    Boost was the one that I linked to... I don't have that.
  • Greg Humphreys
    Greg Humphreys over 12 years
    boost is free in every sense, you could just grab the to_lower algorithm out of there if you cannot install it for some reason.
  • Fadecomic
    Fadecomic over 11 years
    The return value of to_lower is void. You have to apply to_lower first, and then compare as usual. On gcc, the above will give you a 'void value not ignored as it ought to be' error.
  • Deqing
    Deqing about 9 years
    Why not use boost::iequals since you are using boost?
  • Some Guy
    Some Guy about 4 years
    Please don't declare variables in a wider scope than they need to be visible in. The variable 'c' is used entirely within the body of the 'while' loop, so there's no need to declare it outside of the loop. Likewise, if this was made a 'for' loop, the variable 'counter' could be declared inside of the first clause of the for loop as well. It's not good to pollute outer scopes with variables that don't need to be there: this invites bugs and accidental reuse of variables. Also, it's much better to immediately initialize a variable at its point of declaration than to leave it uninitialized.