c-strcasecmp():一个非标准函数



前几天我在CodeReview上创建了一个帖子。一位回答我问题的人建议我不要使用strcasecmp(),因为"函数是非标准的,这使[我的]代码不可移植。"我就是这样使用它的:

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;
}

有人能更深入地解释一下strcasecmp()为什么有这些限制吗?

strcasecmp不在C或C++标准中。它由POSIX.1-2001和4.4BSD.定义

如果您的系统符合POSIX或BSD,您将不会有任何问题。否则,该功能将不可用。

简单回答:由于strcasecmp()不在C标准库中,因此它是非标准的。

strcasecmp()是在诸如4.4BSD、POSIX.1-2001之类的流行标准中定义的。

无大小写函数的定义为挑剔的细节打开了大门。这些通常涉及无病例比较的阳性或阴性结果,而不仅仅是OP使用的0或非0。特别是:

在POSIX区域设置中,strcasecmp()和strncasecmp()的行为应类似于字符串已转换为小写,然后执行字节比较。其他区域设置中未指定结果。

问题在于大小写字母没有1到1的映射。考虑具有Eeé但没有Étoupper('é')->'E'。然后用";就好像字符串已被转换成小写";,'E'有2种选择。

作为一个候选的可移植解决方案,考虑一个往返字母(从上到下)以处理非1对1映射的解决方案:

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 != '');
   return ca - cb;
}

如果您不想往返,则使用以下值:

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

细节:toupper()tolower()仅在unsigned charEOF范围内为int定义。用作CCD_ 16的CCD_ 15可以具有负值。

"函数是非标准的"意味着函数声明和约定没有在C国际标准中指定。

"这使得代码不可移植"意味着不需要实现strcasecmp(),因此您的代码不完全符合标准,也不能保证由严格符合标准的编译器编译。

CCD_ 18本身是CCD_ 19和CCD_ 20规范(链路)的一部分。

另一种选择是使用标准的tolower()将输入规范化为小写。然后可以使用标准的strcmp()。

最新更新