Build Your Own strcasestr() Function

I was a bit surprised the other day. I’d written code on my Macintosh and tried to run it on the PC. Because I usually write generic stuff, I figured that the code would compile and run on both systems. But it didn’t compile.

The culprit was a function called strcasestr(). It’s a cousin to the standard C library string comparison function, strstr(). The word case sandwiched inside means that the strings are compared in a case-insensitive way. Otherwise, both functions are identical.

So I set out to concoct my own rendition of strcasestr().

First, here’s sample code that prompts the user to type two strings. The strings are compared by using the strstr() function:

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

int main()
{
    char first[32],second[32];

/* Fetch strings */
    puts("String comparison");
    printf("First string: ");
    fgets(first,32,stdin);
    printf("Second string: ");
    fgets(second,32,stdin);

/* Compare */
    if( strcmp(first,second)==0 )
        puts("Strings match");
    else
        puts("Strings don't match");

    return(0);
}

Here’s a sample run, where you can see how the same word doesn’t match when the letters are uppercase or lowercase:

String comparison
First string: this
Second string: THIS
Strings don't match

To fix this problem, I crafted a new function, case_compare(). I wanted it to mimic the behavior of strstr(): Values returned are positive, negative, or zero depending on how the strings compare. Not knowing how strstr() operates internally, I chose to use a single character comparison, shown in the following code:

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

int case_compare(char *a, char *b)
{
    char c;

    while(*a)
    {
        c = toupper(*a) - toupper(*b);
        if( c != 0 )
            return(c);
        a++;
        b++;
    }
    return(c);
}

int main()
{
    char first[32],second[32];

/* Fetch strings */
    puts("String comparison");
    printf("First string: ");
    fgets(first,32,stdin);
    printf("Second string: ");
    fgets(second,32,stdin);

/* Compare */
    if( case_compare(first,second)==0 )
        puts("Strings match");
    else
        puts("Strings don't match");

    return(0);
}

The case_compare() function’s while loop at Line 8 plows through string a with string b along for the ride. At each position, character *a is compared with character *b, but only when the toupper() function has converted both to uppercase (Line 10).

When the result in variable c is zero, then the characters match (case insensitive). If not, the if test at Line 11 catches the mismatch and the comparison value (positive or negative) is returned in Line 12. Otherwise, both string pointers are incremented and the comparison continues.

The final return statement at Line 16 passes the value of variable c back to the calling function, which is zero when both strings match. That mimics the behavior of the strstr() function, although I’m not certain exactly how that function works internally.

The bottom line is that my case_compare() function works on any platform, whether the library offers strcasestr() or not. That’s the result I was looking for.

Leave a Reply