当我像这样调用 C 字符串比较函数时:
strcmp("time","time")
它返回 0,这意味着字符串不相等。
谁能告诉我为什么 C 实现似乎会这样做?我认为如果相等,它将返回一个非零值。我很好奇我看到这种行为的原因。
strcmp 返回您作为参数给出的两个字符串的词法差异(或者我应该称之为“短路串行字节比较器”?:-))。0 表示两个字符串相等
正值意味着 s1 在字典中位于 s2 之后。
负值意味着 s1 在字典中将在 s2 之前。
因此,在比较明显不同的“时间”和“金钱”时,您的非零值,即使有人会说时间就是金钱!:-)
像这样的实现的好处是你可以说
if(strcmp(<stringA>, <stringB>) > 0) // Implies stringA > stringB
if(strcmp(<stringA>, <stringB>) == 0) // Implies stringA == stringB
if(strcmp(<stringA>, <stringB>) < 0) // Implies stringA < stringB
if(strcmp(<stringA>, <stringB>) >= 0) // Implies stringA >= stringB
if(strcmp(<stringA>, <stringB>) <= 0) // Implies stringA <= stringB
if(strcmp(<stringA>, <stringB>) != 0) // Implies stringA != stringB
请注意与 0 的比较如何与暗示中的比较完全匹配。
对于常见的或独一无二的情况,函数返回零是很常见的,而对于特殊情况,函数返回非零是很常见的。以 main 函数为例,它通常在成功时返回零,而在失败时返回一些非零值。精确的非零值表明出了什么问题。例如:内存不足,没有访问权限或其他。
在您的情况下,如果字符串相等,那么除了字符串包含相同的字符外,没有其他理由相等。但是如果它们不相等,那么第一个可以更小,或者第二个可以更小。让它返回 1 表示相等,0 表示较小,2 表示较大,我认为这有点奇怪。
你也可以从减法的角度来考虑:
return = s1 - s2
如果 s1 “按字典顺序”较少,那么它将给出一个负值。
返回它所做的代码的另一个原因strcmp()
是它可以直接在标准库函数中使用qsort()
,允许您对字符串数组进行排序:
#include <string.h> // for strcmp()
#include <stdlib.h> // for qsort()
#include <stdio.h>
int sort_func(const void *a, const void *b)
{
const char **s1 = (const char **)a;
const char **s2 = (const char **)b;
return strcmp(*s1, *s2);
}
int main(int argc, char **argv)
{
int i;
printf("Pre-sort:\n");
for(i = 1; i < argc; i++)
printf("Argument %i is %s\n", i, argv[i]);
qsort((void *)(argv + 1), argc - 1, sizeof(char *), sort_func);
printf("Post-sort:\n");
for(i = 1; i < argc; i++)
printf("Argument %i is %s\n", i, argv[i]);
return 0;
}
这个小示例程序按 ASCII 顺序对其参数进行排序(有些人会按词法调用)。看:
$ gcc -o sort sort.c
$ ./sort hi there little fella
Pre-sort:
Argument 1 is hi
Argument 2 is there
Argument 3 is little
Argument 4 is fella
Post-sort:
Argument 1 is fella
Argument 2 is hi
Argument 3 is little
Argument 4 is there
如果相等的字符串strcmp()
返回1
(true),不相等的返回( 0
false),则不可能用它来获得两个字符串之间不等的程度或方向(即不同的程度,哪个更大),从而使不可能将其用作排序功能。
我不知道你对 C 有多熟悉。上面的代码使用了 C 中一些最令人困惑的概念——指针算术、指针重铸和函数指针——所以如果你不理解其中的一些代码,请不要担心,你会及时到达那里。在那之前,你会在 StackOverflow 上问很多有趣的问题。;)
你似乎想像strcmp
(假设的)一样工作
int isEqual(const char *, const char *)
为了确保整数结果的“零是假”解释是正确的,但这会使排序逻辑复杂化,因为在确定两个字符串不相同之后,您仍然需要了解哪个“更早”出现”。
此外,我怀疑一个常见的实现看起来像
int strcmp(const char *s1, const char *s2){
const unsigned char *q1=s1, *q2=s2;
while ((*q1 == *q2) && *q1){
++q1; ++q2;
};
return (*q1 - *q2);
}
这是[编辑:有点]以 K&R 的方式优雅。这里的重点(通过正确编写代码而越来越模糊(显然我应该单独留下足够好的东西))是 return 语句的方式:
return (*q1 - *q2);
它根据字符值自然地给出比较结果。
有三种可能的结果:字符串 1 在字符串 2 之前,字符串 1 在字符串 2 之后,字符串 1 与字符串 2 相同。将这三个结果分开很重要;strcmp() 的一种用途是对字符串进行排序。问题是您希望如何为这三个结果分配值,以及如何使事情或多或少保持一致。您还可以查看 qsort() 和 bsearch() 的参数,它们需要与 strcmp() 类似的比较函数。
如果你想要一个字符串相等函数,它会为相等的字符串返回非零值,为不相等的字符串返回零值,以符合 C 的真假规则。这意味着将无法区分字符串 1 是在字符串 2 之前还是之后。对于 int 或您想命名的任何其他 C 数据类型有多个真值,但只有一个为假。
因此,有一个有用的 strcmp() 为字符串相等返回 true 将需要对语言的其余部分进行大量更改,而这根本不会发生。
我想这只是为了对称:-1 如果小于,0 如果相等,1 如果更多。