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 pointeurs


Sujet :

C

  1. #1
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut Problème de pointeurs
    Bonjour,

    j'ai un petit problème de pointeurs.... (étonnant) et je ne comprends vraiment pas pourquoi ca ne marche pas.
    Pour résumer l'idée du code, je dois réaliser une pseudo bibliothèque et ajouter des ouvrages à celle-ci (ajouterEntree). Lors de l'ajout, il y a une mehode qui recherche si cet ouvrage existe deja (chercherFiche).

    Voici les deux methodes en question:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    void ajouterEntree(int type, char o_titre[],char o_dateEdition[], char o_commentaire[],  
                       char a_nom[], char a_prenom[], char a_commentaire[], char e_nom[], char e_adresse[]);
    et

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Fiche *chercherFicheExistante(Classeur *classeur, char champ1[], char champ2[]);
    Lors de mes tests, j'ai utilisé la méthode ajouterEntree de la manière suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ajouterEntree(0, "toto", "d", "d", "d", "d", "d", "d");
    Tout marche très bien ainsi au final, ce sera l'utilisateur qui remplira les differents champs (sur la console). J'ai donc développé un menu et c'est la que tout va mal.

    J'ai voulu creer des variables globales pour les differents champs dont la valeur serait ecrasee à chaque fois qu'on ajoute un ouvrage.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char o_titre[30];
    .........
    switch() {.......
                 printf(Saisissez le titre);
                 scanf("%s", o_titre);
                 ajouterEntree(0, o_titre, "d", "d", "d", "d", "d", "d");
    Et a chaque nouvel ajout d'un ouvrage, la nouvelle valeur ecrase l'ancienne mais partout, c'est a dire que la variable titre de l'ancien ouvrage prend celle
    du nouvel ouvrage.

    Je ne comprends pourquoi cela fait ca puisque normalement je passe la valeur
    que contient o_titre en argument d'ajouterEntree comme si je faisais "toto", non? Ainsi il n'y a pas de le contenu de o_titre a l'ajout suivant
    et ne devrait donc pas influer sur les ajoutrs precedents... enfin c'est ce que je croyais.


    Bon j'ai testé avec les pointeurs aussi, la ca marche si je les declare a l'interrieur du switch et pas en variables globales du fichier... encore une fois je ne comprends pas trop...

    Quelqu'un pourrait m'expliquer mon erreur s'il vous plait?

    Merci et bonne journée.

  2. #2
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    laisse moi deviner... tu n'utilises pas strcpy dans ajouterEntree ?
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  3. #3
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut
    lol t'es trop fort, justement ca plante au moment d'un strcmp
    quand je recherche si la fiche existe deja mais c'est dans le cas ou j'utilise des pointeurs et que je les declare en variables globales.

    dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Fiche *chercherFicheExistante(Classeur *classeur, char champ1[], char champ2[])
    à un moment, je compare deux strings:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     if(strcmp(champ1, ficheScan -> EditeurPtr -> nom)==0) nom1=1;
    Qu'est ce qui ne va pas alors ? Pourquoi ca ne marche pas et comment régler ca proprement?

  4. #4
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    justement, au lieu de faire des = comme tu le fais, tu devrais faire de strcpy [base de la base]

    sinon c'est l'adresse de la chaîne qui est copiée
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  5. #5
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void ajouterEntree(int type, char o_titre[],char o_dateEdition[], char o_commentaire[],char a_nom[], char a_prenom[], char a_commentaire[], char e_nom[], char e_adresse[]);
    Pour éviter le passage massif de paramètre on peut faire une structure:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct la_structure{
    int type;
    char o_titre[];
    char o_dateEdition[];
    char o_commentaire[];
    char a_nom[];
    char a_prenom[];
    char a_commentaire[];
    char e_nom[];
    char e_adresse[];
    }* pointeur_sur_la_structure;

  6. #6
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    Ou plutôt:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    typedef struct la_structure{
    int type;
    char *o_titre;
    char *o_dateEdition;
    char *o_commentaire;
    char *a_nom;
    char *a_prenom;
    char *a_commentaire;
    char *e_nom;
    char *e_adresse;
    }* pointeur_sur_la_structure;
    Car la taille de la structure doit être connue à la compilation.

  7. #7
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut
    Bonne idée pour la structure, merci

    sinon pour le strcpy... je ne vois trop le problème, je fais un strcmpr et si la valeur est a 0, ca veut dire que les deux chaines sont identiques.
    Je ne vois pas exactement ce que vient faire le strcpy. Pourrais tu détailler un peu plus tes explications s'il te plait?

    Merci.

  8. #8
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    Citation Envoyé par ceres02
    sinon pour le strcpy... je ne vois trop le problème, je fais un strcmpr et si la valeur est a 0, ca veut dire que les deux chaines sont identiques.
    Je ne vois pas exactement ce que vient faire le strcpy. Pourrais tu détailler un peu plus tes explications s'il te plait?
    Donne le corps de ta fonction ajouterEntree comme ça je pourrais m'appuyer dessus, ça sera plus simple
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  9. #9
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut
    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
    void ajouterEntree(int type, char o_titre[],char o_dateEdition[], char o_commentaire[],  char a_nom[], char a_prenom[], char a_commentaire[], char e_nom[], char e_adresse[]) {
     
            int OuvTemp_ID=0;
            int AutTemp_ID=0;
            int EditTemp_ID=0;
            int ajout = 0;
            Fiche *ficheExistante;
            if(type==0 || type==2) {
     
               //Avant d'ajouter une nouvelle fiche au classeur, on verifie si elle existe deja.
               ficheExistante = chercherFicheExistante(listeEditeur, e_nom, e_adresse);
               if(ficheExistante == NULL) {
                   //Creation du contenu de la fiche editeur.
                   Editeur *nouvelEditeur;
                   nouvelEditeur = (Editeur *)(malloc(sizeof(Editeur)));
                   nouvelEditeur -> EDITEUR_ID = (int *)(getNombreFiches(listeEditeur)+1);
                   EditTemp_ID = (int) nouvelEditeur -> EDITEUR_ID;
                   nouvelEditeur -> nom = e_nom;
                   nouvelEditeur -> adresse = e_adresse;
     
                   //Creation & ajout de la fiche.
                   Fiche *nouvelleFicheEditeur;
                   nouvelleFicheEditeur = (Fiche *)(malloc(sizeof(Fiche)));
                   nouvelleFicheEditeur -> EditeurPtr = nouvelEditeur;
                   ajouterFiche(listeEditeur, nouvelleFicheEditeur);
               }
               else EditTemp_ID = (int) ficheExistante -> EditeurPtr -> EDITEUR_ID;
            }

    Mais c'est dans la fonction chercherFicheExistante que je compare et que ca plante apparemment:

    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
    Fiche *chercherFicheExistante(Classeur *classeur, char champ1[], char champ2[]) {
          Fiche *ficheScan=NULL;
     
          if(classeur == listeEditeur) {
                      ficheScan = listeEditeur -> premiereFiche;        
                      while(ficheScan != NULL) {
     
                                      int nom1 = 0;
                                      int adresse1 = 0;
                                      //Verification des deux champs.
     
     
                                      if(strcmp(champ1, ficheScan -> EditeurPtr -> nom)==0) nom1=1;
                                      if(strcmp(champ2, ficheScan -> EditeurPtr -> adresse)==0) adresse1=1;
     
                                      //Si les deux champs sont identiques, la fiche existe deja.
                                      if(nom1 == 1 && adresse1 == 1) {
                                             break;
                                      }
                                      else {
                                             ficheScan = ficheScan -> Suivant;
                                      }
                      }
          }
    Merci encore

  10. #10
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    c'est bien ce que je me disais...

    une chaîne de caractère (en C) c'est un pointeur de caractère, une adresse de variable en gros, donc là, ce que tu fait, c'est que tu stockes l'adresse de ta chaîne de caractère, pas sa valeur, son adresse...

    résultat, quand ta variable est globale, c'est à chaque fois la même adresse que tu stockes donc quand tu en modifies une, tout est modifier...

    mais quand tu prends une variable locale au switch, à chaque passage la variable est allouée/désallouée, donc potentiellement, l'adresse change, d'où l'impression que ça fonction, alors qu'en fait, tu stockes un pointeur fantôme qui peut être modifié à n'importe quel moment par n'importe quoi (puisque non alloué)

    C'est pour ça que le bug SEMBLE se produire à la comparaison

    il faut que tu alloue et copie tes chaînes exemple pour e_nom :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    nouvelEditeur -> nom = malloc(strlen(e_nom)+1);
    strcpy(nouvelEditeur -> nom, e_nom);
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  11. #11
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut
    Donc bon pour résumer et voir si j'ai bien compris, quand je fais un "=" je faisais pointer nouvelEditeur -> nom et e_nom sur la meme variable alors qu en fait il faut que j alloue une nouvelle place a allouer pour le pointeur nouvelEditeur -> nom et que je copie le contenu pointé par e_nom dans celui du premier à l'aide de la methode strcpy?

    Merci encore, les secrets des pointeurs s'eclaircissent de jour en jour =)

  12. #12
    Membre Expert
    Avatar de Pragmateek
    Homme Profil pro
    Formateur expert .Net/C#
    Inscrit en
    Mars 2006
    Messages
    2 635
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Formateur expert .Net/C#
    Secteur : Conseil

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 635
    Par défaut
    une chaîne de caractère (en C) c'est un pointeur de caractère
    Ou plus exactement c'est une zone de mémoire contenant des caractères que l'on manipule en utilisant la syntaxe des pointeurs à partir d'un pointeur pointant sur le premier caractère de la chaine.

  13. #13
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut
    mais a ce moment la, si j alloue un emplacement dans mon switch a chaque fois que j'ajoute un nouvel ouvrage, je peux faire directement le strcpy direct dans ajouterEntree, c est ca ?

  14. #14
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    non car il faut que tu alloues un espace mémoire pour ton nouvelEditeur -> nom

    de plus, pense bien à libérer avec free toute la mémoire qui est allouée avec malloc quand l'espace alloué devient inutile
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  15. #15
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut
    ce que je ne comprends pas, c est que lorsque je mettais directement mes "toto" au lieu d'un pointeur, tout marchait sans avoir a allouer de la place pour les differentes variables

    meme si maintenant ca me semble aberrant, ca n'aurait pas du marcher O_O

  16. #16
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    c'est le même soucis que les pointeurs fantôme, sauf que là comme il s'agit de chaîne stockées directement dans le programme, il n'y aurait pas eu de problème apparent... (chaîne impossible à modifier, et qui ne seront jamais désallouées)
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  17. #17
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut
    ah oki, bon en tout cas merci d'avoir passé du temps à tout m'expliquer! =)

  18. #18
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut
    derniere question

    le fait d allouer de la place pour le "nouvelEditeur" qui est une structure, ca alloue pas directement de la place pour les variables/pointeurs contenus dans cette structure ?

  19. #19
    Expert confirmé
    Avatar de Swoög
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    6 045
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 6 045
    Par défaut
    non, car tu alloues la mémoire pour les pointeurs (c'est à dire pour stocker l'adresse) pas pour les données
    Rédacteur "éclectique" (XML, Cours PHP, Cours JavaScript, IRC, Web...)
    Les Règles du Forum - Mon Site Web sur DVP.com (Développement Web, PHP, (X)HTML/CSS, SQL, XML, IRC)
    je ne répondrai à aucune question technique via MP, MSN ou Skype : les Forums sont là pour ça !!! Merci de me demander avant de m'ajouter à vos contacts sinon je bloque !
    pensez à la balise [ code ] (bouton #) et au tag :resolu: (en bas)

  20. #20
    Membre confirmé
    Inscrit en
    Décembre 2005
    Messages
    105
    Détails du profil
    Informations forums :
    Inscription : Décembre 2005
    Messages : 105
    Par défaut
    Bonjour j'avais encore une question concernant le free.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Fiche *nouvelleFicheOuvrage;
                   nouvelleFicheOuvrage = (Fiche *)(malloc(sizeof(Fiche)));
                   nouvelleFicheOuvrage -> OuvragePtr = nouvelOuvrage;
                   ajouterFiche(listeOuvrage, nouvelleFicheOuvrage);
    Pourquoi lorsque je dis que OuvragePtr pointe sur le meme element que nouvelOuvrage, si je fais un free(nouvelleFicheOuvrage -> OuvragePtr), voir
    de la fiche, apparemment rien n'est libéré car la fiche est tout de même affichée?

    Ou alors est ce que free ne fait que désallouer, dans le sens ou il ne bloque plus l'espace memoire reservé à cet emplacement, mais si je ne fais aucune opération derriere, il existe toujours ? En revanche si d'autres operations surviennent, il se peut que cet emplacement soit effacé?
    Ce dont je doute car par exemple pour le cas de l'éditeur que nous avons vu plus haut, si je désalloue, il ne m affiche plus rien pour les champs concernés.

    *EDIT*bon j'ai vu dans la faq que c'était bien ma deuxieme proposition qui est correcte, désallouer n'efface pas le contenu mais alors pourquoi pour un des champs concernés, si je fais free(........... -> nom) et que j'affiche
    les informations, le champ "nom" ne contient plus rien O_O.

    Merci

Discussions similaires

  1. Problème de pointeurs..embrouillé
    Par Frenchy dans le forum C++
    Réponses: 11
    Dernier message: 10/03/2005, 17h33
  2. Problème de pointeur avec un TQuery
    Par Oluha dans le forum Bases de données
    Réponses: 3
    Dernier message: 25/01/2005, 14h57
  3. Problème de pointeur
    Par toma_lille dans le forum C++
    Réponses: 1
    Dernier message: 07/12/2004, 22h26
  4. [MFC] Problème de pointeur !!
    Par acastor dans le forum MFC
    Réponses: 7
    Dernier message: 19/03/2004, 16h50
  5. TBitmap et problèmes de pointeurs...
    Par benj63 dans le forum C++Builder
    Réponses: 8
    Dernier message: 28/07/2003, 14h39

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