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 :

Problème de gestion de chaînes avec pointeur


Sujet :

C

  1. #1
    Membre du Club
    Inscrit en
    Août 2005
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 49
    Points : 48
    Points
    48
    Par défaut Problème de gestion de chaînes avec pointeur
    Bonjour à tous.

    Voici mon problème : dans le cadre d'un exercice en rapport avec mon cours, je dois reprogrammer, sans utiliser les indices de tableaux (pas de tab[i] en gros), quelques fonctions déjà existantes (strcat, strcpy, etc).

    Voici mon bout de code pour la fonction de concaténation :

    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
    void * concatenation(char *s1,char *s2)
    {
     
    	while(*s1 != '\0') {
    		s1++;
    	}
    	s1--;
     
    	while(*s2 != '\0') {
    		*s1 = *s2;
    		s1++;
    		s2++;
    	}
     
    	*s1 = '\0';
    }
    Que j'appelle comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      printf("s1 concatene avec s2 donne %s",concatenation(s1,s2));
    Alors je vais expliquer le raisonnement que j'ai suivi pour que quelqu'un puisse me dire où ça coince :

    1-je parcours la première chaîne jusqu'à tomber sur le caractère de fin de chaîne '\0' ; j'avance mon pointeur de 1 vu que le type char prend un octet
    2-ensuite, je recule d'un cran pour ne pas écrire après le '\0' (quoique... effet de bord ou pas, je sais plus)
    3-je parcours la deuxième chaîne jusqu'à tomber sur '\0', et à chaque parcours, je mets la valeur *s2 dans la valeur *s1, et j'incrémente de 1 les deux pointeurs pour passer à l'emplacement de lettre suivant
    4-pour finir, je rajoute un '\0' pour avoir une chaîne de caractères valide

    Ah, initialement je déclarais la fonction en char *, mais je voyais mal ce qu'il fallait que je renvoie avec return.

    Enfin voilà, merci d'avance pour votre aide. ^^

  2. #2
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    Moi je viens de tester, compiler executer et ca fonctionne.

    Bon sinon
    1-je parcours la première chaîne jusqu'à tomber sur le caractère de fin de chaîne '\0' ; j'avance mon pointeur de 1 vu que le type char prend un octet
    Meme si c'etait des int ca n'etait pas besoin de faire *s1 +=sizeof(int)
    L'arithmetique des pointeurs se charge de tout

    Ah, initialement je déclarais la fonction en char *, mais je voyais mal ce qu'il fallait que je renvoie avec return.
    Pourquoi void *, tout simplement void

    2-ensuite, je recule d'un cran pour ne pas écrire après le '\0' (quoique... effet de bord ou pas, je sais plus)
    Pas besoin (d'aileurs si tu le fais tu perds un caractere)

  3. #3
    Membre du Club
    Inscrit en
    Août 2005
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 49
    Points : 48
    Points
    48
    Par défaut
    void * à cause du printf %s, sinon mon compilo me renvoie une erreur de toute façon.

    Mais c'est marrant, j'ai retesté, et ça marche pas.
    Testé avec ceci :

    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
    #include <stdio.h>
     
    #define DIM 256
     
    void * concatenation(char *s1,char *s2)
    {
     
    	while(*s1 != '\0') {
    		s1++;
    	}
    	s1--;
     
    	while(*s2 != '\0') {
    		*s1 = *s2;
    		s1++;
    		s2++;
    	}
     
    	*s1 = '\0';
    }
     
    int main(void)
    {
      char s1[DIM],s2[DIM];
     
      puts("Entrez une chaine de caracteres : \r\n");
      scanf("%s",s1);
      puts("Entrez une autre chaine de caracteres : \r\n");
      scanf("%s",s2);
     
      printf("s1 concatene avec s2 donne %s \r\n",concatenation(s1,s2));
     
        return 0;
    }
    J'entre 'aaa', puis 'bbb', il me sort :
    "s1 concatene avec s2 donne"

  4. #4
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    Ben justement ton code ne compile pas.
    2 warning (option -Wall au compilo)
    warning: control reaches end of non-void function
    warning: char format, void arg (arg 2)

    Mais pourquoi donc?
    Alors a ton fonction tu refiles 2 pointeurs sur un caractere.
    Donc si tu modifie s1 et s2 dans ton fonction ca les modifie dans ton main.
    Et pour le return, il attend que tu retourne un pointeur sur n'importe quoi (char, int, double) [il me semble].
    Essaye ce code, il fonctionne

    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
     
    #include <stdio.h>
     
    #define DIM 256
     
    void concatenation(char *s1,char *s2)
    {
     
       while(*s1 != '\0') {
          s1++;
       }
     
       while(*s2 != '\0') {
          *s1 = *s2;
          s1++;
          s2++;
       }
     
       *s1 = '\0';
    }
    int main(void)
    {
      char s1[DIM],s2[DIM];
     
      puts("Entrez une chaine de caracteres : \r\n");
      fgets(s1, DIM, stdin);
      s1[strlen(s1)-1] = 0; /* on envleve le \n */
      puts("Entrez une autre chaine de caracteres : \r\n");
      fgets(s2, DIM, stdin);
      s2[strlen(s2)-1] = 0; /* on envleve le \n */
      concatenation(s1,s2);
      printf("s1 concatene avec s2 donne %s \r\n",s1);
     
      return 0;
    }
    J'ai remplacé scanf par fgets (pour pouvoir saisir des chaines avec des espaces.

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 379
    Points : 41 573
    Points
    41 573
    Par défaut
    à mon avis, il essaie de faire l'équivalent de strcat(chn1, chn2) qui retourne chn1 en cas de réussite
    (permet de passer la valeur de retour de strcat directement à printf, mais si plusieurs appels à strcat/concatenation sont effectués dans le même appel, l'ordre est indéfini : en fait dans ce cas, mieux vaut renvoyer void pour forcer à appeler la fonction séparément)

  6. #6
    Membre du Club
    Inscrit en
    Août 2005
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 49
    Points : 48
    Points
    48
    Par défaut
    Oui, merci, je viens de comprendre ma bêtise (%s avec concatenation(s1,s2) alors que la fonction est déclarée en void et ne renvoie donc rien). Ca marche !

    Mais en suivant ce principe, si je déclare ma fonction en char*, que je lui dis return s1, et que dans mon printf j'indique à afficher concatenation(s1,s2), je n'ai plus rien, est-ce normal ? =/

  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
    Citation Envoyé par Médinoc
    en fait dans ce cas, mieux vaut renvoyer void pour forcer à appeler la fonction séparément)
    Tiens, oui. Bonne idée.

  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
    Citation Envoyé par LorDjidane
    Mais en suivant ce principe, si je déclare ma fonction en char*, que je lui dis return s1, et que dans mon printf j'indique à afficher concatenation(s1,s2), je n'ai plus rien, est-ce normal ? =/
    Ben oui, puisque s1 a bougé (s1++ ...). C'est pourquoi je défend un principe qui veut que la valeur d'un paramètre doit rester inchangée :

    <edit="ajouté retour de type char" />
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    char *concatenation (char *const s1, char *const s2)
    {
       ...
       return s1;
    }
    Ca oblige à utiliser des pointeurs locaux (ou des indices).

  9. #9
    Membre du Club
    Inscrit en
    Août 2005
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 49
    Points : 48
    Points
    48
    Par défaut
    Bon ben merci pour les infos.
    J'ai toujours du mal à comprendre comment renvoyer quelque chose de type char* ; bon, à la rigueur je peux me contenter du void, mais si quelqu'un pouvait juste m'expliquer comment faire (histoire que ça me reserve une prochaine fois).

  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 LorDjidane
    J'ai toujours du mal à comprendre comment renvoyer quelque chose de type char* ; bon, à la rigueur je peux me contenter du void, mais si quelqu'un pouvait juste m'expliquer comment faire (histoire que ça me reserve une prochaine fois).
    Voir ma réponse ci-dessus (j'ai fait une correction).

  11. #11
    Membre habitué
    Profil pro
    Inscrit en
    Août 2005
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 142
    Points : 127
    Points
    127
    Par défaut Re: Problème de gestion de chaînes avec pointeur
    Tu peux même remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	while(*s2 != '\0') {
    		*s1 = *s2;
    		s1++;
    		s2++;
    	}
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	while(*s2) {
    		*s1++ = *s2++;
    	}
    C'est plus geek, tu blufferas ton profs comme ça

  12. #12
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut Re: Problème de gestion de chaînes avec pointeur
    Citation Envoyé par tomasha
    Tu peux même remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    	while(*s2 != '\0') {
    		*s1 = *s2;
    		s1++;
    		s2++;
    	}
    par

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    	while(*s2) {
    		*s1++ = *s2++;
    	}
    C'est plus geek, tu blufferas ton profs comme ça
    Et tu auras 0 pour manque de lisibilité du code ! (cf un post précédent d'Emmanuel)
    Autant faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while (*s1++ = *s2++) ;

  13. #13
    Membre habitué
    Profil pro
    Inscrit en
    Août 2005
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 142
    Points : 127
    Points
    127
    Par défaut Re: Problème de gestion de chaînes avec pointeur
    Citation Envoyé par Trap D
    Et tu auras 0 pour manque de lisibilité du code ! (cf un post précédent d'Emmanuel)
    Beuuuuh non, il suffit d'ajouter un petit commentaire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    /* copie optimisée de s2 dans s1 */
    while (*s2) {
          *s1++ = *s2++;
       }
    Une code correctement indenté est toujours lisible si il est suffisamment commenté !!!

  14. #14
    Membre habitué
    Profil pro
    Inscrit en
    Août 2005
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 142
    Points : 127
    Points
    127
    Par défaut Re: Problème de gestion de chaînes avec pointeur
    Citation Envoyé par Trap D
    Autant faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while (*s1++ = *s2++) ;
    Ca marche ça aussi ?
    Ouah encore plus geek, génial

  15. #15
    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: Problème de gestion de chaînes avec pointeur
    Citation Envoyé par tomasha
    Citation Envoyé par Trap D
    Et tu auras 0 pour manque de lisibilité du code ! (cf un post précédent d'Emmanuel)
    Beuuuuh non, il suffit d'ajouter un petit commentaire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    /* copie optimisée de s2 dans s1 */
    while (*s2) {
          *s1++ = *s2++;
       }
    Une code correctement indenté est toujours lisible si il est suffisamment commenté !!!
    De toutes façons,
    pour Trap D et tomasha, car le 0 final n'est jamais copié...

  16. #16
    Membre habitué
    Profil pro
    Inscrit en
    Août 2005
    Messages
    142
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 142
    Points : 127
    Points
    127
    Par défaut Re: Problème de gestion de chaînes avec pointeur
    Citation Envoyé par Emmanuel Delahaye
    De toutes façons,
    pour Trap D et tomasha, car le 0 final n'est jamais copié...
    Ouah attends je n'ai posté qu'une partie de code, la partie à remplacer !!
    Le reste est toujours valable, notamment le


  17. #17
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut Re: Problème de gestion de chaînes avec pointeur

    pour Emmanuel
    Révise le K & R (page 98 edition 1986.)

    Ceci dit, on peut éviter

  18. #18
    Membre du Club
    Inscrit en
    Août 2005
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 49
    Points : 48
    Points
    48
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Citation Envoyé par LorDjidane
    J'ai toujours du mal à comprendre comment renvoyer quelque chose de type char* ; bon, à la rigueur je peux me contenter du void, mais si quelqu'un pouvait juste m'expliquer comment faire (histoire que ça me reserve une prochaine fois).
    Voir ma réponse ci-dessus (j'ai fait une correction).
    Ah d'accord !
    Je m'inquiétais parce que mon compilo (gcc sur une redhat) m'indiquait des trucs en plus

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    blo.c:17: increment d'une position en lecture seule
    blo.c:23: increment d'une position en lecture seule
    blo.c:24: increment d'une position en lecture seule
    Mais apparemment tout fonctionne. Tant mieux.
    Merci beaucoup.
    (hop, tag résolu)

  19. #19
    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 LorDjidane
    Je m'inquiétais parce que mon compilo (gcc sur une redhat) m'indiquait des trucs en plus
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    blo.c:17: increment d'une position en lecture seule
    blo.c:23: increment d'une position en lecture seule
    blo.c:24: increment d'une position en lecture seule
    Ca, c'est normal, c'est pour t'inviter à ne plus modifier le paramètre pointeur, mais à en utiliser un autre 'jetable' (local, initialisé avec la valeur du paramètre)

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

Discussions similaires

  1. Réponses: 11
    Dernier message: 25/03/2008, 23h12
  2. Réponses: 3
    Dernier message: 27/10/2007, 00h39
  3. Problème de gestion des langues avec MFC
    Par Figaro dans le forum Visual C++
    Réponses: 4
    Dernier message: 20/11/2006, 15h56
  4. [Upload] Problème pour gestion d'erreur avec class
    Par allserv dans le forum Langage
    Réponses: 2
    Dernier message: 27/12/2005, 13h00
  5. [TFrame] Problème de gestion du OnMouseDown avec une Frame
    Par xherault dans le forum Composants VCL
    Réponses: 5
    Dernier message: 23/05/2003, 15h35

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