strcmp 的实现

Implementation of strcmp

我尝试实现 strcmp:

int strCmp(char string1[], char string2[])
{
    int i = 0, flag = 0;    
    while (flag == 0) {
        if (string1[i] > string2[i]) {
            flag = 1;
        } else
        if (string1[i] < string2[i]) {
            flag = -1;
        } else {
            i++;
        }
    }
    return flag;
}

但我坚持用户将输入相同字符串的情况,因为该函数适用于 1-1,但它不适用于 return 0。谁能帮忙?还请指点!

嗯..太复杂了。选择这个:

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

它 returns <0、0 或 >0 符合预期

没有指点是做不到的。在 C 中,索引数组 使用指针。

也许您想避免使用 * 运算符? :-)

您的问题是您没有检测到字符串的结尾,因此如果两个字符串在检测到任何差异之前结束,则不会 return 为零。

您可以通过在循环条件中检查这一点来简单地解决此问题:

while( flag==0 && (string1[i] != 0 | string2[i] != 0 ) )

请注意,两个字符串都会被检查,因为如果最后只有一个字符串,则字符串不相等,循环内的比较应该检测到这一点。

请注意,字符比较可能不会产生您预期的结果。一方面,它没有定义 char 是有符号的还是无符号的,因此您可能应该转换为 unsigned char 进行比较。

也许更简洁的解决方案是当您检测到差异时立即 return,即直接 return -1 而不是 flag = -1。但这更见仁见智。

首先,标准 C 函数 strcmp 比较字符串元素的类型 unsigned char

其次,参数应该是指向常量字符串的指针,以便也为常量字符串提供比较。

函数可以这样写

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

    while ( *p1 && *p1 == *p2 ) ++p1, ++p2;

    return ( *p1 > *p2 ) - ( *p2  > *p1 );
}

您似乎想避免指针算法,这很遗憾,因为这会使解决方案更短,但您的问题只是您扫描到字符串末尾之外。添加显式中断将起作用。您的程序稍作修改:

int strCmp(char string1[], char string2[] )
{
    int i = 0;
    int flag = 0;    
    while (flag == 0)
    {
        if (string1[i] > string2[i])
        {
            flag = 1;
        }
        else if (string1[i] < string2[i])
        {
            flag = -1;
        }

        if (string1[i] == '[=10=]')
        {
            break;
        }

        i++;
    }
    return flag;
}

更短的版本:

int strCmp(char string1[], char string2[] )
{
    for (int i = 0; ; i++)
    {
        if (string1[i] != string2[i])
        {
            return string1[i] < string2[i] ? -1 : 1;
        }

        if (string1[i] == '[=11=]')
        {
            return 0;
        }
    }
}

摘自 here.

#include<stdio.h>
#include<string.h>
 
//using arrays , need to move the string using index
int strcmp_arry(char *src1, char *src2)
{
    int i=0;
    while((src1[i]!='[=10=]') || (src2[i]!='[=10=]'))
    {
        if(src1[i] > src2[i])
            return 1;
        if(src1[i] < src2[i])
            return -1;
        i++;
    }
 
    return 0;
}
//using pointers, need to move the position of the pointer
int strcmp_ptr(char *src1, char *src2)
{
    int i=0;
    while((*src1!='[=10=]') || (*src2!='[=10=]'))
    {
        if(*src1 > *src2)
            return 1;
        if(*src1 < *src2)
            return -1;
        src1++;
        src2++;
    }
    return 0;
}
 
int main(void)
{
    char amessage[] = "string";
    char bmessage[] = "string1";
    printf(" value is %d\n",strcmp_arry(amessage,bmessage));
    printf(" value is %d\n",strcmp_ptr(amessage,bmessage));
}

我做了一些更改,使其像 strcmp 一样工作。

这是 strcmp 的 10 个操作码实现(假定为 GCC)

int strcmp_refactored(const char *s1, const char *s2)
{
    while (1)
    {
        int res = ((*s1 == 0) || (*s1 != *s2));
        if  (__builtin_expect((res),0))
        {
            break;
        }
        ++s1;
        ++s2;
    }
    return (*s1 - *s2);
}

您可以尝试这个实现并与其他实现进行比较https://godbolt.org/g/ZbMmYM

我的实现

int strcmp(const char * s1, const char * s2)
{
    while (*s1 == *s2 && *s1++ | *s2++);
    int i = *s1 - *s2;
    return i < 0 ? -1 : i > 0 ? 1 : 0;
}

return 值

-1 // <0
1  // >0
0  // ==0

The last ternary operation is optional

当您 return *s1 - *s2.

时,该功能仍将遵循 strcmp 的规则

另一个优雅的(但不是最“干净的代码”)实现,带有指针。

int a_strcmp(char* t, char* s)
{
    for( ; *t == *s ; *s++ , *t++)
        if(*t == '[=10=]')
            return 0;
    return *t - *s;
}

不使用指针的版本。

int b_strcmp(char t[], char s[])
{
    int i;
    for(i = 0; s[i] == t[i]; ++i)
        if(t[i] == '[=11=]')
            return 0;
    return t[i] - s[i];
}