【问题标题】:How to make strcmp function?如何制作strcmp函数?
【发布时间】:2017-04-28 05:57:35
【问题描述】:

我想制作自己的 strcmp 函数,就像 C 中的函数一样。

int my_cmp(const char* str1, const char* str2)  
{
    int index;
    for (index = 0; str1[index] != '\0' && str2[index] != '\0'; index++)
        if (str1[index] != str2[index])             
            return (str1[index] - str2[index]);             
    return 0;
}

我说的对吗? 我知道并非所有的字符串都具有相同的长度。 我不确定 for 语句的条件。

【问题讨论】:

  • 当字符串长度不同但排序器的内容与最长的字符串相同时,您的函数不正确。
  • 你需要做一个无符号减法。如果字符串长度不等,则它们不相等。
  • 如果您将此作为学习练习,那很好。但是,请注意 strcmp 可能会被大量使用,因此标准库实现往往是高度优化的 - 内联和 SIMD 操作用于每次迭代测试多个字符。
  • @InternetAussie:该函数也存在于 c++ 中,并且具有相同的语义。为什么要更改标签?
  • @MikeMB 是的,但通常的 C++ 方法是实例化两个 std::string 对象并使用各种 <>、... 运算符来比较字符串。 strcmp 与 C 的用法更相关。

标签: c string function strcmp


【解决方案1】:

这是Official implemention 之一。

int strcmp(const char *s1, const char *s2)
{
    for ( ; *s1 == *s2; s1++, s2++)
        if (*s1 == '\0')
            return 0;
    return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
 }

更新:

你的代码问题:

  1. 您的代码适用于相同长度的字符串,其他情况下会出错。
  2. 对于Extended ASCII(范围在128~255之间),你使用sign char,所以它们的值会溢出到一个负值,那么你可能会得到一个错误的值。

修复版本

int my_cmp(const char* str1, const char* str2)  
{
    int index;
    for (index = 0; str1[index] != '\0' && str2[index] != '\0'; index++)
        if (str1[index] != str2[index])
            return ((*(unsigned char *)str1 < *(unsigned char *)str2) ? -1 : +1);

    // here is the fix code.
    if (str1[index] != '\0') {
        return 1;
    } else if (str2[index] != '\0') {
        return -1;
    }

    return 0;
}

【讨论】:

  • “固定”版本还比较字符而不是无符号字符。
  • 为什么要转换成unsigned char *而不是`char *'?
  • @AugustKarlstrom 因为否则当 char >= 128 时你会得到错误的答案。
  • @MikeMB 谢谢,很好的提示。
  • 我最诚挚的道歉 - 我忘了返回“-1,0,1”实际上并不是 strcmp 规范的一部分
【解决方案2】:

以下代码 sn-p 向您展示了如何实现“strcmp”函数:

int myStrCmp (const char *s1, const char *s2) {
    const unsigned char *p1 = (const unsigned char *)s1;
    const unsigned char *p2 = (const unsigned char *)s2;

    while (*p1 != '\0') {
        if (*p2 == '\0') return  1;
        if (*p2 > *p1)   return -1;
        if (*p1 > *p2)   return  1;

        p1++;
        p2++;
    }

    if (*p2 != '\0') return -1;

    return 0;
}

【讨论】:

    【解决方案3】:

    我说的对吗?我知道并非所有的字符串都具有相同的长度。我不确定 for 语句的条件。

    你几乎是对的。您的if 声明

    if (str1[index] != str2[index])
        return (str1[index] - str2[index]);
    

    基本正确(虽然字符应该减去unsigned chars),但是for循环本身

    for (index = 0; str1[index] != '\0' && str2[index] != '\0'; index++)
    

    错了。具体条件:

    str1[index] != '\0' && str2[index] != '\0'
    

    这是错误的,因为它会检查以确保给定索引处的 both 字符不是 '\0',而不是 either 字符。这可以通过将&amp;&amp; 替换为|| 来解决。

    这是一个经验丰富的 C 程序员可能如何编写 strcmp 函数(我写了这个:p(编辑:@chux 建议改进)):

    int strcmp(const char *s1, const char *s2) {
        for (; *s1 && (*s1 == *s2); s1++, s2++) {}
        return (unsigned char)(*s1) - (unsigned char)(*s2);
    }
    

    【讨论】:

    • 简化:*s1 &amp;&amp; *s2 &amp;&amp; (*s1 == *s2) --> *s1 &amp;&amp; (*s1 == *s2) - 再一次优化编译器可能为你做。 (unsigned char)(*s1) - (unsigned char)(*s2)unsigned charint 位宽相同的稀有机器上存在OF 问题。
    猜你喜欢
    • 2013-11-05
    • 2019-12-04
    • 2021-12-22
    • 2014-11-03
    • 2012-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多