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

C Discussion :

Petit problème de remplacement de sous-chaîne


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut Petit problème de remplacement de sous-chaîne
    Bonjour,


    Dans le cours de mon projet de développement, je met à jour mon Objet String perso que j'utilise dans le projet par l'ajout de quelques fonctions (voilà pour l'intro )

    J'ai créé une table de style clé/valeur (en fait ancienne/nouvelle sous-chaine) sous forme de pile. Ce nouveau type est donc utilisé dans une fonction de remplacement que voici:

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    C_Str_error C_Str_replace_from_table (C_Str * const self,
                                          C_Str_table * const table)
    {
       C_Str_error err = C_STR_NO_ERR;
     
     
       if (self != NULL && table != NULL)
       {
          size_t         count = 0;
          char        *  p     = self->sz_string;
          C_Str_table *  t     = table;
     
     
          /* Parcours de la chaine caracteres par caracteres. */
          while (*p)
          {
             /*
              * Pour chaque avancement dans la chaine, on compare la liste complete
              * des ID dans la table d'ensemble.
              */
             while (t != NULL)
             {
                if (*p == t->id[0])
                {
                   if (memcmp (p, t->id, t->id_size) == 0)
                   {
                      C_Str_replace_string (self, count, t->id_size - 1, t->data);
                      break;
                   }
                }
     
                /* Passage a l'ID suivant. */
                t = t->next;
             }
     
     
             t = table;
             p++;
             count++;
          }
       }
       else
       {
          err = C_STR_NULL_ARG;
       }
     
     
       return err;
    }
    Voici également la fonction de remplacement utilisée dans cette fonction:

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    C_Str_error C_Str_replace_string (C_Str * const self,
                                      size_t start,
                                      size_t lenght,
                                      char const * const s_str)
    {
       C_Str_error err = C_STR_NO_ERR;
       char * tmp_str = NULL;
       size_t size = 0;
     
     
       if (self != NULL && self->sz_string != NULL && s_str != NULL)
       {
          if (self->len > 0)
          {
             size = strlen (s_str);
             tmp_str = malloc (self->len - lenght + size);
     
             if (tmp_str != NULL)
             {
                /* ----- Construction de la nouvelle chaine ----- */
     
                /* Debut de la chaine d'origine. */
                memcpy (tmp_str, self->sz_string, start);
     
                /* Nouvelle chaine. */
                memcpy (&tmp_str[start], s_str, size);
     
                /* Fin de la chaine d'origine. */
                memcpy (
                   &tmp_str[start + size],
                   &self->sz_string[start + lenght + 1],
                   self->len - lenght - start
                );
                /* ----- */
     
     
                err = C_Str_resize (self, strlen (tmp_str));
     
                if (err == C_STR_NO_ERR)
                {
                   memset (self->sz_string, 0, self->len + 1);
                   memcpy (self->sz_string, tmp_str, self->len);
                }
     
     
                free (tmp_str);
                tmp_str = NULL;
             }
             else
             {
                /* Erreur: impossible d'allouer l'espace requis. */
                err = C_STR_DYN_ALLOC_ERR;
             }
          }
          else
          {
             /* Erreur: la chaine est vide. */
             err = C_STR_BAD_STR_LEN;
          }
       }
       else
       {
          /* Erreur: probleme avec un argument passe en parametre. */
          err = C_STR_NULL_ARG;
       }
     
     
       return err;
    }
    J'ai un problème de remplacement dont je ne trouve pas l'origine, ce problème survient lorsque la chaine de remplacement est trop longue (ceci dit dans mes tests elles ne sont pas longues du tout, ce que je ne comprend pas).

    Voici la sortie avec mes tests:

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    C_Str, C ANSI/ISO String object - 2.2.0
     
     
    <date/> : 09/07/08
    <file/> : main.c
    <copy/> : (c) 2008
    <mail/> : franhec@gmail.com
    <author/> : HECHT Franck
    <project/> : CFG
     
     
    id: <project/>, count: 8, *p: <
     
     
    toto
       CFG
       <file/>
       <author/> - <copy/>
       <mail/>
       <date/>
    toto
     
    id: <file/>, count: 15, *p: <
     
     
    toto
       CFG
       main.c
       <author/> - <copy/>
       <mail/>
       <date/>
    toto
     
    id: <author/>, count: 25, *p: <
     
     
    toto
       CFG
       main.c
       HECHT Franck - <copy/>
       <mail/>
       <date/>
    toto
     
    id: <copy/>, count: 40, *p: <
     
     
    toto
       CFG
       main.c
       HECHT Franck - (c) 2008
       <mail/>
       <date/>
    toto
     
    id: <mail/>, count: 52, *p: <
     
     
    toto
       CFG
       main.c
       HECHT Franck - (c) 2008
       franhec@gmail.com
       <date/>
    toto
     
    id: <date/>, count: 63, *p: <
     
     
    toto
       CFG
       main.c
       HECHT Franck - (c) 2008
       franhec@gma09/07/08   <date/>
    toto
     
     
    Process returned 0 (0x0)   execution time : 0.000 s
    Press any key to continue.
    On peut remarquer que l'avant dernière balise est correctement remplacée mais la dernière, est détectée trop tôt par rapport à son emplacement d'origine, ce qui est vraiment bizarre je vous l'accorde mais je ne trouve pas pourquoi

    Si vous voyez quelque chose....


    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  2. #2
    Membre émérite Avatar de crocodilex
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    697
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 697
    Par défaut
    Je ne sais pas si cela peut t'aider, mais en ajoutant un retour chariot à la dernière ligne de ton fichier txt, ça a l'air de fonctionner...

  3. #3
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    En compilant ton archive, j'ai déjà vu deux soucis (qui n'ont a priori pas de rapport avec le comportement observe):

    * Un petit problème de const-correctness, le paramètre data de C_Str_table_set() devrait être const (information à redescendre aux autres fonctions si nécessaire bien entendu).
    * Ce n'est pas va_start (params, format->sz_string); mais va_start (params, format);

    Je continue à regarder concernant le problème initial.

  4. #4
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par gl Voir le message
    Un petit problème de const-correctness, le paramètre data de C_Str_table_set() devrait être const (information à redescendre aux autres fonctions si nécessaire bien entendu).
    Oui exact, j'avais pas fait attention à ca, c'est corrigé

    Citation Envoyé par gl Voir le message
    Ce n'est pas va_start (params, format->sz_string); mais va_start (params, format);
    En fait oui tu as raison mais ce n'était pas mon but. Mon but réel était de fournir la chaîne de l'objet pour au final avoir un format printf standard, je pense qu'il faut que je revoie ce côté, sinon il faut fournir pour les autres arguments également un objet de type C_Str, ce que je ne voulais pas.

    Je suis depuis quelques temps en train de réfléchir pour faire au mieux mais sans trouver de solutions acceptables pour s'approcher du fonctionnement standard... je reste ouvert aux suggestions
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  5. #5
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par crocodilex Voir le message
    Je ne sais pas si cela peut t'aider, mais en ajoutant un retour chariot à la dernière ligne de ton fichier txt, ça a l'air de fonctionner...
    Oui exact ca fonctionne maintenant mais je ne comprend toujours pas pourquoi, il serait de le savoir tout de même

    En tous cas merci, je n'aurais jamais pensé cherché à ce niveau
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  6. #6
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    Oui exact ca fonctionne maintenant mais je ne comprend toujours pas pourquoi, il serait de le savoir tout de même
    Vu les quelques tests que je viens de faire, il semble qu'il y ait un débordement de buffer quelque part (L'ajout de trace faisant fonctionner le programme).

  7. #7
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Citation Envoyé par gl Voir le message
    Vu les quelques tests que je viens de faire, il semble qu'il y ait un débordement de buffer quelque part (L'ajout de trace faisant fonctionner le programme).
    C'était une de mes hypothèses mais sans trouver pour le moment à quel niveau

    Il faut savoir que la mémoire allouée pour la chaîne de l'objet est constamment mise à jour suivant les modification. La réallocation se fait par le biais de la fonction privée C_Str_resize.
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  8. #8
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par Franck.H Voir le message
    C'était une de mes hypothèses mais sans trouver pour le moment à quel niveau
    OK, je viens de trouver et ce n'est pas un débordement mais bel et bien un problème de gestion mémoire.

    Dans la fonction C_Str_replace_from_table() tu fais pointer p sur le début de la chaîne à modifier et tu'lincrémente par la suite.

    Lors du remplacement de balise dans la chaîne (dans la fonction C_Str_replace_string()), tu construis la chaîne final, tu resize self avec la fonction C_Str_resize() puis tu copie la chaîne finale dans self.

    Or dans la fonction C_Str_resize() tu utilises realloc() (ce qui en soi est assez logique) par contre, l'adresse retourné par realloc() peut être différente de l'adresse initiale (par exemple s'il n'y a pas suffisamment de mémoire à l'emplacement précédent).
    Lorsque cela se produit (lors de la recopie de l'adresse mail dans l'exemple fourni), la chaîne se situe à une adresse différente mais le pointeur p lui continue a adresser l'ancienne chaîne (ou la zone mémoire contenant encore la première chaîne). La position du caractère < suivant (celui de la balise date) correspond donc à l'emplacement de la balise dans la chaîne avant le remplacement de l'adresse mail et non à celle dans la chaîne courante.

    Il est donc nécessaire de remettre à jour p au retour de la fonction C_Str_replace_string(), par exemple avec p = self->sz_string + count;

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [RegExp] remplacement de sous-chaîne
    Par Pandi_Panda dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 28/06/2012, 09h47
  2. Un petit problème de sous-chaîne
    Par Tesoleil dans le forum Ada
    Réponses: 2
    Dernier message: 31/10/2010, 00h23
  3. Remplacement de sous-chaînes
    Par psych0o0 dans le forum C
    Réponses: 2
    Dernier message: 15/08/2007, 21h42
  4. Remplacer une sous chaîne par une autre
    Par Erakis dans le forum Général JavaScript
    Réponses: 15
    Dernier message: 10/11/2006, 09h16
  5. [Tableaux] Problème avec remplacement dans chaîne
    Par Baptiste Wicht dans le forum Langage
    Réponses: 5
    Dernier message: 13/07/2006, 10h04

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