Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exercice des chaines de caractères

strcmp

Sujet résolu
    13 août 2008 à 11:00:47

    Bonjour à tous !

    Ayant rencontré quelques petits problèmes en essayant de résoudre l'exercice de M@teo (consistant à écrire certaines fonctions de la librairie string.h) j'ai essayer de trouver une réponse sur le forum à la recherche d'un code clair et déjà réalisé pour pouvoir le comparer le mien et voir ce qui n'allait pas. Sauf que rien ne m'a réellement satisfait, du coup j'ai du résoudre mon problème seul.
    Je poste ici mon code pour ceux qui en auraient besoin (il fonctionne chez moi).

    #include <stdio.h>
    #include <stdlib.h>
    
    int exstrcmp(const char* chaine1, const char* chaine2);
    
    
    int main(int argc, char *argv[])
    {
        char chaine1[] = "Texte de test", chaine2[] = "Texte de test";
    
        if (exstrcmp(chaine1,chaine2) == 0)
        {
            printf("Chaines identiques.\n");
        }
    
        else
        {
            printf("Chaines differentes.\n");
        }
    
        return 0;
    }
    
    
    int exstrcmp(const char* chaine1, const char* chaine2)
    {
        long i = 0, k = 0;
        int valeur = 0;
    
        while (chaine1[i] != '\0' && chaine2[k] != '\0')
        {
            if (chaine1[i] == chaine2[k] || chaine2[i] == chaine1[k])
            {
                valeur = 0;
            }
    
            else
            {
                valeur = 1;
            }
    
            i++;
            k++;
        }
    
        return valeur;
    }
    
    • Partager sur Facebook
    • Partager sur Twitter
      13 août 2008 à 11:06:48

      Un petit défaut, si une chaine est plus longue que l'autre alors le résultat est faussé. Rajoute lettre au bout d'une de tes chaines sans changer le reste. Par exemple: Texte de teste
      Et la, ca te met que tes chaines sont identiques. C'est une simple erreur de condition.
      • Partager sur Facebook
      • Partager sur Twitter
        13 août 2008 à 11:27:26

        Citation : LeViking

        Un petit défaut, si une chaine est plus longue que l'autre alors le résultat est faussé. Rajoute lettre au bout d'une de tes chaines sans changer le reste. Par exemple: Texte de teste
        Et la, ca te met que tes chaines sont identiques. C'est une simple erreur de condition.

        Mince, autant j'avais prévue le coup si on modifiait le texte entre le debut et la dernière lettre "t" (qui renvoyait que les chaines étaient différentes), autant là je ne comprend pas pourquoi quand on ajoute une lettre après le dernier "t" de "test" ça indique toujours que les chaines sont identiques....

        Edit : non, en fait je m'aperçois que tant que chaque mot comporte le même nombre dans chaque variable, même si il y a un mot manquant, ma fonction renvoie toujours la valeur 0... je vais devoir revoir tout ça, moi qui pensait avoir juste :p
        • Partager sur Facebook
        • Partager sur Twitter
          13 août 2008 à 11:32:49

          Regarde bien ce que fais ta boucle.
          Ta condition est:
          tant que chaine 1 n'est pas arrivé à la fin de la chaine ET tant que chaine 2 n'est pas arrivé à la fin de la chaine, Faire....

          En gros, pour que ta fonction continue de tourner, il faut qu'aucune des 2 chaines ne soient arrivé à la fin.
          Donc soit tu changes cette condition, soit tu vérifies que les 2 chaines ont la même longueur (à mon avis, la meilleur solution vu que 2 chaines de longueurs différentes seront forcements.... différentes :) )
          • Partager sur Facebook
          • Partager sur Twitter
            13 août 2008 à 11:38:35

            Tu dois tout d'abord comparer le nombre de caractères des deux chaines. ;) Si le nombre des caractères de la chaine 1 est supérieur à celui de la chaine 2, on renvoie un nombre positif, si c'est l'inverse, on renvoie un nombre négatif
            C'est écrit dans le tuto, d'ailleurs ^^
            • Partager sur Facebook
            • Partager sur Twitter
              13 août 2008 à 11:38:56

              while (chaine1[i] != '\0' && chaine2[k] != '\0')
              


              Pourquoi utilises-tu deux variables i et k ?
              Elle restent au même rang donc tu peux n'en utiliser qu'une !

              (Utilise une boucle for ;) ).

              Et :
              chaine1[i] == chaine2[k] || chaine2[i] == chaine1[k]
              


              C'est pas un peu pareil ;) ?

              Soit :

              /* Voir plus bas */
              
              • Partager sur Facebook
              • Partager sur Twitter
                13 août 2008 à 11:41:27

                Citation : Keiristos

                <code type="c">
                
                /* On vérifie si les deux ont '\0' en commun*/
                if (chaine1[i] != chaine2[i])
                   valeur = 0;
                


                Faudra m'expliquer pourquoi tu refais une comparaison alors qu'au dessus, tu as une boucle for qui le fait :), d'autant plus que ta fonction ne marche pas non plus puisqu'elle fait la même chose.
                • Partager sur Facebook
                • Partager sur Twitter
                  13 août 2008 à 11:47:07

                  Personnellement, j'aurais mis comme condition
                  while(chaine1[i] != '\0' && chaine2[k] != '\0' && valeur == 0)
                  

                  pour que ta boucle s'arrête à la première différence entre les 2 chaines, plutôt que de la parcourir en entier.
                  Sans oublier le test de la longueur des 2 chaines au départ de la fonction.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    13 août 2008 à 11:49:51

                    Ta fonction ne respecte pas le comportement attendu. Voir la doc.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      13 août 2008 à 11:56:23

                      Citation : flyingglamer

                      Ta fonction ne respecte pas le comportement attendu. Voir la doc.


                      Oui, excuse-moi ... c'est mieux ?

                      Sinon j'ai corrigé mon code avec la remarque de zampaku.
                      Par contre, comparer les tailles au début je pense que c'est une opération en plus dont on peut se passer.
                      int exstrcmp(const char chaine1[], const char chaine2[])
                      {
                          int i;
                          int valeur = 0;
                      
                          /* On sort de la boucle si une des deux chaines en est à '\0'
                              ou si valeur != 0*/
                          for (i = 0;
                              chaine1[i] != '\0' && chaine2[i] != '\0' && valeur == 0;
                              i++, valeur += chaine1[i], valeur -= chaine2[i]);
                      
                          return valeur;
                      }
                      


                      NOTE IMPORTANTE : Après analyse (sans vérification) je pense que mon code est faux !
                      il vérifiera pas la première lettre. Bref, j'ai la flemme de le rajouter :-° !
                      • Partager sur Facebook
                      • Partager sur Twitter
                        13 août 2008 à 12:03:28

                        Donc voici les corrections que j'ai pu apporté grâce à vos conseils à vous tous :

                        #include <stdio.h>
                        #include <stdlib.h>
                        
                        int exstrcmp(const char* chaine1, const char* chaine2);
                        
                        
                        int main(int argc, char *argv[])
                        {
                            char chaine1[] = "Texte de test", chaine2[] = "Texte de test";
                        
                            if (exstrcmp(chaine1,chaine2) == 0)
                            {
                                printf("Chaines identiques.\n");
                            }
                        
                            else
                            {
                                printf("Chaines differentes.\n");
                            }
                        
                            return 0;
                        }
                        
                        
                        int exstrcmp(const char* chaine1, const char* chaine2)
                        {
                            long i;
                            int valeur = 0;
                        
                            long nombreDeCaracteres = 0, nombreDeCaracteres2 = 0;
                            char caractereActuel = 0, caractereActuel2 = 0;
                        
                        
                            do
                            {
                                caractereActuel = chaine1[nombreDeCaracteres];
                                nombreDeCaracteres++;
                            }
                            while(caractereActuel != '\0');
                        
                            do
                            {
                                caractereActuel2 = chaine2[nombreDeCaracteres2];
                                nombreDeCaracteres2++;
                            }
                            while(caractereActuel2 != '\0');
                        
                        //Je vérifie maintenant que les caractères sont identiques 
                        
                            for (i = 0; chaine1[i] != '\0' && chaine2[i] != '\0' && valeur == 0 ; i++)
                            {
                                if (chaine1[i] == chaine2[i] && nombreDeCaracteres == nombreDeCaracteres2) //Je vérifie que le nombre de caractères entre chaine1 et chaine2 sont égaux
                                {
                                    valeur = 0; //renvoie 0 si les caractères sont identiques et si les deux chaines comportent le même nombre de caractères
                                }
                        
                                else
                                {
                                    valeur = 1;
                                }
                        
                        
                            }
                        
                            return valeur;
                        }
                        


                        Je l'ai testé dans tous les sens, normalement cette fois c'est bon :D
                        Par contre j'ai conscience qu'il manque un peu de clarté, mais n'ayant pas encore dormis, j'ai pas la tête à chercher à le simplifier (s'il est simplifiable, au moins y mettre des commentaires).
                        • Partager sur Facebook
                        • Partager sur Twitter
                          13 août 2008 à 12:05:32

                          Le must aurait été de faire une fonction qui retourne la taille d'une chaine et d'utiliser cette fonction dans exstrcm afin d'éviter la répétition de code.
                          Ensuite tu compares ces 2 valeurs puis, si elles sont identiques, tu compares les chaines sinon fin de la comparaison
                          • Partager sur Facebook
                          • Partager sur Twitter
                            13 août 2008 à 12:08:06

                            Bon, tu as comparé le nombre de caractères des deux chaines au début, donc il est préférable de réagir tout de suite ^^ :
                            if (nombreDeCaracteres > nombreDeCaracteres2)
                            {
                               valeur = 1;
                            }
                            
                            else if (nombreDeCaracteres < nombreDeCaracteres2)
                            {
                              valeur = -1;
                            }
                            
                            else if (nombreDeCaracteres == nombreDeCaracteres2)
                            {
                              // Tu compares les caractères
                            }
                            
                            • Partager sur Facebook
                            • Partager sur Twitter
                              13 août 2008 à 12:23:50

                              Citation : HighTam

                              Bon, tu as comparé le nombre de caractères des deux chaines au début, donc il est préférable de réagir tout de suite ^^ :

                              if (nombreDeCaracteres > nombreDeCaracteres2)
                              {
                                 valeur = 1;
                              }
                              
                              else if (nombreDeCaracteres < nombreDeCaracteres2)
                              {
                                valeur = -1;
                              }
                              
                              else if (nombreDeCaracteres == nombreDeCaracteres2)
                              {
                                // Tu compares les caractères
                              }
                              


                              Je l'ai écris selon ta présentation, mais au fond je pense que mis à part un peu de clarté, cela reviens au même (attention, je suis d'accord qu'il vaut mieux que le code soit clair et lisible, seulement comme je l'ai dit, j'ai juste besoin d'aller dormir la immédiatement, donc j'ai pas les idées forcément très claires :p).

                              #include <stdio.h>
                              #include <stdlib.h>
                              
                              int exstrcmp(const char* chaine1, const char* chaine2);
                              
                              
                              int main(int argc, char *argv[])
                              {
                                  char chaine1[] = "Texte de test", chaine2[] = "Texte de test";
                              
                                  if (exstrcmp(chaine1,chaine2) == 0)
                                  {
                                      printf("Chaines identiques.\n");
                                  }
                              
                                  else
                                  {
                                      printf("Chaines differentes.\n");
                                  }
                              
                                  return 0;
                              }
                              
                              
                              int exstrcmp(const char* chaine1, const char* chaine2)
                              {
                                  long i;
                                  int valeur = 0;
                              
                                  long nombreDeCaracteres = 0, nombreDeCaracteres2 = 0;
                                  char caractereActuel = 0, caractereActuel2 = 0;
                              
                              
                                  do
                                  {
                                      caractereActuel = chaine1[nombreDeCaracteres];
                                      nombreDeCaracteres++;
                                  }
                                  while(caractereActuel != '\0');
                              
                                  do
                                  {
                                      caractereActuel2 = chaine2[nombreDeCaracteres2];
                                      nombreDeCaracteres2++;
                                  }
                                  while(caractereActuel2 != '\0');
                              
                              
                                  if (nombreDeCaracteres > nombreDeCaracteres2)
                                  {
                                      valeur = 1;
                                  }
                              
                                  else if (nombreDeCaracteres < nombreDeCaracteres2)
                                  {
                                      valeur = -1;
                                  }
                              
                                  else
                                  {
                              
                                      for (i = 0; chaine1[i] != '\0' && chaine2[i] != '\0' && valeur == 0 ; i++)
                                      {
                                          if (chaine1[i] == chaine2[i]) 
                                          {
                                              valeur = 0;
                                          }
                              
                                          else
                                          {
                                              valeur = 1;
                                          }
                              
                              
                                      }
                                  }
                              
                                  return valeur;
                              }
                              
                              • Partager sur Facebook
                              • Partager sur Twitter
                                13 août 2008 à 13:31:55

                                Voilà deux implémentations possibles qui respectent le comportement attendu (normalement) :
                                int mystrcmp(const char* string1, const char* string2)
                                {
                                    while(*string1 != '\0' && *string1 == *string2) {
                                        string1++;
                                        string2++;
                                    }
                                
                                    return ((*string1 < *string2) ? -1 : (*string1 > *string2));
                                }
                                
                                int mystrcmp2(const char* string1, const char* string2)
                                {
                                    int i = 0;
                                    while (string1[i] != '\0' && string1[i] == string2[i])
                                        i++;
                                
                                    return ((string1[i] < string2[i]) ? -1 : (string1[i] > string2[i]));
                                }
                                
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  13 août 2008 à 14:13:45

                                  Bof pour le relecture du code ca. Je préfère amplement l'abus de return à un ternaire. Au moins on comprend du premier coup d'œil.
                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  Exercice des chaines de caractères

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown