22

当我像这样调用 C 字符串比较函数时:

strcmp("time","time")

它返回 0,这意味着字符串不相等。

谁能告诉我为什么 C 实现似乎会这样做?我认为如果相等,它将返回一个非零值。我很好奇我看到这种行为的原因。

4

7 回答 7

31

strcmp 返回您作为参数给出的两个字符串的词法差异(或者我应该称之为“短路串行字节比较器”?:-))。0 表示两个字符串相等

正值意味着 s1 在字典中位于 s2 之后。

负值意味着 s1 在字典中将在 s2 之前。

因此,在比较明显不同的“时间”和“金钱”时,您的非零值,即使有人会说时间就是金钱!:-)

于 2009-02-27T16:25:40.677 回答
17

像这样的实现的好处是你可以说

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 的比较如何与暗示中的比较完全匹配。

于 2009-02-27T17:09:29.290 回答
6

对于常见的或独一无二的情况,函数返回零是很常见的,而对于特殊情况,函数返回非零是很常见的。以 main 函数为例,它通常在成功时返回零,而在失败时返回一些非零值。精确的非零值表明出了什么问题。例如:内存不足,没有访问权限或其他。

在您的情况下,如果字符串相等,那么除了字符串包含相同的字符外,没有其他理由相等但是如果它们不相等,那么第一个可以更小,或者第二个可以更小。让它返回 1 表示相等,0 表示较小,2 表示较大,我认为这有点奇怪。

你也可以从减法的角度来考虑:

return = s1 - s2

如果 s1 “按字典顺序”较少,那么它将给出一个负值。

于 2009-02-27T16:55:11.040 回答
4

返回它所做的代码的另一个原因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),不相等的返回( 0false),则不可能用它来获得两个字符串之间不等的程度方向(即不同的程度,哪个更大),从而使不可能将其用作排序功能。

我不知道你对 C 有多熟悉。上面的代码使用了 C 中一些最令人困惑的概念——指针算术、指针重铸和函数指针——所以如果你不理解其中的一些代码,请不要担心,你会及时到达那里。在那之前,你会在 StackOverflow 上问很多有趣的问题。;)

于 2009-09-02T04:58:48.077 回答
3

你似乎想像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);

它根据字符值自然地给出比较结果。

于 2009-02-27T16:53:25.523 回答
2

有三种可能的结果:字符串 1 在字符串 2 之前,字符串 1 在字符串 2 之后,字符串 1 与字符串 2 相同。将这三个结果分开很重要;strcmp() 的一种用途是对字符串进行排序。问题是您希望如何为这三个结果分配值,以及如何使事情或多或少保持一致。您还可以查看 qsort() 和 bsearch() 的参数,它们需要与 strcmp() 类似的比较函数。

如果你想要一个字符串相等函数,它会为相等的字符串返回非零值,为不相等的字符串返回零值,以符合 C 的真假规则。这意味着将无法区分字符串 1 是在字符串 2 之前还是之后。对于 int 或您想命名的任何其他 C 数据类型有多个真值,但只有一个为假。

因此,有一个有用的 strcmp() 为字符串相等返回 true 将需要对语言的其余部分进行大量更改,而这根本不会发生。

于 2009-02-27T17:25:53.620 回答
0

我想这只是为了对称:-1 如果小于,0 如果相等,1 如果更多。

于 2009-02-27T16:57:22.423 回答