stricmp, comparing two strings in C case-insensitively

For some reason, I found that the stricmp() function isn’t implemented in standard C. So I implemented mine, which works for ASCII strings only.

Maybe it’s not that all interesting, but I’ll post it here, if someone needs it:

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

int
stricmp (const char *s1, const char *s2)
{
   if (s1 == NULL) return s2 == NULL ? 0 : -(*s2);
   if (s2 == NULL) return *s1;

   char c1, c2;
   while ((c1 = tolower (*s1)) == (c2 = tolower (*s2)))
   {
     if (*s1 == '\0') break;
     ++s1; ++s2;
   }

   return c1 - c2;
}

int
main ()
{
   const char *a = NULL;
   const char *b = NULL;
   const char *c = "piPpO";
   const char *d = "pIpPa";
   const char *e = "";
   const char *f = "pippOdue";

   printf ("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
      stricmp (a, c),  // <0
      stricmp (c, a),  // >0
      stricmp (c, d),  // >0
      stricmp (c, c),  // =0
      stricmp (d, c),  // <0
      stricmp (e, e),  // =0
      stricmp (c, f)); // <0

   return 0;
}
Advertisements

2 Responses to stricmp, comparing two strings in C case-insensitively

  1. michele says:

    Hi Matteo, I have copied your example of stricmp ’cause I was really bored It was not included in C6000 TI software library, and IMHO it is very well written. I would ask your opinion about a fact. Recently my son argued with his IT teacher about the use of break statement. I always used it in my code, but it seems the teacher won’t to use it, ’cause “it disrupts the structured C environment” and so on… Please note also the teacher won’t use the switch() construct.. while I’ve written tons of stati machines using only switches… What do you think about this?

    • Dear Michele,

      as per the break; statement (or any other programming keyword in languages like C or C++), I can say it has a lot of legitimate uses. While I understand teachers that discourage it, to teach newbies the benefits of explicit exit conditions from loops, I find it just as readable when the exit condition is in the middle of the loop. However, your mileage may vary.

      For instance:

      int a, b;
      for (int i = 0; i < 100; i++)
      {
         a = f ();
         if (a == 0) 
            break;
         b += 1;
      }
      

      Now, I could rewrite it with a boolean variable, making clear my intent:

      int a, b;
      bool invalid_a = false;
      for (int i = 0; !invalid_a && i < 100; i++)
      {
        a = f ();
        if (a == 0)
          invalid_a = true;
        else
          b += 1;
      }
      

      Notice how, while being clearer that the meaning of a == 0 (but this is just the example being contrived, it could be clear by giving a good name to a itself), it forces me to put the side-effect on b on the conditional else branch.

      I find this annoying: while it's true that b should be incremented only if a is not invalid, it's not immediately clear:
      – that the whole loop will exit at the end of this iteration
      – whether b has some logical relationship with the above test over a

      I really think that one should always choose in favor of readability. break; might not be the best idea in the world for many situations (especially in C++, where if you have an exceptional behaviour, you should really use an exception! — and conversely, if you don't, you should use break in place of an exception), but sometimes I argue it can indeed improve readability.

      Even goto has some legitimate uses! It's abuses that should be avoided.

      As for switches… especially for checking enum values, they're much better than the if ... then ... else if ... else ... counterpart. I really don't see why someone shouldn't use them. Considering they only work with cases sporting constant literals, I can't find any reason not to use them when you need to check if a variable matches one or more of a limited set of unrelated constant values.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: