【问题标题】:Creating my own strcmp () function in C在 C 中创建我自己的 strcmp() 函数
【发布时间】:2014-04-09 20:52:13
【问题描述】:

我的老师让我用 C 语言编写自己的 strcmp() 函数。我确实创建了自己的上述函数版本,我希望得到一些反馈。

int CompareTwoStrings ( char *StringOne, char *StringTwo ) {
    // Evaluates if both strings have the same length.
    if  ( strlen ( StringOne ) != strlen ( StringTwo ) ) {
        // Given that the strings have an unequal length, it compares between both
        // lengths.
        if  ( strlen ( StringOne ) < strlen ( StringTwo ) ) {
            return ( StringOneIsLesser );
        }
        if  ( strlen ( StringOne ) > strlen ( StringTwo ) ) {
            return ( StringOneIsGreater );
        }
    }
    int i;
    // Since both strings are equal in length...
    for ( i = 0; i < strlen ( StringOne ); i++ ) {
        // It goes comparing letter per letter.
        if  ( StringOne [ i ] != StringTwo [ i ] ) {
            if  ( StringOne [ i ] < StringTwo [ i ] ) {
                return ( StringOneIsLesser );
            }
            if  ( StringOne [ i ] > StringTwo [ i ] ) {
                return ( StringOneIsGreater );
            }
        }
    }
    // If it ever reaches this part, it means they are equal.
    return ( StringsAreEqual );
}

StringOneIsLesser、StringOneIsGreater、StringsAreEqual 分别定义为 const int,其值分别为:-1、+1、0。

问题是,我不确定,例如,我的 StringOne 的长度是否比我的 StringTwo 短,这自动意味着 StringTwo 更大,因为我不知道 strcmp() 是如何特别实现的。我需要你的一些反馈。

【问题讨论】:

  • 那么问题是什么?
  • 这不是一般反馈的最佳站点。 CodeReview.stackexchange.com 对此很有帮助。鉴于此,我回答的问题是“如果 StringOne 的长度小于我的 StringTwo,[是否] 这自动意味着 StringTwo 更大?”
  • 你不是把问题复杂化了很多吗?一个标准的strcmp 实现主体可以很容易地写成 3 行......当它们指向相同的字符时向前移动两个指针(注意在字符串终止符处停止),然后只比较你到达的字符,这将成为第一个不同的人。
  • 这会将两个字符串都扫描到完整长度,可能会多次扫描,而正统的strcmp() 通常只需要查看第一个字符即可找到差异。如果字符串的长度为数千字节,那么这对性能造成很大影响。
  • 提示:不要在 for 循环中使用 strlen(string1)。这对速度非常不利。使用 aux 变量,例如:int size = strlen(string1),然后在循环中使用该变量。 (for(i=0;i

标签: c strcmp


【解决方案1】:

这么简单的任务就这么多。我相信这样做很简单:

int my_strcmp(const char *a, const char *b)
{
    while (*a && *a == *b) { ++a; ++b; }
    return (int)(unsigned char)(*a) - (int)(unsigned char)(*b);
}

【讨论】:

  • 我会在减去之前转换为 int 以避免上溢/下溢。此外,参数应该是 const。
  • 老实说,我不知道该代码的作用。我试图避免使用指针,因为我对指针的使用仍然很陌生。我比较两个字符串的想法是逐个字母地比较它们。
  • 请注意,如果char 是无符号类型,则“转换为int”建议尤其重要。
  • 除非另有说明,否则所有原语都是signed,所以我认为这不是问题。此外,strcmp 应该比较可读文本并且不需要是二进制安全的,因此考虑到您正在使用 strcmp 执行它的任务时,不用担心涉及带有“负”符号的算术的意外行为专为 -- 比较和排序文本而设计。
  • @user193203821309 因为您只测试字符串中的第一个字节。
【解决方案2】:

strcmp 按字母顺序比较:所以"aaa" &lt; "b" 即使“b”更短。

因此,您可以跳过长度检查,只进行逐个字母的比较。如果你在两个字符串到目前为止相等的情况下得到一个 NULL 字符,那么较短的就是较小的。

另外:为了与标准排序函数兼容,制作 StringsAreEqual == 0,而不是 1。

【讨论】:

    【解决方案3】:
        int mystrncmp(const char * str1, const char * str2, unsigned int n)
         {
          while (*str1 == *str2) {
              if (*str1 == '\0' || *str2 == '\0')
                 break;
    
              str1++;
              str2++;
           }
    
    
       if (*str1 == '\0' && *str2 == '\0')
          return 0;
       else
          return -1;
    }
    

    【讨论】:

    • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。
    • 第三个函数参数的作用是什么:unsigned int n?
    • 这个mystrncmp() 从不返回正值,不像strcmp(),所以出乎意料地对排序没有用处。使用 n 参数 - 如果用于限制比较范围,则应为 size_t。
    【解决方案4】:

    strcmp() 相当容易编码。常见的错误编码问题包括:

    参数类型

    strcmp(s1,s2) 使用 const char * 类型,而不是 char *。这允许使用指向const 数据的指针调用该函数。它向用户传达了功能的数据不变性。它可以帮助优化。

    无符号比较

    所有str...() 函数的执行都如同char 是unsigned char,即使char 已签名。当字符串不同并且发现[1...CHAR_MAX] 范围之外的字符时,这很容易影响结果。

    范围

    在选择实现中,unsigned char 减去 unsigned char 的范围超出了 int 范围。使用 2 比较 (a&gt;b) - (a-b) 可以避免任何问题,而不是 a-b;。此外:许多编译器都认识到了这种习惯用法并发出了很好的代码。

    int my_strcmp(const char *s1, const char *s2) {
      // All compares done as if `char` was `unsigned char`
      const unsigned char *us1 = (const unsigned char *) s1;
      const unsigned char *us2 = (const unsigned char *) s2;
    
      // As long as the data is the same and '\0' not found, iterate
      while (*us1 == *us2 && *us1 != '\0') {
        us1++;
        us2++;
      }
    
      // Use compares to avoid any mathematical overflow 
      // (possible when `unsigned char` and `unsigned` have the same range).
      return (*us1 > *us2) - (*us1 < *us2);
    }
    

    恐龙电脑

    使用 已签名 char 和非 2 补码的机器,以下可能是错误的或带有 *s1 != '\0' 的陷阱。这样的机器可能有一个负 0 - 这并不表示字符串的结尾,但会退出循环。使用unsigned char * 指针可以解决这个问题。

    int my_strcmp(const char *s1, const char *s2) {
      while (*s1 == *s2 && *s1 != '\0') { // Error!
        s1++;
        s2++;
      }
    

    【讨论】:

      【解决方案5】:

      试试这个也可以更好地理解:

      #include <stdio.h>
      #include <string.h>
      
      int main(void)
      {
          char string1[20], string2[20];
          int i=0,len=0, count=0;
          puts("enter the stirng one to compare");
          fgets(string1, sizeof(string1), stdin);
          len = strlen(string1);
          if(string1[len-1]=='\n')
          string1[len-1]='\0';
      
          puts("enter the stirng two to compare");
          fgets(string2, sizeof(string2), stdin);
          len = strlen(string2);
          if(string2[len-1]=='\n')
          string2[len-1]='\0';
          if(strlen(string1)==strlen(string2))
          {
          for(i=0;string1[i]!='\0', string2[i]!='\0', i<strlen(string1);i++)
          {
              count=string1[i]-string2[i];
              count+=count;
          }
              if(count==0)
                  printf("strings are equal");
              else if(count<0)
                  printf("string1 is less than string2");
              else if(count>0)
                  printf("string2 is less than string1");
          }
      
          if(strlen(string1)<strlen(string2))
          {
          for(i=0;string1[i]!='\0', i<strlen(string1);i++)
          {
              count=string1[i]-string2[i];
              count+=count;
          }
              if(count==0)
                  printf("strings are equal");
              else if(count<0)
                  printf("string1 is less than string2");
              else if(count>0)
                  printf("string2 is less than string1");
          }
      
          if(strlen(string1)>strlen(string2))
          {
          for(i=0;string2[i]!='\0', i<strlen(string2);i++)
          {
              count=string1[i]-string2[i];
              count+=count;
          }
              if(count==0)
                  printf("strings are equal");
              else if(count<0)
                  printf("string1 is less than string2");
              else if(count>0)
                  printf("string2 is less than string1");
          }
      
      
          return 0;
      }
      

      【讨论】:

        【解决方案6】:
        bool str_cmp(char* str1,char* str2)
        {
            if (str1 == nullptr || str2 == nullptr)
                return false;
        
        
            const int size1 = str_len_v(str1);
            const int size2 = str_len_v(str2);
        
            if (size1 != size2)
                return false;
        
            for(int i=0;str1[i] !='\0' && str2[i] !='\0';i++)
            {
                if (str1[i] != str2[i])
                    return false;
            }
        
            return true;
        }
        

        【讨论】:

        • 如果你能解释一下你的解决方案会很好
        猜你喜欢
        • 2013-09-22
        • 1970-01-01
        • 1970-01-01
        • 2020-09-20
        • 1970-01-01
        • 2013-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多