Why does strcmp() return 0 when its inputs are equal?
当我像这样调用C字符串比较函数时:
它返回0,这意味着字符串不相等。
有人能告诉我为什么C实现看起来要这样做吗?如果相等的话,我想它会返回一个非零值。我很好奇看到这种行为的原因。
strcmp返回一个词法差异(或者我应该称它为"短路串行字节比较器")?:-)作为参数提供的两个字符串。0表示两个字符串相等
正值意味着在字典中,s1将在s2之后。
负值表示在字典中,s1在s2之前。
因此,当比较"时间"和"金钱"时,你的非零值是明显不同的,即使有人会说时间就是金钱!-)
像这样的实现的好处在于
1 2 3 4 5 6 | 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的比较如何与含义中的比较完全匹配。
对于公共或一种类型的情况,函数通常返回零;对于特殊情况,函数通常返回非零。以主函数为例,它通常在成功时返回零,而在失败时返回一些非零的值。精确的非零值表示出了什么问题。例如:内存不足,没有访问权限或其他内容。
在您的例子中,如果字符串相等,那么除了字符串包含相同的字符之外,没有理由它是相等的。但是如果它们不相等,那么第一个可以更小,或者第二个可以更小。如果它等于1,小于0,大于2,我觉得有点奇怪。
你也可以用减法来思考:
1 | return = s1 - s2 |
如果s1的"词典编纂"较少,那么它将给出一个负值。
另一个原因是它的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #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: "); for(i = 1; i < argc; i++) printf("Argument %i is %s ", i, argv[i]); qsort((void *)(argv + 1), argc - 1, sizeof(char *), sort_func); printf("Post-sort: "); for(i = 1; i < argc; i++) printf("Argument %i is %s ", i, argv[i]); return 0; } |
这个小示例程序:(一asciibetically将其所受的呼叫lexically)。看:
1 2 3 4 5 6 7 8 9 10 11 12 | $ 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 |
如果
我不知道你是熟悉与C代码使用上述的一些最confusing概念C的指针的指针和函数的四则运算,recasting分-所以,如果你不明白这是一些代码,放心,你有没有时间。直到永远,你会有很多有趣的问题来问在线的计算器。);
你似乎希望
1 | int isEqual(const char *, const char *) |
要确保对整数结果的"零即假"解释是正确的,但这会使排序逻辑复杂化,因为在确定两个字符串不相同之后,您仍然需要了解"较早"出现的字符串。
此外,我怀疑一个常见的实现看起来像
1 2 3 4 5 6 7 | 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的方式,这是[编辑:有点]优雅。这里重要的一点是返回语句的方式(这一点越来越被代码的正确性所蒙蔽(显然我应该单独留下足够好的代码)):
1 | return (*q1 - *q2); |
这就自然地给出了字符值的比较结果。
有三种可能的结果:字符串1在字符串2之前,字符串1在字符串2之后,字符串1与字符串2相同。将这三个结果分开是很重要的;strcmp()的一个用途是对字符串进行排序。问题是你想如何为这三个结果赋予价值,以及如何保持事物或多或少的一致性。您还可以查看qsort()和bsearch()的参数,它们需要类似于strcmp()的比较函数。
如果您想要一个字符串相等函数,它将返回非零(对于相等的字符串)和零(对于不相等的字符串),以符合C关于"真"和"假"的规则。这意味着无法区分字符串1是在字符串2之前还是之后出现。一个int或任何其他c数据类型都有多个true值,但只有一个false。
因此,为字符串相等返回true的有用strcmp()将需要对语言的其余部分进行大量更改,而这根本不会发生。
我想这只是为了对称:如果小于1,等于0,大于1。