strcasecmp():非标准函数?

Sup*_*GoA 8 c string comparison

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

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;
}
Run Code Online (Sandbox Code Playgroud)

有人可以更深入地解释为什么strcasecmp()有这些限制?

chu*_*ica 7

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

\n

strcasecmp()在 4.4BSD、POSIX.1-2001 等流行标准中定义。

\n

无大小写函数的定义为挑剔的细节打开了大门。这些通常涉及无大小写比较的正结果或负结果,而不仅仅是 OP 使用的 0 或非 0。尤其:

\n
\n

在 POSIX 语言环境中,strcasecmp() 和 strncasecmp() 的行为就像字符串已转换为小写,然后执行字节比较。其他语言环境中的结果未指定。

\n
\n

这样做的问题是大写和小写字母没有一对一的映射。考虑一个本地人,有Ee但还\xc3\xa9没有--> 。然后“就好像字符串已转换为小写”,\xc3\x89toupper(\'\xc3\xa9\')\'E\'\'E\'有 2 个选择。

\n

作为候选人便携式解决方案,请考虑往返字母(先向上然后向下)以处理非一对一映射的解决方案:

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

如果您不想往返这些值,请使用:

\n
     ca = tolower(ca);\n     cb = tolower(cb);\n
Run Code Online (Sandbox Code Playgroud)\n

详细信息:toupper()和仅在和范围内tolower()定义。用作intunsigned charEOF* (unsigned char *)a*a可能具有负值。

\n


ros*_*031 5

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

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

  • 请注意,[`strcasecmp()`](http://pubs.opengroup.org/onlinepubs/7990989775/xsh/strcasecmp.html) 是由 Single Unix Specification v2 在 1997 年定义的。我不确定它是否在 POSIX 中在那个时候,但 `strcasecmp()` 的历史比 2001 年的引用所暗示的还要长。 (3认同)
  • 这完全是一种误解。仔细阅读:“以 str 开头后跟小写字母的名称由 C 标准保留”。这意味着,如果你编写了一个名为 strcasewhatever 的函数,那么你就已经离开了 C 标准。strcmp 是 C 标准的_一部分_。 (2认同)
  • @SuperGoA:我的意思是我说的。C 标准将 `strcmp()` 定义为其函数之一,并且还保留了以 `str` 和小写字母开头的其他名称。POSIX 使用 `strcasecmp()` 来处理这个保留的名称空间,但是却侥幸逃脱。如果你创建了一个函数 `strcasecmp()`,你不能保证会成功,但是 `strCaseCmp()` 或 `str_casecmp()` 或 `str9cmp()` 是可以的(`str` 后面没有跟这三个中的任何一个的小写字母)。当然,如果系统不像预期的那样严格,您仍然可能会遇到问题。 (2认同)
  • 与其说是关于平台,不如说是关于 C 编译器及其库。您可以在 Windows 上安装 MinGW 并像在 Unix 或 OS X 上一样调用 strcasecmp,即使它在您使用 Visual Studio 时不起作用。或者,您可以根据工具集的需要,仅使用`#define strcasecmp stricmp`,反之亦然。 (2认同)
  • 您*可能*需要担心的是,函数的运行时实现如何确定哪些大写和小写字符与其不区分大小写的比较等效?您可能会发现对于英语字符串来说一切都很好,但是如果您为它提供带有其他语言(例如德语、法语、西班牙语)的重音或变音符号的字符串,那么它是否有效可能取决于实现,或者取决于“C”语言环境。然后是宽字符语言,如日语和汉语;那是一个完全不同的故事。欢迎来到巴别塔! (2认同)