C++ string class - case insensitve compare?

Discussion in 'Mac Programming' started by toddburch, Jun 8, 2007.

  1. toddburch macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #1
    I've looked in an online reference (cppreference.com) and my C++ book, but I can't find a string insensitive compare(). There are certainly C-String case insensitive compares, but I'd rather use a C++ compare if there is one.

    (Plus, now I'm on a mission to find it...)

    Thanks, Todd
     
  2. toddburch thread starter macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #2
    I guess I could use a bitset OR with a known longer-than-I-needed string of all blanks (X'20') and then test for a lower case compare...
     
  3. iSee macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #3
    It's almost beyond belief, but I don't believe the standard C++ library has a case-insensetive.

    If you don't want or need to worry about locales, then:
    _stricmp( str1.c_str(), str2.c_str() )
    Is the simplest solution (also quite efficient).

    Locales complicate things quite a bit (well, it's really the deficiencies of the standard library that makes this so complicated).
    Lemme see if I can find a link for something that deals with locales...
    here's one: http://lafstern.org/matt/col2_new.pdf
    I don't know if he really knows what he's talking about, but it sounds like he does. He goes on for a while about this so you can understand the issue, but you can skip to the bottom and check out the last code block for his best solution.
     
  4. toddburch thread starter macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #4
    Thanks iSee. Yeah, he's probably correct. However, for my purposes, I'll be working with 7-bit ASCII character codes, and I think this code chunk will be good enough.

    Thanks for the confirmation - glad to see I wasn't just missing it.

    Todd

    Code:
    #include <iostream>
    #include <string> 
    using namespace std ; 
    
    bool case_insensitive_compare( string a, string b) { 
    	char char1, char2, blank = ' ' ;   
    	int len1 = a.length() ; 
    	int len2 = b.length() ;  
    
    	for (int i = 0 ; i < min(len1, len2) ; ++i ) { 
    		char1 = *(a.substr(i,1).data()) ;   // get a single character
    		char2 = *(b.substr(i,1).data()) ; 
    		char1 |= blank ;   // make lowercase for compare 
    		char2 |= blank ; 
    		if ( char1 == char2 ) continue ; 
    		return false ; 
    	} 
    	if (len1 != len2) return false ; 
    	return true ; 
    } 
    
    int main (int argc, char * const argv[]) {
    	string input ; 
    	string hello = "Hello" ; 
    	bool result ; 
    	
    	std::cout << "Enter the word 'hello', in any form of upper or lower case characters." << endl ; 
    	std::cin >> input ; 
    	
    	result = case_insensitive_compare(input, hello) ; 
    
        std::cout << "Result of compare of " << input << " to " << hello << " is " << (result ? "true" : "false" )  << endl ;
        return 0;
    }
     
  5. toddburch thread starter macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #5
    OK, I give up. Where did you come up with _stricmp?

    Todd
     
  6. wittegijt macrumors member

    Joined:
    Feb 18, 2007
    Location:
    Eindhoven
    #6
    It's a Windows thing. Unix libraries use strcasecmp, it's in <strings.h>.

    Wittegijt.
     
  7. iSee macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #7
    OK, sorry for throwing that out there.

    I thought it was part of the standard C library, but it isn't. It just appears, unofficially, under different names, in various implementations of the C library. So a case-insensitive compare isn't an official part of the official C library either. Geeze. It seems like such a huge omission. Under VS, it's _stricmp() or stricmp(), under CodeWarrior for Mac it's stricmp() or strcasecmp(), and under OS X 10.4/Xcode it's strcasecmp().

    Come to think of it, the leading underscore should have given me the hint.

    I guess if you want to conform to the C standard you have to implement your own using tolower() (or toupper()) in a loop.

    Let's see a first pass might be (This is off the top of my head, NOT tested code):
    Code:
    #include <ctype.h>
    ...
    int mystricmp(const char* str1, const char* str2)
    {
      if (str1 == str2)
        return 0;
      else if (str1 == NULL)
        return -1;
      else if (str2 == NULL)
        return 1;
      else {
        while (tolower(*str1) == tolower(*str2) && *str1 != 0 && *str2 != 0)
        {
          ++str1;
          ++str2;
        }
        if (*str1 < *str2)
          return -1;
        else if (*str1 > *str2)
          return 1;
        else
          return 0;
      }
    }
    
    Anyway, again, sorry for the bad advice. I guess I haven't really done a lot of C/C++ coding on Mac OS X where I wanted to avoid the OS API (CFString, etc.) since the CodeWarrior days...
     
  8. toddburch thread starter macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #8
    Ahhhha. Makes sense. Thanks Wittegijt & iSee. I've been reading my "Encyclopedia C" (Sybex, 1991) and all (or a lot of, at least) the non-standard keywords by Microsoft all have an underscore for the first character as well. Should have tipped me off.

    OK, now to strcasecmp(). The cppreference.com web site I've been using looks to be only standard C/C++. I've googled for a Mac OS X XCode specific reference site and haven't found one. What's a good Mac OS X C++ reference website? Or, is there a C++ reference built into XCode help somewhere and I just haven't found it? Or, failing all that, is there one on the Apple Development Center that I've missed too?

    As big as the XCode diskimages are that I download and install when prompted, surely there's a language reference in there someone - I mean, the Java stuff I downloaded initially was HUGE.

    Todd
     
  9. Krevnik macrumors 68040

    Krevnik

    Joined:
    Sep 8, 2003
    #9
    It is there, but I don't think it goes over the C functions that are in the POSIX layer, just all of Apple's additions to POSIX. You can use the terminal to access man pages on some of these functions. 'man strcasecmp' will take you right to the page talking about that function and describe how to use it.
     
  10. iSee macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #10
    Poking around in Xcode, I found a link to this page:

    http://developer.apple.com/documentation/Darwin/Reference/ManPages/index.html

    which is a table of contents for everything in the OS X man pages, including the C library functions.

    The Xcode reference library accesses man pages in addition to other resources, so these are all available through Xcode (I use "Find Selected Text in API Reference" all the time).

    It looks like the C functions are in section 3. It looks like the documentation for each function contains a "standard" or "history" section that gives some info on what standard the function complies with. Apparently strcasecmp() was moved from "string.h" to "strings.h" for compliance reasons. I'm not sure in exactly what way that makes it compliant. I guess it means that non-standard functions should not appear in string.h, so they moved it to a different header file.
     
  11. toddburch thread starter macrumors 6502a

    Joined:
    Dec 4, 2006
    Location:
    Katy, Texas
    #11
    That's a great reference page! I figured info like that was in there somewhere!
     

Share This Page