2

I want to compare to string pointers while ignoring their case. I cant think of any C function that can do that.

For example:

ToMMy == tommy == TOMMY == tOMmy etc.....

Does anyone know how this can be done in C?

Brandon
  • 401
  • 5
  • 20
  • 3
    Take a look at [strcasecmp](http://publib.boulder.ibm.com/infocenter/zos/v1r10/topic/com.ibm.zos.r10.bpxbd00/rsrccm.htm) in string.h – Peyman Mohamadpour Feb 07 '16 at 05:09
  • Do you mean the string values themselves or the identifiers in C? – e0k Feb 07 '16 at 05:10
  • 3
    Suggest you do a Stackoverflow and/or web search before asking questions in the future. Many answers already. For example: [Case Insensitive String comp in C](http://stackoverflow.com/questions/5820810/case-insensitive-string-comp-in-c) – kaylum Feb 07 '16 at 05:13
  • Interested in a true/false compare or an order compare like the result of `strcmp()`? – chux - Reinstate Monica Feb 07 '16 at 05:47

3 Answers3

1

strcasecmp() is not a standard C function, but it is on most compilers.

Write your own:

int strnocasecmp(char const *a, char const *b)
{
    for (;; a++, b++) {
        int d = tolower((unsigned char)*a) - tolower((unsigned char)*b);
        if (d != 0 || !*a)
            return d;
    }
}

Don't forget the #include <ctype.h> library for tolower().

SegFault
  • 2,526
  • 4
  • 21
  • 41
  • 2
    This program may invoke undefined behavior for passing out-of-range value to `tolower()` if `char` is signed. – MikeCAT Feb 07 '16 at 05:13
1

If it is OK to support only single-byte English alphabets to ignore cases, just convert each characters to lower case (or upper case) and compare.

#include <ctype.h>

int cmp(const char *a, const char *b) {
    while (*a || *b) {
        int c1 = tolower((unsigned char)*a++);
        int c2 = tolower((unsigned char)*b++);
        if (c1 != c2) return c1 > c2 ? 1 : -1;
    }
    return 0;
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • You can use a quick bit-shift as well and eliminate the `ctype.h` dependency. To convert to lower and compare: `int c1 = (unsigned)*a++ | (1 << 5);` or to upper `(unsigned)*a++ & ~(1 << 5);` It's not any better than `tolower`, but emphasizes the 6th-bit as the lower-case bit in 7-bit ASCII. – David C. Rankin Feb 07 '16 at 08:44
  • @DavidC.Rankin In my opinion, that would be worse than `tolower` because it harms readability. Using `tolower` makes the intention more clear. – PC Luddite Feb 11 '16 at 11:58
  • I disagree, that is what *comments* are for. e.g. `/* convert to lowercase & compare */`. Without any comments, much of what is done in C isn't immediately apparent. This would certainly be an instance where comment would be called for. There is nothing wrong with `tolower` if you are not doing a huge number of conversions, but if you are, using the case bit can help optimize the routine. – David C. Rankin Feb 11 '16 at 19:25
0

If you have access to strcasecmp (POSIX) in string.h, that's probably your best bet.

strcasecmp("TOMMY", "tOMmy") == 0

Otherwise, it's not too hard to make your own.

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

bool check_strings(const char* str1, const char* str2)
{
    if (strlen(str1) != strlen(str2))
        return false;

    do {
        if (tolower(*str1++) != tolower(*str2++))
            return false;
    } while(*str1 || *str2)

    return true;
}
PC Luddite
  • 5,883
  • 6
  • 23
  • 39
  • This program may invoke undefined behavior for passing out-of-range value to `tolower()` if `char` is signed. – MikeCAT Feb 07 '16 at 12:41
  • @MikeCAT If you see anything, feel free to edit the code. I just sort of rattled it off although I'm pretty sure it works (I obviously didn't work on this too hard). – PC Luddite Feb 07 '16 at 22:05