前几天我在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的映射。考虑具有E
、e
和é
但没有É
但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 char
和EOF
范围内为int
定义。用作CCD_ 16的CCD_ 15可以具有负值。
"函数是非标准的"意味着函数声明和约定没有在C国际标准中指定。
"这使得代码不可移植"意味着不需要实现strcasecmp()
,因此您的代码不完全符合标准,也不能保证由严格符合标准的编译器编译。
CCD_ 18本身是CCD_ 19和CCD_ 20规范(链路)的一部分。
另一种选择是使用标准的tolower()将输入规范化为小写。然后可以使用标准的strcmp()。