IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Télécharger C Discussion :

Remplacer toutes les occurrences d'une sous-chaîne [Sources]


Sujet :

Télécharger C

  1. #1
    Membre émérite

    Homme Profil pro
    Urbaniste
    Inscrit en
    Mars 2002
    Messages
    255
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Urbaniste

    Informations forums :
    Inscription : Mars 2002
    Messages : 255
    Points : 2 717
    Points
    2 717
    Par défaut Remplacer toutes les occurrences d'une sous-chaîne
    Bonjour, Je vous propose un nouvel élément à utiliser : Remplacer toutes les occurrences d'une sous-chaîne



    Remplace toutes les occurrences de Avant par Apres dans la chaine txt, puis renvoie un pointeur sur la nouvelle chaîne créée. Renvoie NULL si txt ne contient aucune occurrence de Avant.



    Qu'en pensez-vous ?

  2. #2
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2013
    Messages
    1
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Finistère (Bretagne)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Industrie

    Informations forums :
    Inscription : Avril 2013
    Messages : 1
    Points : 1
    Points
    1
    Par défaut Test retour malloc
    Bonjour,
    Très pratique cette fonction ! merci.
    Cependant attention les valeurs de retour des allocations ne sont pas testés, elles sont suivis par des copies -> segfault.
    Bonne journée

  3. #3
    Expert éminent
    Avatar de Pyramidev
    Homme Profil pro
    Développeur
    Inscrit en
    Avril 2016
    Messages
    1 469
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 469
    Points : 6 102
    Points
    6 102
    Par défaut
    Bonjour,

    Ton code actuel réussit bien les tests suivants :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char* res1 = str_replace("O_O_O_O_O_O", "O_O", "XY");
    assert(0 == strcmp(res1, "XY_XY_XY"));
     
    char* res2 = str_replace("O_O_O_O_O_O", "O_O", "");
    assert(0 == strcmp(res2, "__"));
    Dans la suite de mon message, je vais noter N le nombre d'occurrences de Avant dans txt.

    Je propose les améliorations suivantes :
    • Si N est non nul, Ton code fait un appel à malloc et N+1 appels à realloc. Il serait plus performant de calculer N puis de faire une seule allocation :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      TxtRetour = (char *) malloc(strlen(txt) - N*strlen(Avant) + N*strlen(Apres) + 1);
    • Si une allocation échoue, la fonction devrait retourner NULL.
    • Il y a un commentaire à corriger :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      /* Aucune occurrences : renvoie simplement une copie de la chaine */
      if (pos == NULL)
      {
          return NULL;
      }
      En effet, ce code ne renvoie pas une copie de la chaîne : il renvoie NULL.
    • Il y a un bout de ton code qui est de la forme :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      BOUT_DE_CODE_B;
      while(condition)
      {
          BOUT_DE_CODE_A;
          BOUT_DE_CODE_B;
      }
      Dans ton cas, BOUT_DE_CODE_B est :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      /* Ajoute la chaîne de remplacement */
      Long = strlen (Apres);
      strncpy (TxtRetour + PosTxtRetour, Apres, Long);
      PosTxtRetour += Long;
       
      /* Cherche la prochaine occurrence */
      pos = strstr (txt, Avant);
      Ce code peut être factorisé, par exemple de cette manière :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      while(true)
      {
          BOUT_DE_CODE_B;
          if(!codition)
              break;
          BOUT_DE_CODE_A;
      }
    • Au début de ta fonction, je te conseille d'ajouter :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      assert(strlen(Avant) > 0);
      if(strlen(Avant) == 0)
          return NULL;
      Sinon, l'utilisateur risque d'être bloqué dans une boucle infinie.
    • Dans ton premier appel à realloc, tu as bien pensé à convertir le résultat en (char *). Il faudrait aussi le faire pour ton appel à malloc et ton autre appel à realloc. Ainsi, le code de ta fonction compilera aussi en C++.
    • Pour aller plus loin, tu pourrais factoriser le code en fournissant une nouvelle fonction str_replace_without_alloc utile aux utilisateurs qui voudraient gérer la mémoire autrement :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      // nombre d'occurrences de substring dans txt
      // retourner -1 si substring est une chaîne vide
      int str_count(const char *txt, const char *substring)
      {
          // ...
      }
       
      // remplacer toutes les occurrences de Avant par Apres dans la chaine txt
      // retourner false en cas d'erreur
      bool str_replace_without_alloc(char *Resultat, size_t tailleMaxResultat, const char *txt, const char *Avant, const char *Apres)
      {
          assert(Resultat != txt);
          // ...
      }
       
      char *str_replace(const char *txt, const char *Avant, const char *Apres)
      {
          char* TxtRetour = NULL;
       
          assert(strlen(Avant) > 0);
          if(strlen(Avant) == 0)
              return TxtRetour;
       
          const int N = str_count(txt, Avant);
          if(N <= 0)
              return TxtRetour;
       
          const size_t tailleTxtRetour = strlen(txt) - N*strlen(Avant) + N*strlen(Apres);
          TxtRetour = (char *) malloc(tailleTxtRetour + 1);
          if(TxtRetour == NULL)
              return TxtRetour;
       
          if(!str_replace_without_alloc(TxtRetour, tailleTxtRetour, txt, Avant, Apres)) {
              free(TxtRetour);
              TxtRetour = NULL;
          }
       
          return TxtRetour;
      }

Discussions similaires

  1. Réponses: 3
    Dernier message: 14/11/2012, 15h25
  2. Réponses: 5
    Dernier message: 26/11/2011, 13h09
  3. Réponses: 4
    Dernier message: 07/07/2010, 09h33
  4. supprimer toutes les occurrences d'une chaine dans une autre
    Par identifiant_bidon dans le forum Langage
    Réponses: 3
    Dernier message: 21/11/2007, 10h36
  5. Nombre d'occurrences d'une sous chaîne
    Par yanice dans le forum Langage
    Réponses: 2
    Dernier message: 22/03/2007, 16h37

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo