My Own strcasecmp() Function – Round Three

The strcasecmp() function isn’t part of the standard C library, though many compilers feature it. As having the function is handy, I wrote about crafting your own version back in 2019. Alas, that implementation is flawed.

The first flaw was pointed out to me by Professor Dr. Greg Byrd of North Carolina State University. He noted that the function doesn’t necessarily return the difference between mismatched characters. Some compilers instead return -1, 0, or 1. In fact, the strcasecmp() man page, as well as the man page for strcmp(), claim that the return value is less than, greater than, or equal to zero.

My first update to the code accounted for the return value, as noted by Dr. Byrd. I added a function sign(), which returns -1, 0, or 1 based on the value of a passed integer. Even with this update, however, the code remains flawed.

I didn’t discover another issue with my strcasecmp() function until I used it to compare two similar strings, one longer than the other:

"I drink co"
"I drink coffee and tea"

The program reports that both strings match. However, when I use the (non-standard) library function strcasecmp(), as well as the strcmp() function, the strings are reported as not matching.

For reference, here is the while loop in my strcasecmp() function that compares strings, s1 and s2:

offset = 0;
ch = 0;
while( *(s1+offset) != '\0' )
{
    /* check for end of s2 */
    if( *(s2+offset)=='\0')
        return( *(s1+offset) );

    a = (unsigned)*(s1+offset);
    b = (unsigned)*(s2+offset);
    ch = toupper(a) - toupper(b);
    if( ch<0 || ch>0 )
        return( sign(ch) );
    offset++;
}

In the loop, you see both strings are tested for their terminating condition: s1 in the while loop’s condition, then an if statement tests for the terminating null character in s2. This construction is wrong, as it doesn’t properly detect the end of the second string.

The fix is easy: Place both comparisons as the while loop’s condition:

while( *(s1+offset)!='\0' || *(s2+offset)!='\0' )

I updated the code, as well as the testing statements to compare similar strings of different lengths. Here’s the output:

I drink coffee v. I drink coffee = match
I drink coffee v. I DRINK COFFEE = match
I drink coffee v. I drink tea = no match
I drink coffee v. I drink co = no match
I drink coffee v. I drink coffee and tea = no match

This flaw was discovered when I tried to use my own strcasecmp() function in the unique words series of programs back in this Lesson from earlier this month. My version of the strcasecmp() function incorrectly matched “to” and “too.” I’m embarrassed that my code didn’t work, but happy that I discovered the flaw and was able to fix the code with an update.

Click here to view my fully updated code on Github. This third version is hopefully the final update.

Leave a Reply