Implementation of strcmp

2019-01-24 08:48发布

问题:

I tried to implement 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;
}

but I'm stuck with the case that the user will input the same strings, because the function works with 1 and -1, but it's doesn't return 0. Can anyone help? And please without pointers!

回答1:

You seem to want to avoid pointer arithmetics which is a pity since that makes the solution shorter, but your problem is just that you scan beyond the end of the strings. Adding an explicit break will work. Your program slightly modified:

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] == '\0')
        {
            break;
        }

        i++;
    }
    return flag;
}

A shorter version:

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] == '\0')
        {
            return 0;
        }
    }
}


回答2:

Uhm.. way too complicate. Go for this one:

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

It returns <0, 0 or >0 as expected

You can't do it without pointers. In C, indexing an array is using pointers.

Maybe you want to avoid using the * operator? :-)



回答3:

First of all standard C function strcmp compares elements of strings as having type unsigned char.

Secondly the parameters should be pointers to constant strings to provide the comparison also for constant strings.

The function can be written the following way

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 );
}


回答4:

This is a 10 opcodes implementation of strcmp (GCC assumed)

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);
}

You can try this implementation and compare to others https://godbolt.org/g/ZbMmYM



回答5:

Taken from 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]!='\0') || (src2[i]!='\0'))
    {
        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!='\0') || (*src2!='\0'))
    {
        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));
}

I've made a few changes to make it work like strcmp.



回答6:

Your problem is that you don't detect the end of the string and therefore don't return zero if both strings ends before any difference is detected.

You can simply fix this by checking for this in the loop condition:

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

Note that both strings are checked because if only one is at the end the strings are not equal and the comparison inside the loop should detect that.

Please note that the character comparison might not yield the result that you might expect. For one it's not defined whether char is signed or unsigned so you should probably cast to unsigned char for comparison.

Perhaps a cleaner solution would be to return immediately when you detect the difference, that is instead of flag = -1 you return -1 directly. But that's more a matter of opinion.



回答7:

My Implementation

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 values

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

The last ternary operation is optional

The function would still in the rules of strcmp when you just return *s1 - *s2.



标签: c strcmp