2
votes

Fonction récursive pour comparer des chaînes sans fonctions de bibliothèque

Je suis censé écrire une fonction récursive en langage de programmation C qui vérifie si la chaîne 1 est supérieure ou égale ou inférieure à la chaîne 2, et donc renvoyer 1 , 0 code>, -1 respectivement.

Voici mon code que j'ai écrit. Le programme ne peut pas se terminer et je ne peux pas comprendre la raison. Veuillez me donner quelques conseils. Merci.

int revisedStrcmp(char *s1, char *s2) {
    int i = 0, n = 0, p = 0;

    if (s1[i] == '\0' && s2[i] != '\0') //s1 shorter than s2
        return -1;

    else if (s1[i] != '\0' && s2[i] == '\0') //s1 longer than s2
        return 1;

    else if (s1[i] != '\0' && s2[i] != '\0')  //both not equal to null
    {
        if (s1[i] > s2[i])  n += 1; //s1
        else if (s1[i] < s2[i]) p += 1; //s2
        else
        {
           n += 1; //s1
           p += 1; //s2
        }
        i += 1;
        return revisedStrcmp(s1, s2);
    }
    else    //if s1[i] & s2[i] are null
    {
        if (n > p) //s1 > s2
            return 1;
        else if (n < p)
            return -1;
        else
            return 0;
    }
}


0 commentaires

5 Réponses :


1
votes

Vous ne passez pas à la fonction les variables i, n, p . De cette façon, votre fonction ne se terminera pas, car elle commencera à chaque fois avec les variables de compteur à 0.


0 commentaires

1
votes

Dans la partie:

int rStrcmp(char *s1, char *s2)
{
    if (*s1 =='\0' && *s2 !='\0') //s1 shorter than s2
        return -1;

    else if (*s1 !='\0' && *s2 =='\0') //s1 longer than s2
        return 1;

    else if (*s1 !='\0' && *s2 !='\0')  //both not equal to null
    {
        if (*s1>*s2)  return 1; //s1
        else if (*s1<*s2) return -1; //s2
        else
            return rStrcmp(s1+1,s2+1);
    }
    else    //if s1[i] & s2[i] are null
    {
        // since both are null, they are the same length and each
        // character was the same: equal
        return 0;
    }
}

vous appelez rStrcmp (s1, s2); avec s1 et s2 code>, cependant, vous venez de traiter un caractère. Appelez rStrcmp (s1 + 1, s2 + 1); .


Remarque: puisque votre fonction ne traite qu'un seul caractère par appel, vous n'avez pas besoin d'indexer les chaînes avec i . Il vaut toujours 0 sauf avant une instruction return, donc sa valeur n'est jamais utilisée:

    else if (s1[i] !='\0' && s2[i] !='\0')  //both not equal to null
    {
        if (s1[i]>s2[i])  n+=1; //s1
        else if (s1[i]<s2[i]) p+=1; //s2
        else
        {
           n+=1; //s1
           p+=1; //s2
        }
        i+=1;
        return rStrcmp(s1,s2);


0 commentaires

1
votes

Changez simplement le return rStrcmp (s1, s2); en return rStrcmp (s1 + i, s2 + i); . Ainsi, vous stockez les incréments de la position de votre tableau.


0 commentaires

3
votes

Le principal problème dans votre fonction est que vous ne transmettez pas de pointeurs mis à jour dans l'appel récursif à modifiedStrcmp , provoquant une boucle infinie et un potentiel débordement de pile .

Voici une version corrigée et simplifiée:

int revisedStrcmp(const char *s1, const char *s2) {
    unsigned char c1 = *s1, c2 = *s2;
    if (c1 < c2)
        return -1;
    if (c1 > c2)
        return +1;
    // c1 == c2
    if (c1 == '\0')
        return 0;
    return revisedStrcmp(s1 + 1, s2 + 1);
}

Il n'est pas nécessaire de faire des cas particuliers pour les chaînes plus courtes car le terminateur nul peut être utilisé dans les comparaisons.

Ce style particulier de récursivité est appelé récursivité de queue et sera compilé dans une boucle par les compilateurs modernes.

Notez cependant que pour modifiedStrcmp () renvoyer le même ordre que strcmp , les comparaisons doivent être effectuées sur des valeurs de unsigned char au lieu de simples char , qui peuvent être signés par défaut sur de nombreuses architectures:

int revisedStrcmp(const char *s1, const char *s2) {
    if (*s1 < *s2)
        return -1;
    if (*s1 > *s2)
        return +1;
    // *s1 == *s2
    if (*s1 == '\0')
        return 0;
    return revisedStrcmp(s1 + 1, s2 + 1);
}


0 commentaires

1
votes

La raison est que s1 et s2 sont les mêmes en récursivité. Ce que je veux dire: si vous avez char * s1 = "Hello"; et char * s2 == Elloh , vos appels récursifs sont les mêmes. vous commencez au même point, toujours, vous ne passez aucun incrément de quelque manière que ce soit (n, p) donc vous partez essentiellement du même point à chaque appel récursif. Ce que vous pouvez faire est d'incrémenter le pointeur et voici une solution courte:

return revisedStrcmp(s1+i, s2+i);

ou vous pouvez faire ce qui suit:

int revisedStrcmp (char *s1, char *s2) {
    if (*s1 == *s2)
        return *s1 == '\0' ? 0 : revisedStrcmp(s1 + 1, s2 + 1);

    return (*s1 > *s2) ? 1 : -1; 
}                                                                                                    


1 commentaires

@chqrlie C'est ce que vous vouliez dire? C'est une bonne idée, merci !!! Dans le cas où ils sont différents oui, cela en économise 2, mais je peux aussi m'en tirer avec un cas de test de moins dans d'autres cas. Ce que je veux dire, c'est que je peux m'en tirer sans tester si * s2 == '\ 0' parce que si '* s1 == * s2` et * s1 =' \ 0 '< / code> cela signifie automatiquement que s2 = '\ 0'