Reputation: 245
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
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
Reputation: 1
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
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