8

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.

Community
  • 1
  • 1
CoffeeRain
  • 4,460
  • 4
  • 31
  • 50
  • What standard libraries that are available depend on which version of C++ compiler you plan on using to compile your binary. For example, C++0x has regex support. For older compilers, you can use stricmp. – Alan Feb 07 '12 at 20:05
  • How do you expect to compare two strings *without iterating over them*? Do *none* of the answers to the linked question help you at all? – johnsyweb Feb 07 '12 at 20:59
  • @Johnsyweb I already found an answer that was simple and did **not** involve iterating over them. – CoffeeRain Feb 07 '12 at 22:01
  • 1
    @CoffeeRain: `strncasecmp` **does** iterate over them. – johnsyweb Feb 07 '12 at 22:02
  • @Johnsyweb I saw that in Googling for an answer and I mentioned it in my post. The suggested answer didn't work for me. And I meant that I didn't have to manually write a function to iterate over it. – CoffeeRain Feb 07 '12 at 23:02
  • @CoffeeRain: There is more than one answer on that question, including this one, http://stackoverflow.com/a/332713/78845, which is an expanded version of your accepted answer. – johnsyweb Feb 07 '12 at 23:26
  • 5
    @arx `stricmp()` is _not_ available everywhere: it's a Microsoftism (and is now spelled `_stricmp()` anyway). Neither is `strcasecmp()`, which is a POSIX extension. It's mind-boggling that there's no still standard way to do a case-insensitive string comparison in C, but there you are. (As for C++, apparently you either roll your own case-insensitive strings with `char_traits`, or use boost.) – rsfinn Jun 19 '13 at 22:47

5 Answers5

17

strncasecmp

The strcasecmp() function performs a byte-by-byte comparison of the strings s1 and s2, ignoring the case of the characters. It returns an integer less than, equal to, or greater than zero if s1 is found, respectively, to be less than, to match, or be greater than s2.

The strncasecmp() function is similar, except that it compares no more than n bytes of s1 and s2...

gnat
  • 6,213
  • 108
  • 53
  • 73
7

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
}
Greg Humphreys
  • 968
  • 1
  • 7
  • 11
  • Boost was the one that I linked to... I don't have that. – CoffeeRain Feb 07 '12 at 20:00
  • 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. – Greg Humphreys Feb 09 '12 at 15:38
  • 2
    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. – Fadecomic Oct 31 '12 at 19:50
  • 1
    Why not use `boost::iequals` since you are using boost? – Deqing May 15 '15 at 05:22
3

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);
whtlnv
  • 2,109
  • 1
  • 25
  • 26
  • 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 Feb 07 '12 at 19:59
  • 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. – Some Guy Apr 21 '20 at 02:39
2

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;
}
davideanastasia
  • 366
  • 1
  • 13
2

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;
}
Praetorian
  • 106,671
  • 19
  • 240
  • 328