SuperGoA
SuperGoA

Reputation: 245

strcasecmp() : A Non-Standard Function?

The other day I created a post over at CodeReview. One person who answered my question suggested that I refrain from using strcasecmp() because the "function is non-standard [and] this makes [my] code non-portable." This is how I used it:

int playGame()
{

    char scanned[3];
    printf("Do you wish to play tick-tack-toe?\n");
    scanf("%s", scanned);
    if(strcasecmp(scanned,"yes")==0)
        startGame();

    else
    {
        if (strcasecmp(scanned,"no")==0 || strcasecmp(scanned,"nah")==0 || strcasecmp(scanned,"naw")==0)
        {
            printf("That's too bad!/nThis program will now end.");
            return 1;
        }
        printf("Not valid input!/nThis program will now end.");
        return 1;
    }
return 0;
}

Can someone explain more in-depth and why strcasecmp() has these limitations?

Upvotes: 16

Views: 35925

Answers (4)

chux
chux

Reputation: 154173

strcasecmp() : A Non-Standard Function?

Short answer: As strcasecmp() is not in the C standard library, that make it non-C standard.

strcasecmp() is defined in popular standards such as 4.4BSD, POSIX.1-2001.

The definition of case-less functions opens the door to the nit-picky details. These often involve the positive or negative result of case-less compares, not just the 0 or non-0 as used by OP. In particular:

In the POSIX locale, strcasecmp() and strncasecmp() shall behave as if the strings had been converted to lowercase and then a byte comparison performed. The results are unspecified in other locales.

The trouble with this is with upper and lower case letters that do not have a 1 to 1 mapping. Consider a locale that has E, e and é but no É, yet toupper('é') -- > 'E' . Then with "as if the strings had been converted to lowercase", 'E' has 2 choices.

As a candidate portable solution consider one that round trips the letter (to upper then to lower) to cope with non 1-to-1 mappings:

int SGA_stricmp(const char *a, const char *b) {
  int ca, cb;
  do {
     ca = * (unsigned char *)a;
     cb = * (unsigned char *)b;
     ca = tolower(toupper(ca));
     cb = tolower(toupper(cb));
     a++;
     b++;
   } while (ca == cb && ca != '\0');
   return ca - cb;
}

Alternate code needed with select implementations with UCHAR_MAX > INT_MAX.

If you do not want to round-trip the values use:

     ca = tolower(ca);
     cb = tolower(cb);

Detail: toupper() and tolower() only defined for int in the range of unsigned char and EOF. * (unsigned char *)a used as *a may have negative values.

Upvotes: 9

An alternative would be to canonize the input to lower case using tolower(), which is standard. Then you could use the standard strcmp().

Upvotes: -1

набиячлэвэли
набиячлэвэли

Reputation: 4677

"The function is non-standard" means, that the function declaration and contract aren't specified in The C International Standard.

"This makes code non-portable" means, that implementations aren't required to implement strcasecmp(), and therefore your code is not fully standard-compliant and not guaranteed to be compiled by strictly standard-conforming compilers.

strcasecmp() is itself a part of the POSIX.1-2001 and 4.4BSD specifications (link).

Upvotes: 1

rost0031
rost0031

Reputation: 1926

strcasecmp is not in the C or C++ standard. It's defined by POSIX.1-2001 and 4.4BSD.

If your system POSIX or BSD compliant, you'll have no problems. Otherwise, the function will be unavailable.

Upvotes: 7

Related Questions