【问题标题】:Why does strcmp() return 0 when its inputs are equal?为什么 strcmp() 在其输入相等时返回 0?
【发布时间】:2010-10-10 09:00:03
【问题描述】:

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

strcmp("time","time")

返回0,表示字符串不相等。

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

【问题讨论】:

  • Time != money directly - 您必须先进行单位转换。
  • @remeador:我可以问很多愚蠢的笑话问题。对于那些感兴趣的人,最初的问题是:“为什么 strcmp("time","money") 返回 0 而不是非零?”。
  • 编辑:返回非零而不是 0。

标签: c strcmp


【解决方案1】:

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

正值表示 s1 在字典中位于 s2 之后。

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

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

【讨论】:

  • strcmp() 不做词法比较,它只是比较每个字符的值,直到有差异或两个字符串都终止。
  • 我可以发誓我读过文档说 strcmp() 进行了词法比较,但是一些快速的谷歌搜索表明 Ferruccio 是正确的......它会在某个时候改变吗?
  • 嗯,我很确定这是一个词汇比较! cplusplus.com/reference/clibrary/cstring/strcmp.html
  • 我认为它会随着给定的“词汇”定义而改变。我也看到 strcmp() 被称为“词法”比较器,但显然它没有考虑不同的本地化、排序规则等。也许称它为“短路串行字节比较器”会更好。
  • 它只是使用每个字符的 ASCII 值进行比较,其顺序如下:ABCDE...abcde。词汇比较会将它们排序为:AaBbCcDdEe。
【解决方案2】:

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

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 的比较如何与隐含的比较完全匹配。

【讨论】:

  • comp.lang.c FAQ 中有一个奇妙/可怕的宏,它几乎完全实现了这种字符串行为。 #define StrTest(str1, op, str2) (strcmp(str1, str2) op 0) 有了它,你会写 if(StrTest(stringA, ==, stringB)) 和朋友们。对于这是一个可怕的想法还是一个绝妙的想法,我持观望态度。
【解决方案3】:

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

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

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

return = s1 - s2

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

【讨论】:

    【解决方案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) 和0 (false) 为不相等的字符串,则不可能使用它来获得degree两个字符串之间不等式的方向(即差异有多大,哪个更大),因此无法将其用作排序函数。

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

    【讨论】:

      【解决方案5】:

      您似乎希望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);
      }
      

      这是 [edit: 有点] K&R 的优雅方式。这里的重点(由于代码正确而越来越模糊(显然我应该独自留下足够好的东西))是 return 语句的方式:

         return (*q1 - *q2);
      

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

      【讨论】:

      • “通用实现”不会离开缓冲区(超过空终止符吗?)我看不出它会如何返回 0...
      • 我认为如果你来到 \0 ,你必须终止循环 :) 你还必须注意 *s1 - *s2 中的下溢,所以 s1=-127, s2=2 => 哎呀:)
      • 哦等等。 no 不会导致下溢,因为两者都首先转换为 int。
      • @dmckee:为什么不只是 && *s1? :]
      • 我在 c99 中查找过,它说两者都先转换为无符号字符,然后再减去。所以甚至不可能出现 s1=-127 的情况 :) 但它改变了一些:* a - *b 可以变成 -2 与 char (*a=-1, *b=1) 和 +254 与 unsigned char.so 我相信应该在那里添加一个演员表。有点棘手:)
      【解决方案6】:

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

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

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

      【讨论】:

        【解决方案7】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-10-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-04
          相关资源
          最近更新 更多