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 :

Operation sur chaine de caractere


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 41
    Points : 24
    Points
    24
    Par défaut Operation sur chaine de caractere
    Bonjour a vous,
    Voila j'ai l'impression que ma fonction est a l'origine de mes erreurs quand je lance un valgrind sur mon code.
    De plus je ne vois pas trop comment je pourrais faire pour libérer la place mémoire de ma chaîne res...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    char * EnleveLigne (char *s, int NbreLigne)
    {
     int i=0;
     if (!s) {fprintf(stderr,"La chaine passé a EnleveLigne est NULL\n"); return NULL;}
     char *res = NULL;
     for (i=0; i<NbreLigne;i++)
      {
       res = strchr (s,'\n');
       if (i<NbreLigne-1)
          strcpy(s,res+1);
      }
     return (res+1);
    }
    Merci pour votre aide

  2. #2
    Membre éclairé 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
    Points : 858
    Points
    858
    Par défaut
    Je ne vois pas bien à quoi sert ton malloc(), puisque juste après tu modifie ton pointeur res.

  3. #3
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par BatuBou Voir le message
    Voila j'ai l'impression que ma fonction est a l'origine de mes erreurs quand je lance un valgrind sur mon code.
    De plus je ne vois pas trop comment je pourrais faire pour libérer la place mémoire de ma chaîne res...
    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
     
    char * EnleveLigne (char *s, int NbreLigne)
    {
     int i=0;
     int taille_chaine =0;
     if (!s) {fprintf(stderr,"La chaine passé a EnleveLigne est NULL\n"); return NULL;}
     taille_chaine = strlen(s);
     char *res = malloc(sizeof(char) * taille_chaine);
     for (i=0; i<NbreLigne;i++)
      {
       res = strchr (s,'\n');
       if (i<NbreLigne-1)
          strcpy(s,res+1);
      }
     return (res+1);
    }
    Si tu alloues 'res' et que tu libères res + 1, le comportement est indéfini, car une règle a été brisée :

    "la valeur passe à free() doit exactement être celle qui a été donnée par malloc()".

    Je conseille donc de retourner la valeur 'officielle' (res) et de jouer avec +1 dans l'appelant si nécessaire.

    De plus, il est probable que la taille allouée soit insuffisante (et le 0 final ?)

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par crocodilex Voir le message
    Je ne vois pas bien à quoi sert ton malloc(), puisque juste après tu modifie ton pointeur res.
    Oui, exact.

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 41
    Points : 24
    Points
    24
    Par défaut
    Merci pour votre aide

    J'ai donc enlevé mon allocation mémoire de la chaîne "res"

    mais j'ai toujours ce message de valgrind

    ==6903== Source and destination overlap in strcpy(0x4163212, 0x4163218)
    ==6903== at 0x401EA27: strcpy (mc_replace_strmem.c:106)
    ==6903== by 0x80488FF: EnleveLigne
    ==6903== by 0x8048BB2: Lire
    ==6903== by 0x8049519: main

    Sachant que ma fonction EnleveLigne est appelée dans Lire et que Lire est appelé par main.

    J'espère ne pas me tromper en disant que c'est ma fonction EnleveLigne qui est incorrecte...

  6. #6
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par BatuBou Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ==6903== Source and destination overlap in strcpy(0x4163212, 0x4163218)
    ==6903==    at 0x401EA27: strcpy (mc_replace_strmem.c:106)
    Quand la source et la destination sont dans le même tableau, utilise memmove().

  7. #7
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut
    Salut,

    Dans cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char * EnleveLigne (char *s, int NbreLigne)
    curieux de savoir la valeur que l'on peut donner à NbreLigne ?

    Et si EnleveLigne n'était que supprimer les caractères '\n' ?

  8. #8
    Membre éclairé 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
    Points : 858
    Points
    858
    Par défaut
    Citation Envoyé par dj.motte Voir le message
    Salut,

    Dans cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    char * EnleveLigne (char *s, int NbreLigne)
    curieux de savoir la valeur que l'on peut donner à NbreLigne ?

    Et si EnleveLigne n'était que supprimer les caractères '\n' ?
    A priori, NbreLigne correspond au nombre de lignes qu'il veut supprimer (en commençant par le début) de sa chaîne. Cela me paraissait trivial....

  9. #9
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 41
    Points : 24
    Points
    24
    Par défaut
    J'essaye avec memmove mais il me fait une erreur de segmentation,

    ==7583== Process terminating with default action of signal 11 (SIGSEGV)
    ==7583== Bad permissions for mapped region at address 0x80486D4
    ==7583== at 0x401E544: memmove (mc_replace_strmem.c:503)
    ==7583== by 0x8048508: EnleveLigne
    ==7583== by 0x804856C: main

    Oui c'est supprimer tout ce qui est avant un "\n", dans l'ideal il me renvoie le texte apres avoir supprimer les "NbreLigne" premieres lignes de mon texte

    Merci pour votre aide

  10. #10
    Membre éclairé 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
    Points : 858
    Points
    858
    Par défaut
    Citation Envoyé par BatuBou Voir le message
    J'essaye avec memmove mais il me fait une erreur de segmentation,

    ==7583== Process terminating with default action of signal 11 (SIGSEGV)
    ==7583== Bad permissions for mapped region at address 0x80486D4
    ==7583== at 0x401E544: memmove (mc_replace_strmem.c:503)
    ==7583== by 0x8048508: EnleveLigne
    ==7583== by 0x804856C: main
    Montres ton code modifié.

    Sinon, tu peux essayer ceci (ma version ne modifie pas la chaine source) :
    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
    char *EnleveLigne(const char *s, int NbreLigne)
    {
        int i = 0;
        char *res = NULL;
        char *p_next_line = NULL;
        char *p_temp = (char *)s;
     
        if (s != NULL)
        {
            do
            {
                p_next_line = strchr (p_temp, '\n');
                if (p_next_line != NULL)
                {
                    p_temp = p_next_line + 1;
                    i++;
                }
            }
            while( (i != NbreLigne) && (p_next_line != NULL) );
     
            if ( p_next_line != NULL )
            {
                res = malloc(strlen(p_temp) + 1);
                if (res != NULL )
                {
                   strcpy(res, p_temp);
                }
            }
        }
        return (res);
    }

  11. #11
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 41
    Points : 24
    Points
    24
    Par défaut
    Merci pour votre aide, votre code fonctionne parfaitemment

    Attention a vos yeux, tres vilain code
    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
    char * EnleveLigne (char *s, int NbreLigne)
    {
     int i=0;
     size_t taille_chaine =0;
     if (!s) {fprintf(stderr,"La chaine passé a EnleveLigne est NULL\n"); return NULL;}
     
     char *res;
     for (i=0; i<NbreLigne;i++)
      {
       res = strchr (s,'\n');
       taille_chaine = strlen(res);
       if (i<NbreLigne-1)
          memmove((char *)s,(char *)res+1,taille_chaine);
      }
     return (res+1);
    }

  12. #12
    Membre éclairé 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
    Points : 858
    Points
    858
    Par défaut
    Citation Envoyé par BatuBou Voir le message
    Merci pour votre aide, votre code fonctionne parfaitemment

    Attention a vos yeux, tres vilain code
    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
    char * EnleveLigne (char *s, int NbreLigne)
    {
     int i=0;
     size_t taille_chaine =0;
     if (!s) {fprintf(stderr,"La chaine passé a EnleveLigne est NULL\n"); return NULL;}
     
     char *res;
     for (i=0; i<NbreLigne;i++)
      {
       res = strchr (s,'\n');
       taille_chaine = strlen(res);
       if (i<NbreLigne-1)
          memmove((char *)s,(char *)res+1,taille_chaine);
      }
     return (res+1);
    }
    Ne pas oublier de déplacer le caractère de fin de chaine :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
          memmove((char *)s,(char *)res+1,taille_chaine+1);
    Étant donné que tu modifie la chaîne source, il faudra juste veiller à ce qu'elle ne soit pas en lecture seule.

  13. #13
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    41
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 41
    Points : 24
    Points
    24
    Par défaut
    Oui effectivement elle etait en lecture seule...
    Ca marche bien maintenant

    Merci pour votre aide

    Bonne journée

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

Discussions similaires

  1. [XSLT] operation sur chaines de caractere
    Par jeb001 dans le forum XSL/XSLT/XPATH
    Réponses: 1
    Dernier message: 25/01/2008, 09h14
  2. recherche sql sur chaines de caractere
    Par alexkickstand dans le forum Langage SQL
    Réponses: 5
    Dernier message: 31/08/2007, 09h37
  3. operation sur chaine de caracteres
    Par aliboubou dans le forum Access
    Réponses: 11
    Dernier message: 11/01/2007, 11h36
  4. [sqlserver2000]operations sur chaine
    Par graphicsxp dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 26/05/2006, 16h48
  5. Réponses: 3
    Dernier message: 19/12/2004, 14h30

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