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 :

fonction manipulant une string


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut fonction manipulant une string
    Bonjour, je désire me faire une fonction qui "supprime" tous les espaces contenus dans la string. Donc si j'ai une string "1 2 3 4 5" ma sortie doit être "12345". Mais j'ai un segmentation fault et je ne comprends pas pourquoi. Je vous envoie ma 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
     
    #include<stdlib.h>
    #include<stdio.h>
    #include<ctype.h>
    #include<string.h>
     
    void DeleteAllSpaces(char * s)
    {
      unsigned int i,j;
      for(i=0;i<strlen(s);++i)
      {
        if(isspace(s[i]))
        {
          for(j=i;j<strlen(s);++j)
            s[j]=s[j+1];
          s[strlen(s)-1]='\0';
        }
      }
    }
     
    int main()
    {
      char * s="1 2 3 4 5 6";
      DeleteAllSpaces(s);
      printf("s =%s\n",s);
     
      return 0;
    }
    Mon algo est pourtant ultra simple (mais pas du tout optimisé !). Pouvez-vous m'expliquer mon erreur s'il vous plait ? Merci.

  2. #2
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Points : 9 860
    Points
    9 860
    Par défaut
    Bonjour,

    ton segmentation fault est normal.
    supposons que tu as un espace en dernière position de ta chaine de caractère, soit en "strlen(s)-1".
    Tu vas donc entrer dans ta boucle "for(j=i;j<strlen(s);..." or, cette condition est juste puisque j=i=strlen(s)-1<strlen(s) et ensuite à la ligne du dessous, tu demandes d'accéder à s[i+1] qui n'existe pas. Tu débordes donc à la fin de ton tableau.
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    oui mais là dans mon exemple je n'ai pas d'espace à la fin de ma string, alors d'où vient mon bug ?
    j'avais penser traiter ce cas une fois que mon test fonctionnerait sur un cas simple (ce qui n'est pas encore le cas). Mais voici mon code qui tient compte de ta remarque (mais qui ne marche toujours pas)

    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
     
    #include<stdlib.h>
    #include<stdio.h>
    #include<ctype.h>
    #include<string.h>
     
    void DeleteFinalSpaces(char * s)
    {
      /* this function deletes all the spaces between the last char of s which is
         not a space (a blank char) and the char '\0'
      */
      unsigned short i;
      for(i=strlen(s)-1;isspace(s[i]);--i);
      s[i+1]='\0';  
    }
     
    void DeleteAllSpaces(char * s)
    {
      DeleteFinalSpaces(s);
      unsigned int i,j;
      for(i=0;i<strlen(s);++i)
      {
        if(isspace(s[i]))
        {
          for(j=i;j<strlen(s);++j)
            s[j]=s[j+1];
          s[strlen(s)-1]='\0';
        }
      }
    }
     
    int main()
    {
      char * s="1 2 3 4 5 6";
      DeleteAllSpaces(s);
      printf("s =%s\n",s);
     
      return 0;
    }

  4. #4
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Citation Envoyé par ToTo13
    Bonjour,

    ton segmentation fault est normal.
    supposons que tu as un espace en dernière position de ta chaine de caractère, soit en "strlen(s)-1".
    Tu vas donc entrer dans ta boucle "for(j=i;j<strlen(s);..." or, cette condition est juste puisque j=i=strlen(s)-1<strlen(s) et ensuite à la ligne du dessous, tu demandes d'accéder à s[i+1] qui n'existe pas. Tu débordes donc à la fin de ton tableau.
    C'est faux...

    En supposant bien sûr que la zone mémoire soit suffisante pour contenir la chaîne...

    Puisqu'on a la supposition que j<strlen(s), on peut très bien accéder à la case j+1, ce sera la case qui contient le '\0'... Le fait qu'il y ait un espace à la fin ou non...

    Je rappelle à titre d'exemples:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char *s = "a"  /* -> strlen(s) == 1, à la case s[1]=='\0' */
    char *s = "abc" /* -> strlen(s) == 3 */

    La raison du segmentation fault est ici:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      char * s="1 2 3 4 5 6";
    Comme il a souvent été dit, une telle déclaration met généralement (mais pas toujours) la chaîne "1 2 3 4 5 6" dans une zone en lecture seule. Ce qui engendre un segmentation fault lors de sa modification... Ce qui est surement ton problème.

    Pour résoudre ton problème voir la FAQ:
    http://c.developpez.com/faq/c/?page=...GS_string_init

    Ensuite Toto a mis le point sur un problème algorithmique... Lorsque tu repères un espace, tu décales la chaîne, et ensuite tu décales le '\0'... Es-tu sûr de n'avoir pas déjà décalé l'ancien '\0'?

    Je dis que oui...

    Jc

  5. #5
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Points : 9 860
    Points
    9 860
    Par défaut
    Je suis d'accord avec la dernière remarque de fearyourself.

    Si tu veux un algo tres simple, non optimisé et qui fonctionne parfaitement, tu utlises une deuxième chaine de caractères (vide au début) dans laquelle tu recopies tous les caractères qui sont différents des espaces.
    C'est pas forcément tres joli, mais ca marche et le risque d'erreur est minimisé.[/code]
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    OK, merci ! voilà mon code qui marche. L'erreur venait bien de mon main char * s="1 2 3 4 5 6";

    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
     
    #include<stdlib.h>
    #include<stdio.h>
    #include<ctype.h>
    #include<string.h>
     
    void DeleteFinalSpaces(char * s)
    {
      /* this function deletes all the spaces between the last char of s which is
         not a space (a blank char) and the char '\0'
      */
      unsigned short i;
      for(i=strlen(s)-1;isspace(s[i]);--i);
      s[i+1]='\0';  
    }
     
    void DeleteAllSpaces(char * s)
    {
      DeleteFinalSpaces(s);
      unsigned int i,j;
      for(i=0;i<strlen(s);++i)
      {
        if(isspace(s[i]))
        {
          for(j=i;j<strlen(s);++j)
            s[j]=s[j+1];
        }
      }
    }
     
    int main()
    {
      char s[]="1 2 3 4 5 6  ";
      DeleteAllSpaces(s);
      printf("s =%stoto\n",s);
     
      return 0;
    }
    Merci !

  7. #7
    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 Re: fonction manipulant une string
    Citation Envoyé par salseropom
    Bonjour, je désire me faire une fonction qui "supprime" tous les espaces contenus dans la string.
    http://emmanuel-delahaye.developpez.com/clib.htm
    Module STR
    Fonction STR_DelBlanks()

    Evidemment, la chaine d'origine doit être modifiable, ce qui n'est las le cas d'une chaine littérale...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      char * s="1 2 3 4 5 6";
    Non !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      char s[]="1 2 3 4 5 6";
    Pas de Wi-Fi à la maison : CPL

  8. #8
    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 Re: fonction manipulant une string
    Citation Envoyé par salseropom
    Mon algo est pourtant ultra simple (mais pas du tout optimisé !).
    Il tout sauf simple et il est surtout très faux...

    Ca, c'est simple. Je ne sais pas si c'est optimisé, mais je m'en tamponne...
    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
     
    #include<stdio.h>
    #include<ctype.h>
    #include<string.h>
     
    void DeleteAllSpaces(char * s)
    {
       size_t const n = strlen(s);
       size_t r = 0;
       size_t w = 0;
       while (r < n)
       {
          if (!isspace(s[r]))
          {
             s[w] = s[r];
             w++;
          }
          r++;
       }
       s[w] = 0;
    }
     
    int main(void)
    {
       char s[] = " 1 2 3 4 5 6 ";
       printf("s = '%s'\n", s);
       DeleteAllSpaces(s);
       printf("s = '%s'\n", s);
     
       return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    s = ' 1 2 3 4 5 6 '
    s = '123456'
    Pas de Wi-Fi à la maison : CPL

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Merci pour ta fonction. j'ai encore qq progrès à faire (mais je progresse) quant à la manipulation des strings.

  10. #10
    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 salseropom
    Merci pour ta fonction. j'ai encore qq progrès à faire (mais je progresse) quant à la manipulation des strings.
    Tu dois surtout viser la simplicité. Pour ça, il faut travailler tes algorithmes. C'est un problème de 'culture générale de programmeur', pas de langage C... La solution ne dépend pas (ou peu) du langage (OK, c'est une chaine C).
    Pas de Wi-Fi à la maison : CPL

  11. #11
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut Re: fonction manipulant une string
    Citation Envoyé par Emmanuel Delahaye
    Ca, c'est simple. Je ne sais pas si c'est optimisé, mais je m'en tamponne...
    Ce n'est pas tres optimise, en effet. En regle general, on peut considerer qu'appeler strlen() avant de boucler sur les elements d'une chaine est peu optimise (il est fort probable que strlen() boucle elle-meme a la recherche du terminateur '\0').

    En fait, on n'a pas besoin de connaitre la longueur de la chaine:
    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
     
    #include<ctype.h>
     
    void delete_spaces(char *s)
    {
      char *w = s;
     
      while(*s)
      {
        if(!isspace(*s))
        {
          *w = *s;
          w++;
        }
        s++;
      }
      *w = '\0';
    }

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    1 298
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 298
    Points : 886
    Points
    886
    Par défaut
    Effectivement, en plus de travailler mes algos, j'ai de quoi travailler l'optimisation (même si c'est lié vous allez me dire).

    Merci encore de votre aide !

  13. #13
    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 Re: fonction manipulant une string
    Citation Envoyé par DaZumba
    Citation Envoyé par Emmanuel Delahaye
    Ca, c'est simple. Je ne sais pas si c'est optimisé, mais je m'en tamponne...
    Ce n'est pas tres optimise, en effet.
    Exact.
    Ca me rappelle quelquechose :
    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
     
    /* ---------------------------------------------------------------------
       STR_DelBlanks()
       ---------------------------------------------------------------------
       Suppression des blancs dans une chaine
       LA CHAINE EST MODIFIEE !!!
       ---------------------------------------------------------------------
       E : Chaine initiale
       S :
       --------------------------------------------------------------------- */
    void STR_DelBlanks (char *const s)
    {
       ENUM_CHECK ();
     
       if (s && *s)
       {
          char const *pr = s;
          char *pw = s;
     
          while (*pr)
          {
             if (*pr != ' ')
             {
                *pw = *pr;
                pw++;
             }
             pr++;
          }
     
          *pw = 0;
       }
    }
    Hé hé.
    Pas de Wi-Fi à la maison : CPL

  14. #14
    Membre expérimenté
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Points : 1 664
    Points
    1 664
    Par défaut Re: fonction manipulant une string
    Citation Envoyé par Emmanuel Delahaye
    Ca me rappelle quelquechose:
    Oh, je ne pretendais pas soumettre une implementation entierement nouvelle
    Mais j'ai pas copie, promis!

  15. #15
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut Re: fonction manipulant une string
    Citation Envoyé par DaZumba
    Citation Envoyé par Emmanuel Delahaye
    Ca me rappelle quelquechose:
    Oh, je ne pretendais pas soumettre une implementation entierement nouvelle
    Mais j'ai pas copie, promis!
    Attention vous deux, sinon je divise votre note par deux et ça sera bien fait...

  16. #16
    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 Re: fonction manipulant une string
    Citation Envoyé par fearyourself
    Citation Envoyé par DaZumba
    Citation Envoyé par Emmanuel Delahaye
    Ca me rappelle quelquechose:
    Oh, je ne pretendais pas soumettre une implementation entierement nouvelle
    Mais j'ai pas copie, promis!
    Attention vous deux, sinon je divise votre note par deux et ça sera bien fait...
    T'awar ta gueule à la récrée!
    Pas de Wi-Fi à la maison : CPL

  17. #17
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Ça pourrait être pas mal de compiler avec l'option -Wwrite-strings.
    Boost ftw

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

Discussions similaires

  1. Manipuler une string
    Par yanis97 dans le forum C
    Réponses: 4
    Dernier message: 21/10/2010, 18h13
  2. Appel d'une fonction par une string depuis un plugin
    Par cahnory dans le forum jQuery
    Réponses: 1
    Dernier message: 04/06/2010, 21h11
  3. [AC-2003] Fonction retournant une string dans un état
    Par yupyupxav dans le forum IHM
    Réponses: 2
    Dernier message: 28/02/2010, 18h41
  4. Fonction renvoyant une string
    Par salseropom dans le forum C
    Réponses: 8
    Dernier message: 04/05/2006, 11h44
  5. [XSLT] Manipulation d'une String
    Par Eskarina43 dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 15/06/2004, 11h52

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