web-dev-qa-db-fra.com

Implémentation de strcmp

J'ai essayé d'implémenter 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;
}

mais je suis coincé avec le cas où l'utilisateur saisira les mêmes chaînes, car la fonction fonctionne avec 1 et -1, mais ne renvoie pas 0. Quelqu'un peut-il aider? Et s'il vous plaît sans pointeurs!

9
blackFish

Vous semblez vouloir éviter les arithmétiques de pointeur, ce qui est dommage car cela raccourcit la solution, mais votre problème est que vous balayez au-delà de la fin des chaînes. Ajouter une pause explicite fonctionnera. Votre programme légèrement modifié:

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

Une version plus courte:

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;
        }
    }
}
3
Daniel B.

Uhm .. beaucoup trop compliquer. Allez pour celui-ci:

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

Il retourne <0, 0 ou> 0 comme prévu

Vous ne pouvez pas le faire sans pointeurs. En C, indexer un tableau est en utilisant des pointeurs.

Peut-être voulez-vous éviter d'utiliser l'opérateur *? :-)

25
Gianluca Ghettini

Tout d'abord, la fonction C standard strcmp compare les éléments de chaînes avec le type unsigned char.

Deuxièmement, les paramètres doivent être des pointeurs sur les chaînes constantes pour permettre la comparaison également pour les chaînes constantes.

La fonction peut être écrite de la manière suivante

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 );
}
5
Vlad from Moscow

Ceci est une implémentation de 10 opcodes de strcmp (GCC est supposé)

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

Vous pouvez essayer cette implémentation et comparer les autres https://godbolt.org/g/ZbMmYM

1
Larytet

Tiré de ici .

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

J'ai apporté quelques modifications pour que cela fonctionne comme strcmp .

0
Ashish Ahuja

Ma mise en œuvre

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

retourne des valeurs

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

La dernière opération ternaire est optionnel

La fonction serait toujours dans les règles de strcmp lorsque vous retournerez simplement *s1 - *s2.

0
X Stylish

Votre problème est que vous ne détectez pas la fin de la chaîne et ne renvoyez donc pas zéro si les deux chaînes se terminent avant que toute différence ne soit détectée.

Vous pouvez simplement résoudre ce problème en recherchant ceci dans la condition de boucle:

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

Notez que les deux chaînes sont vérifiées, car si une seule est à la fin, les chaînes ne sont pas égales et la comparaison à l'intérieur de la boucle devrait le détecter.

Veuillez noter que la comparaison des caractères peut ne pas donner le résultat escompté. Pour l'un, il n'est pas défini si char est signé ou non signé, vous devriez donc probablement transtyper en unsigned char pour la comparaison.

Une solution plus propre consisterait peut-être à revenir immédiatement lorsque vous détectez la différence, c’est-à-dire que, au lieu de flag = -1, vous renvoyez directement -1. Mais c'est plus une question d'opinion.

0
skyking