Enregistrer / charger un fichier en C

Enregistrer / charger un fichier en C - C - Programmation

Marsh Posté le 29-04-2014 à 21:08:31    

Bonjour je suis bloqué dans un gros TP qui dure tout le semestre.
 
Le but du tp est de gérer une université en entrant les établissements, diplômes, matières attachées aux diplômes, étudiants attachées aux diplômes, leurs notes, les moyennes des diplômes et encore différente chose tout en utilisant les listes chaînées.
 
J'ai pratiquement tout fait mais le problème c'est que je stock tout dans des listes chaînées et donc tout se perd à la fermeture du programme. J'ai lu qu'il faut tout stocké dans un fichier texte mais tout doit être mis dans un ordre bien précis :  
 
            • Nom de l’établissement  
            • Code de l’établissement  
            • Nombre de matières  
            • Liste des matières  
                 Pour une matière :  
                       o son nom,  
                       o son code  
            • Nombre de diplômes
            • Liste des diplômes  
            Pour un diplôme :  
               o son nom,  
               o son code  
               o le nombre de matières,  
               o la liste des couples (codes de la matière, coefficient)  
               • Nombre d’étudiants  
               • Liste d’étudiants  
 
J'ai toutes ses données dans mes listes chaînées après les différentes saisies mais j'ai jamais vraiment bien compris les fichiers et je ne sais pas comment les écrire dans un fichier et de plus toutes ces données doivent être lues et transcrites dans la structure de données afin de permettre à l’utilisateur de travailler. Et il faut aussi pouvoir actualiser si on ajoute une matière ou un diplôme.
 
J'ai quand même quelque base en fichier avec fprintf et fscanf mais je sais pas si il faut créer une nouvelle fonction ou si il faut écrire à chaque fois que l'utilisateur éffectue saisie et je ne sais pas comment faire pour écrire ou lire à un endroit précis.
 
Merci d'avance pour votre aide  :)

Reply

Marsh Posté le 29-04-2014 à 21:08:31   

Reply

Marsh Posté le 30-04-2014 à 02:01:29    

Ta question est un peu vague pour quelqu'un qui manipule déjà des listes chaînées. Plus de détails / de code auraient été nécessaire pour t'aider de manière concrète.

 

Dans ton cas, l'idée est de traverser ta liste chaînée afin d'écrire les données: C'est assez simple: Tu ouvres le fichier (avec open/fopen) en écriture (par exemple fopen("db.txt", "w+" ) ouvre le fichier db.txt, le crée s'il n'existe pas et s'il existe le vide de son contenu précédent )) et tu traverses la liste chaînée en écrivant chaque donnée avec des fwrite successifs.

 

Une fois que tu as fini d'écrire ton fichier, tu refermes le fichier avec la fonction fclose.

 

Ça c'est simple. Tu peux aussi décider de générer le contenu du fichier en mémoire, puis de l'écrire avec un seul et unique fwrite. C'est potentiellement plus optimal mais je pense pas que le gain de performances soit ta préoccupation principale.

 

Ensuite il te faudra une fonction qui lit les données du fichier précédemment écrit afin de recréer des données en mémoire. Ca c'est un peu plus chiant, ça nécessite de parser le fichier que tu as créé et c'est quelque chose qui dépendra pas mal de la structure de ton fichier créé.

 

A chaque fois que tu mets à jour tes données en mémoire (rajout d'une matière/diplôme), il te suffira d'appeler ta fonction écrivant tes données en mémoire dans un fichier. Le faire à chaque modification est un peu lourd, mais encore une fois je doute que l'optimisation des entrées sorties soit ta principale préoccupation. Et ca te permettra d'éviter de perdre tes données.

 

Après je peux pas plus t'aider ... Difficile de voir ce qui te bloque vraiment dans les fichiers, quand à mon sens le concept de listes chaînées est plus dur à comprendre car il implique de la manipulation de pointeurs qui n'est pas évidente pour un débutant.


Message édité par WiiDS le 30-04-2014 à 02:01:50

---------------
"I can cry like Roger. It's just a shame I can't play like him" - Andy Murray, 2010
Reply

Marsh Posté le 30-04-2014 à 10:21:36    

Merci de ton aide j'ai un peux mieux compris, en faite je suis en fin de 2 éme année et les fichiers ont été vu en première année mais vraiment vite fait et j'avais pas compris grand chose et la on nous demande de faire sa.
 
Le problème c'est que mon code la fait 600 lignes y'a beaucoup de structure et de fonction qui fallait faire et que j'ai pas précisé ici mais je peux vous mettre mes structure si vous voulez.
 
Pour créer le fichier je pense que j'ai compris en gros je l'efface a chaque saisie et je le réécris en entier en appelant la fonction mais par contre le charger au lancement du programmes là je comprends pas. Et aussi j'ai vu qu'on peux l'écrire en binaire ou en texte mais il est précisé dans l'énoncé qu'il faut l'enregistrer dans un fichier texte donc il faut utilisé fprintf à la place de fwrite ?


Message édité par nios le 30-04-2014 à 13:28:05
Reply

Marsh Posté le 30-04-2014 à 14:39:05    

Citation :

           • Nom de l’établissement  
            • Code de l’établissement  
            • Nombre de matières  
            • Liste des matières  
                 Pour une matière :  
                       o son nom,  
                       o son code  
            • Nombre de diplômes
            • Liste des diplômes  
            Pour un diplôme :  
               o son nom,  
               o son code  
               o le nombre de matières,  
               o la liste des couples (codes de la matière, coefficient)  
               • Nombre d’étudiants  
               • Liste d’étudiants


Donc c'est simple, en supposant que chaque champ de ton fichier soit sur une ligne:
Boucle principale
Tu lis une ligne -> si tu es en fin de fichier, tu sors de la boucle principale, sinon (tu crées un élément de ta liste chainée de type établissement, tu le chaîne si ce n'est pas le premier), tu as le nom de l'établissement (et sa taille, pour un malloc si tes structures sont dynamiques) -> tu remplis ta structure pour ce champ
Tu lis une ligne -> tu as le code de l'établissement comme une chaine. Si ce code est un nombre entier, tu convertis en nombre, sinon tu appliques la méthode précédente -> tu remplis ta structure pour ce champ
Tu lis une ligne -> tu as le Nombre de matières comme une chaine. Tu convertis en nombre N et tu alloues un tableau dynamique de N pointeurs (si tes structures sont dynamiques) sur des structures de type matière ou bien tu crées une liste chaînée de N structures de type matière selon ton implémentation
Tu fais en boucle N fois
    Tu lis une ligne -> tu as le nom de la matière -> tu remplis ta structure pour ce champ
    Tu lis une ligne -> tu as le code de la matière Si ce code est un nombre entier, tu convertis en nombre... -> tu remplis ta structure pour ce champ
Fin de la boucle
Tu lis une ligne -> tu as le Nombre de diplômes comme une chaine. Tu convertis en nombre M et tu alloues un tableau dynamique de M pointeurs (si tes structures sont dynamiques) sur des structures de type diplôme ou bien tu crées une liste chaînée de M structures de type diplôme selon ton implémentation
Tu fais en boucle M fois
     Tu lis une ligne -> tu as le nom du diplôme -> tu remplis ta structure pour ce champ
      etc
Fin de la boucle
Fin de la boucle principale
 
Bref tu vois le principe. Après, à toi de moduler (par exemple, tu peux insérer des lignes vides pour aérer, et sauter les lignes vides a la lecture) et de tenir compte des erreurs (fin de fichier hors du début de la boucle principale, etc)
C'est une manière de faire, mais il y en a plein d'autres.Une manière moderne serait de sauver en XML (le XML c'est du texte (balisé, certes)) et de relire en faisant appel a une librairie parsant le XML comme Expat.
 
A+,


Message édité par gilou le 30-04-2014 à 14:59:57

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 30-04-2014 à 14:58:57    

Ah oui c'est assez simple en faite mais par contre comment on fait pour indiquer au fscanf qu'on veux passer à la ligne d'après ?
 
Par exemple je fais pour la première ligne :
            fscanf(f,"%s",nom);
Est ce que mon deuxième fscanf se fera automatique sur la deuxième ligne ?
Par exemple ici : fscanf(f,"%d",nom);

Reply

Marsh Posté le 30-04-2014 à 15:07:41    

Ben comme on n'est plus à l'ère préhistorique, tu utilises getline.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 30-04-2014 à 15:17:36    

Ah on ne m'avais jamais parler de cette fonction mais d'après ce que j'ai vu c'est du c++ non ?  
Car on doit juste le réaliser en C mais sinon comment elle s'utilise ?
 
Merci de ton aide

Reply

Marsh Posté le 30-04-2014 à 15:24:17    

C'est du C POSIX 2008, que le compilo gnu implémente.
Si ton compilo ne l'a pas, tu le rajoute à ton code, cf le lien ici: http://stackoverflow.com/questions [...] 2#12169132
Notes que si tu sais à l'avance que aucun de tes champs ne sera plus grand qu'une certaine taille tmax, tu peux utiliser directement fgets et un buffer de taille tmax+2 (chaîne max + \n + \0), ce qui simplifie les choses.
A+,


Message édité par gilou le 30-04-2014 à 15:30:25

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 30-04-2014 à 15:31:15    

Merci et j'ai une dernière question, quand on demande à l'utilisateur d'entrer un entier et qu'il entre une lettre sa fait planter mon programme.
Comment je pourrais faire pour être sur qu'il entre un entier ?
Et aussi ma fonction pour écrire dans le fichier tourne en boucle j'aimerais savoir si j'utilise bien le fprintf ,par exemple pour l'étudiant j'ai sa :
        FILE *f = fopen("log.txt", "w+" );
 
        for(i=1;i<=nbr_etu;i++){
            fprintf(f,"%s\n%s\n%d\n%d\n%d\n%d\n%s ",etu->etudiant.nom,etu->etudiant.prenom,etu->etudiant.code,etu->etudiant.date_jour,etu->etudiant.date_mois,etu->etudiant.date_annee,etu->etudiant.lieu);
            etu=etu->suivant;
        }
 
avec nbr_etu le nombre d'étudiant et etu qui est le pointeur sur le premier étudiant au départ

Reply

Marsh Posté le 30-04-2014 à 16:48:46    

1) Tu utilises la fonction de lecture blindée de mon dernier post ici: http://forum.hardware.fr/hfr/Progr [...] m#t2165223
2) tu vires le \n final s'il est présent dans le buffer (je me souviens plus si la fonction le garde, et les espaces avant ce \n le cas échéant)
3) tu vérifies que tu n'as que des chiffres dans le buffer (boucle avec isdigit)
4) tu convertis en nombre avec atoi ou atol
5) en cas d'erreur, gérer en demandant de recommencer ou d'abandonner la saisie en cours...
 
Et pour ta fonction, ça sera quelque chose dans ce genre la en effet (mais il faudra écrire la valeur nbr_etu en premier avant la boucle)
 
A+,


Message édité par gilou le 30-04-2014 à 16:50:40

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed