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 :

Modifier les champs d'une structure dans un fichier binaire


Sujet :

C

  1. #1
    Candidat au Club
    Homme Profil pro
    Etudiant Ingénieur
    Inscrit en
    Novembre 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Territoire de Belfort (Franche Comté)

    Informations professionnelles :
    Activité : Etudiant Ingénieur

    Informations forums :
    Inscription : Novembre 2018
    Messages : 4
    Points : 3
    Points
    3
    Par défaut Modifier les champs d'une structure dans un fichier binaire
    Bonjour au sein d'un projet scolaire j'ai été amené à gérer une bibliothèque fictive (ajout de livres, emprunts, etc)
    J'ai réussi à modifier les infos de ma structure en faisant saisir la nouvelle valeur des chaines de caractères mais là en l’occurrence on doit remplir l.emprunteur en fonction de l'utilisateur connecté, l.date_emprunt avec le numéro du jour actuel
    J'ai pas d'erreur dans mon code mais l'affectation ne se fait pas au sein de la structure... C'est l'une des premières fois que je j'utilise des structures donc j'ai peut-être raté quelque chose d'important sur leur utilisation auquel cas je serais ravi d'en savoir plus !
    Structure livre utilisée :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    typedef struct livre livre;
    struct livre
    {
        char id[18];
        char nom[100];
        char editeur[30];
        char auteur[30];
        int quantite;
        char *cat;
        int date_emprunt;
        int date_lim;
        char emprunteur[30];
    };
    livre l;
    Recherche de l'ID entré dans le fichier livres préalablement ouvert :
    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
    while(fread(&l,sizeof(l),1,livres)==1) //livres est le fichier qui contient les livres ^^
            {
                if(strcmp(l.id,(d))==0) //ici d est la chaine qui vient d'etre entrée (on a vérifié que la syntaxe d'un code isbn était respectée
                {
                    if(l.quantite>0)
                    {
                        printf("\n\nLe livre est disponible !\n");
                        printf("ID :%s\n",l.id);
                        printf("Categorie :%s\n",l.cat);
                        printf("Nom :%s\n",l.nom);
                        printf("Auteur :%s\n",l.auteur);
                        printf("Editeur :%s\n",l.editeur);
                        printf("Quantite :%d\n",l.quantite);
                        printf("Date de l'emprunt : %i\n",l.date_emprunt); // je n'arrive pas à modifier ce paramètre dans la structure
                        printf("Date de retour du livre : %i\n",l.date_lim); //je n'arrive pas à modifier ce paramètre dans la structure
                        printf("Emprunteur : %s\n",l.emprunteur); //je n'arrive pas à modifier ce paramètre dans la structure
                        printf("Voulez-vous l'emprunter ? (O/N) : ");
                        emprunt(utilisateur,d); //on envoie l'utilisateur connecté et la chaine à rechercher
                    }
                }
            }
    emprunt.c :
    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 emprunt (char utilisateur[], char d[])
     
    {
        switch (getch())
        {
            case 'o':
                    {
                        strcpy(l.emprunteur,utilisateur);
                        l.date_emprunt=temps_syst();
                        l.date_lim=15;
                        l.quantite=0;
                        printf("\nLe livre a bien ete emprunte, vous devrez l'avoir rendu d'ici 15 jours.\n");
                    }
            break;
    [...]
    }
    Je me suis dit que le fait d'appeler une nouvelle fonction (emprunt.c) pendant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while(fread(&l,sizeof(l),1,livres)==1)
    devait "stopper" la lecture et par conséquent modifier les champs d'une autre structure que celle recherchée. Mais ajouter un nouveau while fread + strcmp dans emprunt.c ne solutionne rien du tout pour autant...

    Voilà j'espère avoir été clair, bonne journée !

    Clément

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Wazzabeee Voir le message
    J'ai pas d'erreur dans mon code mais l'affectation ne se fait pas au sein de la structure... C'est l'une des premières fois que je j'utilise des structures donc j'ai peut-être raté quelque chose d'important sur leur utilisation auquel cas je serais ravi d'en savoir plus !

    emprunt.c :
    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
    void emprunt (char utilisateur[], char d[])
    {
        switch (getch())
        {
            case 'o':
                    {
                        strcpy(l.emprunteur,utilisateur);
                        l.date_emprunt=temps_syst();
                        l.date_lim=15;
                        l.quantite=0;
                        printf("\nLe livre a bien ete emprunte, vous devrez l'avoir rendu d'ici 15 jours.\n");
                    }
            break;
    [...]
    }
    Alors l'affectation est bonne (pas besoin d'accolades dans un case) mais d'après ce que je vois, tu remplis une variable "l" qui est locale à la fonction. Donc quand la fonction se termine, la variable est perdue. Il n'y a aucun lien entre le "l" de "emprunt.c" et le "l" que tu utilises ailleurs pour lire le fichier et afficher son contenu.

    Citation Envoyé par Wazzabeee Voir le message
    donc j'ai peut-être raté quelque chose d'important sur leur utilisation
    Je pense plutôt que tu as raté quelque chose d'important sur "comment faire remplir par une fonction une variable qui lui est extérieure" et ça c'est plus grave car c'est la base du C.

    Mais une chose m'interpelle. Je ne vois pas de déclaration de "l" dans la fonction "emprunt()". Aurais-tu commis la monumentale erreur d'utiliser des variables globales ? Si c'est le cas, quasiment tout est à jeter.

    Citation Envoyé par Wazzabeee Voir le message
    Je me suis dit que le fait d'appeler une nouvelle fonction (emprunt.c) pendant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while(fread(&l,sizeof(l),1,livres)==1)
    devait "stopper" la lecture et par conséquent modifier les champs d'une autre structure que celle recherchée.
    C'est exact. La lecture est stoppée durant le temps que la fonction "emprunt()" s'exécute. Ensuite elle repart et écrase la variable "l"...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Candidat au Club
    Homme Profil pro
    Etudiant Ingénieur
    Inscrit en
    Novembre 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Territoire de Belfort (Franche Comté)

    Informations professionnelles :
    Activité : Etudiant Ingénieur

    Informations forums :
    Inscription : Novembre 2018
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Alors l'affectation est bonne (pas besoin d'accolades dans un case) mais d'après ce que je vois, tu remplis une variable "l" qui est locale à la fonction. Donc quand la fonction se termine, la variable est perdue. Il n'y a aucun lien entre le "l" de "emprunt.c" et le "l" que tu utilises ailleurs pour lire le fichier et afficher son contenu.
    Merci pour les accolades j'ai pris l'habitude de les mettre en pensant qu'elles étaient obligatoires... Ensuite, je comprends ce que tu veux dire en effet je n'y avais pas pensé, il faudrait donc plutôt que je pointe l'adresse de "l" pour les champs que je veux remplir ?

    Je pense plutôt que tu as raté quelque chose d'important sur "comment faire remplir par une fonction une variable qui lui est extérieure" et ça c'est plus grave car c'est la base du C.

    Mais une chose m'interpelle. Je ne vois pas de déclaration de "l" dans la fonction "emprunt()". Aurais-tu commis la monumentale erreur d'utiliser des variables globales ? Si c'est le cas, quasiment tout est à jeter.
    Ma structure est déclarée dans main.h qui lui même est inclus dans quelques unes de mes fonctions dont emprunt.c.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #include <stdio.h>
    #include <stdlib.h>
    #include "main.h"
    #include "isbn.h"
    #include "temps_syst.h"
    C'est exact. La lecture est stoppée durant le temps que la fonction "emprunt()" s'exécute. Ensuite elle repart et écrase la variable "l"...
    Donc il n'est pas possible de remplir ma structure et plus précisément les champs "int date_emprunt; int date_lim; char emprunteur[30];" pour un id donné dans une fonction annexe sans lancer une nouvelle recherche complète dans le fichier depuis cette nouvelle fonction ?

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Wazzabeee Voir le message
    Merci pour les accolades j'ai pris l'habitude de les mettre en pensant qu'elles étaient obligatoires... Ensuite, je comprends ce que tu veux dire en effet je n'y avais pas pensé, il faudrait donc plutôt que je pointe l'adresse de "l" pour les champs que je veux remplir ?
    Si "l" vient de l'extérieur, oui. En dehors des globales, on ne peut remplir une variable venue du dehors qu'en passant par son adresse. Et ça vaut aussi pour les variables de type structure.

    Citation Envoyé par Wazzabeee Voir le message
    Ma structure est déclarée dans main.h qui lui même est inclus dans quelques unes de mes fonctions dont emprunt.c.
    Je ne parlais pas de la structure mais de la variable "l". Mais bon, si ce n'est pas une globale c'est ok.

    Citation Envoyé par Wazzabeee Voir le message
    Donc il n'est pas possible de remplir ma structure et plus précisément les champs "int date_emprunt; int date_lim; char emprunteur[30];" pour un id donné dans une fonction annexe sans lancer une nouvelle recherche complète dans le fichier depuis cette nouvelle fonction ?
    Je ne comprends pas la phrase "il n'est pas possible de remplir sans lancer une nouvelle recherche". Surtout que tu peux faire tout ce que tu veux avec ton "l". Mais si ensuite tu l'écrases via un fread() ben tout ce que tu auras fait sera... écrasé.

    Perso je pense qu'il faudrait mettre la recherche dans une fonction à part. Comme ça tu n'aurais pas de collision avec le "l" que tu veux remplir et le "l" servant à stocker l'info en cours de lecture pendant la recherche. Et peut-être même que tu devrais tout charger ton fichier en mémoire. Dans un tableau de structures. Comme ça, tu pourrais ensuite modifier à loisir l[0], l[1] ou l[18] et garder ces modifs puisque tout serait en RAM...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  5. #5
    Candidat au Club
    Homme Profil pro
    Etudiant Ingénieur
    Inscrit en
    Novembre 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Territoire de Belfort (Franche Comté)

    Informations professionnelles :
    Activité : Etudiant Ingénieur

    Informations forums :
    Inscription : Novembre 2018
    Messages : 4
    Points : 3
    Points
    3
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Perso je pense qu'il faudrait mettre la recherche dans une fonction à part. Comme ça tu n'aurais pas de collision avec le "l" que tu veux remplir et le "l" servant à stocker l'info en cours de lecture pendant la recherche. Et peut-être même que tu devrais tout charger ton fichier en mémoire. Dans un tableau de structures. Comme ça, tu pourrais ensuite modifier à loisir l[0], l[1] ou l[18] et garder ces modifs puisque tout serait en RAM...
    J'espère que tu ne m'en voudras pas mais je note ça pour dans deux semaines... Ca fait très peu de temps que j'ai commencé le langage C et la programmation en général je me suis déjà lancé dans les structures et les fichiers que l'on n'a pas vu en cours mais charger un fichier dans la mémoire RAM avec un tableau de structures me semble un peu trop complexe pour le moment. Surtout que je ne suis pas le seul sur ce projet et utiliser ton idée m'obligerait, dans un souci de cohérence, à modifier toutes les autres fois où l'on modifie l[x].
    Donc à moins que tu aies un exemple simple sous la main à me proposer pour que je vois le truc, saurais-tu m'expliciter clairement comment je peux modifier mon "l" pendant cette recherche ?
    Citation Envoyé par Sve@r Voir le message
    Je ne comprends pas la phrase "il n'est pas possible de remplir sans lancer une nouvelle recherche". Surtout que tu peux faire tout ce que tu veux avec ton "l". Mais si ensuite tu l'écrases via un fread() ben tout ce que tu auras fait sera... écrasé.
    J'ai justement du mal à saisir comment je peux tout faire avec "l" tu voudrais que je fasse une fonction recherche au sein de laquelle je cherche l'id rentré ? Mais ça je le fais déjà dans ma fonction je ne vois vraiment pas comment ça me permet de modifier "int date_emprunt; int date_lim; char emprunteur[30];" pour l'ID que je recherche.
    Je vois vraiment pas comment modifier ce que je veux sans tout écraser avec un autre fread justement....

  6. #6
    Membre actif
    Homme Profil pro
    Développeur
    Inscrit en
    Août 2011
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur

    Informations forums :
    Inscription : Août 2011
    Messages : 71
    Points : 214
    Points
    214
    Par défaut
    Pour ajouter une remarque,
    Je note qu'il y a un point de vigilance sur le champ cat de ta structure car il s'agit d'un pointeur char* ça risque de ne pas lire/écrire exactement ce que tu veux
    pourquoi ne pas avoir utilisé un tableau statique comme pour tes autres champs ? Tu as peut être un problème a ce niveau la ce qui expliquerai que tu n'arrives pas à lire tout les champs de ta structure après celui-ci ?

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Wazzabeee Voir le message
    J'espère que tu ne m'en voudras pas mais je note ça pour dans deux semaines... Ca fait très peu de temps que j'ai commencé le langage C et la programmation en général je me suis déjà lancé dans les structures et les fichiers que l'on n'a pas vu en cours mais charger un fichier dans la mémoire RAM avec un tableau de structures me semble un peu trop complexe pour le moment. Surtout que je ne suis pas le seul sur ce projet et utiliser ton idée m'obligerait, dans un souci de cohérence, à modifier toutes les autres fois où l'on modifie l[x].
    Ca roule. De toute façon charger tout un fichier en RAM n'est pas forcément tout le temps une bonne idée (ça dépend surtout de la taille du fichier). Ca a des avantages (pouvoir modifier facilement n'importe quelle ligne) mais l'inconvénient de consommer de la RAM.

    Citation Envoyé par Wazzabeee Voir le message
    J'ai justement du mal à saisir comment je peux tout faire avec "l" tu voudrais que je fasse une fonction recherche au sein de laquelle je cherche l'id rentré ? Mais ça je le fais déjà dans ma fonction je ne vois vraiment pas comment ça me permet de modifier "int date_emprunt; int date_lim; char emprunteur[30];" pour l'ID que je recherche.
    Je vois vraiment pas comment modifier ce que je veux sans tout écraser avec un autre fread justement....
    Ben j'avais pensé que si la fonction de recherche était à part, fatalement elle utiliserait un "l" local qui n'entrerait pas en collision avec le "l" que tu utilises pour stocker tes modifications. Et ça s'adapterait bien avec la logique générale d'un code qui veut des fonctions les plus minimalistes possibles permettant ainsi de les associer dans tous les sens (comme des Legos).

    Déjà ton exemple est assez incomplet. Donc je ne peux que deviner ce qui se passe. Mais il me semble que tu cherches une info dans le fichier, que tu stockes cette info dans "l" puis tu modifies certaines partie (sensées êtres changeantes) de "l". Jusque là ok.
    Mais ensuite que se passe-t-il ? Il se passe que tu recherches une autre info dans le fichier et que la nouvelle recherche va écraser ce "l". Donc ta modif est perdue effectivement. Malheureusement c'est toi qui a codé ce comportement. Tu dois bien te rendre compte que si tu écris (par exemple) int v; scanf("%d", &v); v=500; tu perds le "v" saisi. C'est exactement ce qui se passe (en plus grand) dans ton code.

    Donc une fois que "l" a été modifié, que veux-tu que ton programme fasse avant de faire une autre recherche ? Parce que ça tu ne l'as jamais dit...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    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 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par pjlan Voir le message
    Pour ajouter une remarque,
    Je note qu'il y a un point de vigilance sur le champ cat de ta structure car il s'agit d'un pointeur char* ça risque de ne pas lire/écrire exactement ce que tu veux
    pourquoi ne pas avoir utilisé un tableau statique comme pour tes autres champs ? Tu as peut être un problème a ce niveau la ce qui expliquerai que tu n'arrives pas à lire tout les champs de ta structure après celui-ci ?
    Pour ajouter là-dessus, d'une manière générale ce n'est pas une bonne idée de faire directement des fread/fwrite de structures, cela n'étant pas portable (problèmes d'alignements/bourrage, et les façons de spécifier cela ne sont pas normalisées, donc elles varient d'un compilateur à l'autre; puis viennent les problèmes de boutisme...).

    Le mieux est de faire des fonctions dédiées pour lire/écrire champ par champ, et pas nécessairement vers un fichier.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Ajout d'une structure dans un fichier binaire
    Par PolkovnikMedved dans le forum C
    Réponses: 1
    Dernier message: 18/09/2017, 05h03
  2. [find] recherche dans les champs d'une structure
    Par ImagingAllthe dans le forum MATLAB
    Réponses: 7
    Dernier message: 20/06/2013, 22h57
  3. Réponses: 2
    Dernier message: 29/08/2012, 16h59
  4. Réponses: 9
    Dernier message: 04/06/2007, 21h44
  5. [EXCEL]Modifier les marges d'une page dans Excel
    Par ms91fr dans le forum Composants VCL
    Réponses: 4
    Dernier message: 06/01/2004, 15h26

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