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 d'utilisation de structures


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 44
    Par défaut Problème d'utilisation de structures
    bonjour,

    je suis plutôt débutante en langage C et je dois créer une interface (simple, faite avec des printf et scanf) permettant entre autre à un utilisateur d'importer des contacts sur un répertoire, lu dans un fichier contact_.txt qui en contient 100. Mais aussi de faire quelques recherche, ajout, suppression etc...
    contact.txt est sous la forme :
    ==Contact==
    nom
    prénom
    ...
    ==Contact==

    dans mon main, je créer un nouveau fichier repertoire.txt qui contient juste les info des contacts "bout à bout"
    nom
    prénom
    ...

    je veux créer différentes fonctions. La première doit lire les contacts de repertoire.txt et les "stocker" dans une structure Contact (contenue dans main.h, dont le code est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    typedef struct{
        char nom[100];
        char prenom[100];
        char num[100];
        char mail[100];
        char adresse[100];
        char ville[100];
    }Contact;
    Voici mon 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
    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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "main.h"
     
     
    #define CONTACT "contacts_.txt"
    #define REPERTOIRE "repertoire.txt"
    #define RDV "rendezvous.txt"
     
    int lireContact(FILE* fichier, Contact* lecontact)
    {
        fichier = NULL;
     
        char copy[100];
     
     
        if (fichier == NULL)
        {
            fprintf(stderr,"ERROR : Can't open repertory file");
            return 0;
        }
        else
        {
            ;
            while(fgets(copy,100,fichier)!= NULL)
            {
     
                lecontact = (Contact*) malloc (sizeof(Contact));
                strcpy(lecontact->nom,copy);
                // Prénom
                fgets(copy,100,fichier);
                strcpy(lecontact->prenom,copy);
                // Num
                fgets(copy,100,fichier);
                strcpy(lecontact->num,copy);
                // Mail
                fgets(copy,100,fichier);
                strcpy(lecontact->mail,copy);
                // Adresse
                fgets(copy,100,fichier);
                strcpy(lecontact->adresse,copy);
                // Ville
                fgets(copy,100,fichier);
                strcpy(lecontact->ville,copy);
            }
            printf("valeur %s",lecontact->ville);
        }
        fclose(fichier);
        return 0;
    }
     
    // Fonction qui ajoute les contacts de contacts.txt au repertoire
    int main(void){
            // initialisation des pointeurs
            FILE *f_contact = NULL;
            FILE *f_repertoire = NULL;
     
            char temp[100];
     
            f_contact=fopen(CONTACT,"r");
            f_repertoire = fopen(REPERTOIRE,"w");
     
             if (f_contact == NULL){
                    fprintf(stderr,"ERROR : Can't open contact file");
                    return 0;
            }
            else{
                    // On génére le fichier binaire repertoire
                    // Ouverture, puis écriture
                    if((f_repertoire == NULL)){
                            fprintf(stderr,"ERROR : Can't create repertoire file");
                            fclose(f_contact);
                            return 0;
                    }
                    else{
                            int in_contact = 1;
                            char* ret;
     
                            ret = fgets(temp,100,f_contact);
                            // Tant qu'on est pas à la fin du fichier
                            while(ret != NULL)
                            {
     
                                    // On test si on dans le champ contact
                                    if(strcmp(temp,"==Contact==\r\n") == 0)
                                    {
                                            in_contact = 1;
                                            // Tant qu'on est dans un même contact
                                            while(in_contact == 1)
                                            {
                                                    in_contact = 1;
                                                    // On lit une autre ligne
                                                    ret=fgets(temp,100,f_contact);
                                                    // Si on est sur un autre contact ou qu'on est à la fin, on sort
                                                    if(strcmp(temp,"==Contact==\r\n") == 0 || ret == NULL)
                                                            in_contact = 0;
                                                    // Sinon on enregistre la ligne si elle n'est pas vide
                                                    else if (strcmp(temp,"\n") != 0)
                                                                    fputs(temp,f_repertoire);
                                            }
                                    }
                                    else // ligne superflu avant ou entre contacts
                                            ret=fgets(temp,100,f_contact);
                                    }
                            }
     
                    }
                    printf("Copy success \n");
                    fclose(f_repertoire);
                    fclose(f_contact);
     
            Contact lecontact;
            FILE* fichier;
            fichier = NULL;
            fichier = fopen(REPERTOIRE,"r");
            lireContact(fichier,&lecontact);
     
            return 0;
     
    }
    mon code semble fonctionner mais :

    Le soucis est que je ne comprends pas très bien comment gérer ma structure, comment voir si elle fonctionne, comment stocker plusieurs contacts et je suis un peu coincée pour la suite ... par exemple pour quelques recherche :/
    en effet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("valeur %s",lecontact->ville);
    m'affiche la dernière ville lue dans le fichier repertoire. Comment accéder aux autres ?
    Pouvez vous m'aider svp ?
    Merci d'avance

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    Pour commencer quelques remarques sur ton code :
    1. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      int lireContact(FILE* fichier, Contact* lecontact)
      {
          fichier = NULL;
      
          char copy[100];
      
          if (fichier == NULL)
      La première ligne rouge n'a rien à faire ici. Vu que tu mets fichier à NULL juste avant, ton test sera toujours vrai, même si tu as ouvert ton fichier avec succès.
    2. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      int lireContact(FILE* fichier, Contact* lecontact)
      {
          // ...
          if (fichier == NULL)
          {
              fprintf(stderr,"ERROR : Can't open repertory file");
              return 0;
          }
          // ...
          return 0;
      }
      Là, qu'il y ait une erreur ou non, tu renvoies 0... difficile de savoir donc si la fonction s'est bien exécutée correctement ou non.
    3. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      while(fgets(copy,100,fichier)!= NULL)
      {
          lecontact = (Contact*) malloc (sizeof(Contact));
          // ....
      }
      ici tu as une belle fuite de mémoire : allocation en boucle sans aucun free() ni stockage des adresses.
    4. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      fichier = fopen(REPERTOIRE,"r");
      lireContact(fichier,&lecontact);
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      int lireContact(FILE* fichier, Contact* lecontact)
      {
          // ...
          fclose(fichier);
      }
      J'aime moyennement ce fclose() à l'intérieur de la fonction avec le fopen() associé en dehors. Préfère mettre les deux au même niveau.
    5. Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      while(in_contact == 1)
      {
          in_contact = 1;
      Si on est entré dans le while, c'est qu'elle est déjà à 1 Cette ligne est donc inutile.
    6. Enfin sache que le pointeur int lireContact(FILE* fichier, Contact* lecontact) n'est qu'une copie de celui passé ici lireContact(fichier,&lecontact);. Donc ta ligne avec malloc() ne modifiera pas ta donnée d'origine.


    Venons-en à ce problème de stockage
    Tu souhaites stocker plusieurs Contact, et tu ne sais pas à priori combien : tu auras donc besoin d'un pointeur que tu alloueras au final au nombre contenu dans le fichier.
    À partir de là, tu as deux approches possibles :
    1. Soit effectuer une première passe en comptant les lignes ==Contact==, allouer ton pointeur
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      contacts = malloc(nbContacts * sizeof(Contact));
      puis refaire le parcours pour remplir les cases ;
    2. Soit n'en faire qu'une et utiliser realloc() au fur et à mesure.

    Dans les deux cas, il te faudra passer un pointeur sur pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    int lireContact(FILE* fichier, Contact** contacts)
        *contacts = malloc/realloc(/*...*/);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Contact *contacts;
    lireContact(fichier,&contacts);
    Pense aussi que tu auras besoin de savoir une fois la fonction lireContact() exécutée le nombre de contacts lus/alloués, le b) serait alors à considérer

    Une autre façon de stocker tes contacts serait l'utilisation d'une liste chaînée.

  3. #3
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 44
    Par défaut
    Merci beaucoup pour votre réponse très détaillé !!

    Je suis arrivée hier soir à faire fonctionner le code mais certes il n'est pas très "propre" et je vais suivre vos suggestions pour le rendre...

    J'ai effectivement ajouter une variable nbContact qui lit le nombre de contact dans le fichier de départ et je la passe en argument de la fonction lireContact.

    Voici donc mon code qui 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
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    int lireContact(FILE* fichier, Contact* lecontact, int nbContacts,Contact** save_contact)
    {
        fichier = NULL;
     
        char copy[100];
        fichier = fopen(REPERTOIRE,"r");
     
        int i=0;
     
        if (fichier == NULL)
        {
            fprintf(stderr,"ERROR : Can't open repertory file");
            return 0;
        }
        else
        {
     
            while(fgets(copy,100,fichier)!= NULL)
            {
                // Allocation de la mémoire pour chaque nouveau contact
                lecontact = (Contact*) malloc (sizeof(Contact));
                strcpy(lecontact->nom,copy);
                // Prénom
                fgets(copy,100,fichier);
                strcpy(lecontact->prenom,copy);
                // Num
                fgets(copy,100,fichier);
                strcpy(lecontact->num,copy);
                // Mail
                fgets(copy,100,fichier);
                strcpy(lecontact->mail,copy);
                // Adresse
                fgets(copy,100,fichier);
                strcpy(lecontact->adresse,copy);
                // Ville
                fgets(copy,100,fichier);
                strcpy(lecontact->ville,copy);
                // Sauvegarde contact dans un tableau de structure
                save_contact[i]=lecontact;
                i++;
     
     
            }
            free(lecontact);
        }
        printf("%s",save_contact[1]->nom);
        // fermeture du fichier
        fclose(fichier);
        return 0;
    }
    J'espère avoir libérer la mémoire où il le fallait.
    Cette fonction marche bien le printf m'affiche la bonne valeur donc je suis contente (même si certes mon code n'est pas très "propre"...)

    Je suis en train maintenant de faire des fonctions de recherches et là, c'est un peu plus complexe pour moi...

    bon si je récapitule, j'ai un tableau de pointeurs save_contact[nbContacts] dont chaque case pointe vers un élément de la structure à savoir un contact.

    Je souhaites faire des recherches du genre "afficher les informations du contact du nom de Durand" etc...

    Mon soucis est que je n'arrive pas à créer une fonction "générale" qui puisse autant rechercher en fonction du nom, du prénom, ou d'autres choses...

    Comment gérer avec ma structure de tels recherches? :/

  4. #4
    Invité
    Invité(e)
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int lireContact(FILE* fichier, Contact* lecontact, int nbContacts,Contact** save_contact)
    {
        fichier = NULL;
     
        char copy[100];
        fichier = fopen(REPERTOIRE,"r");
    Alors je vois que tu as choisi de mettre les deux dans la fonction. Tu n'as alors plus besoin de passer fichier en paramètre de même lecontact

    Citation Envoyé par melissar Voir le message
    J'espère avoir libérer la mémoire où il le fallait.
    Je suis au regret de te dire non.
    De 1), tu exécutes normalement nbContacts fois la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    lecontact = (Contact*) malloc (sizeof(Contact));
    Tu alloues donc nbContacts contacts en mémoire.
    Or le free(lecontact); que tu as placé après la boucle ne fait que libérer le dernier.
    De 2) en considérant que ton free() les ait tous libéré, que comptes-tu ressortir avec ton save_contact() ? Tu vas pointer vers des espaces mémoires qui ont été libérés, et qui peuvent donc contenir n'importe quoi.
    Ce n'est pas dans la fonction que tu doit les libérer, mais à l'extérieur une fois que tu auras fini d'utiliser ces contacts que tu as lu.

    Pour la recherche, il te suffit de simplement parcourir les contacts avec une boucle et t'arrêter à/stocker l'élément qui correspond au critère recherché.

    PS : Je te laisse corriger d'autres points déjà mentionnés dans mon premier message

  5. #5
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Avril 2012
    Messages
    44
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2012
    Messages : 44
    Par défaut
    si je comprends bien le raisonnement il faut donc qu'à la fin de mon Programme je fasse un free du tableau de pointeurs save_contact, c'est bien celà?

  6. #6
    Invité
    Invité(e)
    Par défaut
    Tu dois avoir autant de free() que de malloc() effectués, et ceci sur les mêmes adresses retournées par malloc(), et entre les deux (et seulement) l'utilisation de cette mémoire (stockage des contacts, recherche...).

  7. #7
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    il faut que pour chaque malloc, un free soit fait avec la même adresse en argument. (pour les fuites mémoire, calloc est équivalent à malloc: c'est une allocation)

    mathématiquement parlant:
    pour toute adresse différente de NULL retournée par malloc au cours de l’exécution du programme, il y a un et un seul appel de free utilisant cette adresse.

    Ceci est la version simple.
    Il faut tenir compte du fait que realloc appelle free sur l'ancienne adresse et en retourne une autre (ou ne compte pas).
    Par ailleurs, free(NULL) ne provoque jamais d'erreur, il ne se passe juste rien.

    Il faut aussi que chaque accès à une adresse se fasse sur de la mémoire effectivement allouée. (soit via un pointeur construit via une prise d'adresse d'une variable encore vivante, soit sur une adresse issue d'un malloc)

Discussions similaires

  1. Problème d'utilisation structure PROCESSENTRY 32
    Par yoshi84300 dans le forum Visual C++
    Réponses: 5
    Dernier message: 25/02/2013, 15h41
  2. Réponses: 1
    Dernier message: 29/01/2013, 14h44
  3. Problème d'utilisation de structure en C++
    Par marcix dans le forum C++
    Réponses: 1
    Dernier message: 08/12/2007, 12h47
  4. Problème d'utilisation de Mysql avec dev-c++
    Par Watchi dans le forum Dev-C++
    Réponses: 10
    Dernier message: 06/08/2004, 14h35
  5. problème d'utilisation avec turbo pascal 7.0
    Par le 27 dans le forum Turbo Pascal
    Réponses: 4
    Dernier message: 03/12/2003, 10h44

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