[C] [réglé] Récupérer le contenu d'un fichier texte ?

Récupérer le contenu d'un fichier texte ? [C] [réglé] - C - Programmation

Marsh Posté le 16-06-2005 à 13:29:36    

Bonjour, je viens vous demander un peu d'aide car là je sèche :D
Petit détail de ce que je veux faire :
J'ai un fichier nommé "test" (juste pour l'instant hein ;)) qui contient des infos que je dois analyser (une en tout cas), et des trous à remplir par l'application !
 
Le fichier se présente comme celà au début (balises de changement de ligne type unix) :

Code :
  1. 1
  2. 0.0
  3. sylver
  4. 37650432


 
J'ai choisi (mauvais choix :??:) de récupérer les informations non connues par mon appli et de reconstruire le fichier de zéro, ca m'a semblé le plus simple vu que l'appli met à jour ce fichier assez souvent !
 
j'ai fait un fichier de test pour vérifier mon analyse du fichier :

Code :
  1. #include <stdio.h>
  2. FILE *stat_tf;
  3. char *stat_file= (char*) 0;
  4. void main (void)
  5. {
  6.   int stat_state = 0;
  7.   char stat_user[80];
  8.   char stat_size[80];
  9.   stat_file = "test";
  10.   stat_tf = fopen(stat_file, "r+" );
  11.   fscanf(stat_tf, "%d%*s%*s%*s%*s%s%*s%*s%*s%*s%*s%*s%s",&stat_state, stat_user, stat_size);
  12.   printf("%d %s %d", stat_state, stat_user, stat_size);
  13. }


et voilà, mon problème c'est que quand le fichier est dans son état initial, la ligne pour lire les infos qui m'interessent est :

Code :
  1. fscanf(stat_tf, "%d%*s%s%s",&stat_state, stat_user, stat_size);


mais par la suite mon application modifie le fichier pour compléter les parties vides, et quand le fichier est completement rempli, la ligne qui lit correctement le fichier est alors :

Code :
  1. fscanf(stat_tf, "%d%*s%*s%*s%*s%s%*s%*s%*s%*s%*s%*s%s",&stat_state, stat_user, stat_size);


exemple de fichier "test" rempli :

Code :
  1. 1
  2. 0.0
  3. 1
  4. 2
  5. 33
  6. sylver
  7. 11
  8. 55
  9. 77
  10. 99
  11. 55
  12. 22
  13. 37650432


 
Le problème (ou j'ai cherché un moment) vient du fait que fscanf considère les retours chariots comme du vent et passe aux prochaines infos utiles => pleins de retours chariot sont équivalent à un espace par exemple ! Ca n'arrange pas du tout mes affaires, donc si vous aviez un piste pour que je m'en sorte, ça serait cool (par exemple un balise type %[] pour que fscanf considère les \n comme de l'info ou éventuellement un approche différente basée sur autre chose que du fscanf :sweat:)
 
Merci d'avance :jap:
 
Sylver


Message édité par _Sylver_ le 16-06-2005 à 16:48:35
Reply

Marsh Posté le 16-06-2005 à 13:29:36   

Reply

Marsh Posté le 16-06-2005 à 13:39:39    

c'est du C

Reply

Marsh Posté le 16-06-2005 à 13:41:24    

lol +1 pour taz

Reply

Marsh Posté le 16-06-2005 à 13:45:39    

Oui c'est du C pour le test, mais mon appli finale est en C++, je ne suis donc pas limité aux primitives C ...
 
Des idées ?


Message édité par _Sylver_ le 16-06-2005 à 13:46:37
Reply

Marsh Posté le 16-06-2005 à 13:48:11    

ben fais le en C++ alors avec des std::string et VERIFIE que les fonctions d'E/S n'échoue pas (si tu sors une seule fois un eof, je me casse)

Reply

Marsh Posté le 16-06-2005 à 13:53:45    

Ca a l'air tellement simple :D (je ne manipule pas souvent les chaines de caractères, c'est pour ça que je ne connais que le scanf :D), je vais chercher sur google :D, en tout cas tu me confirmes que j'aurais toutes les opérateurs pour faire ce que je souhaite ?
 
Merci en tout cas !
 
PS : pourquoi les fonctions d'IO échoueraient ?

Reply

Marsh Posté le 16-06-2005 à 15:16:05    

Je déplace dans [C] car en C++ c'est un peu lourd je trouve !
Edit : bon j'ai trouvé une méthode qui marche, à base de gros fseek des familles !
 

Code :
  1. #include <stdio.h>
  2. FILE *stat_tf;
  3. char *stat_file= (char*) 0;
  4. void main (void)
  5. {
  6.   int stat_state = 0;
  7.   char stat_user[80];
  8.   char stat_size[80];
  9.   long int offset;
  10.   int  compteur;
  11.   stat_file = "test";
  12.   stat_tf = fopen(stat_file, "r+" );
  13.   /* Get state */
  14.   fscanf(stat_tf, "%d", &stat_state);
  15.   /* Jump to owner line */
  16.   for (compteur=0;compteur<6;compteur++){
  17. while (fgetc(stat_tf) != '\n'){
  18.  offset++;
  19.  fseek (stat_tf,offset,SEEK_SET);
  20. }
  21.     offset++;
  22.     fseek (stat_tf,offset,SEEK_SET);
  23.   }
  24.   fscanf(stat_tf, "%s", stat_user);
  25.  
  26.   /* Jump to size line */
  27.   for (compteur=0;compteur<8;compteur++){
  28. while (fgetc(stat_tf) != '\n'){
  29.  offset++;
  30.  fseek (stat_tf,offset,SEEK_SET);
  31. }
  32.     offset++;
  33.     fseek (stat_tf,offset,SEEK_SET);
  34.   }
  35.   fscanf(stat_tf, "%s", stat_size);
  36.  
  37.   printf("%d %s %d", stat_state, stat_user, stat_size);
  38. }


 
C'est moche mais ça marche ! En attendant de trouver mieux, au moins je peux avancer ;)


Message édité par _Sylver_ le 16-06-2005 à 15:44:39
Reply

Marsh Posté le 16-06-2005 à 18:11:50    

et bien pris pour que ton fichier soit bien formé ... parce que là c'est n'importe quoi

Reply

Marsh Posté le 16-06-2005 à 19:22:44    

[:hide]  
 
C'est ni du C++, ni du C. C'est portnawak.
 
Je me permets de commenter :
 

Code :
  1. #include <stdio.h>
  2. /* ERK ! Pourquoi des globales ?! */
  3. FILE *stat_tf;
  4. /* re-ERK ! tu as donc *stat_file = NULL, je parie que tu  
  5.    ne lui alloueras rien en memoire, invoquant un superbe
  6.    comportement indefini. Voyons la suite */
  7. char *stat_file= (char*) 0;
  8. /* Non : main() est cense retourner un int.
  9.    donc : int main(void) */
  10. void main (void)
  11. {
  12.   int stat_state = 0;
  13.   char stat_user[80];
  14.   char stat_size[80];
  15.   long int offset;
  16.   int  compteur;
  17.   /* bingo, le beau comportement indefini que voila. Tu n'as  
  18.      absolument aucun espace memoire pour stocker ta chaine  
  19.      dans stat_file. Ca passe ou ca casse (coredump sous *nix,
  20.      violation machin error sous windows), c'est aleatoire.
  21.      Voir malloc() pour corriger ca, au plus vite */
  22.   stat_file = "test";
  23.   /* admettons que fopen() echoue, genre le fichier existe pas,
  24.      tu n'as pas les droits ou autre, stat_tf == NULL.
  25.      Il faut le tester pour s'assurer que tout fonctionne.
  26.      Et je ne vois pas l'utilité du "+" dans "r+" */
  27.   stat_tf = fopen(stat_file, "r+" );
  28.   /* Pourquoi pas, mais ce serait bien... voire necessaire, de
  29.      verifier que fscanf() a reussi a recuperer un entier. */
  30.   fscanf(stat_tf, "%d", &stat_state);
  31.   /* Ton programme n'a decidement aucune chance
  32.      face a la moindre malformation de ton fichier. */
  33.   for (compteur=0;compteur<6;compteur++){
  34.         /* Oh, le beau while (fgetc() ...)
  35.            Pourquoi ne pas plutot utiliser fgets() ? */
  36. while (fgetc(stat_tf) != '\n'){
  37.                 /* offset++ ?! Mais il n'est jamais  
  38.                    initialisé, il y a potentiellement
  39.                    n'importe quoi dedans ! */
  40.  offset++;
  41.                 /* WTF ?! fseek() ? */
  42.  fseek (stat_tf,offset,SEEK_SET);
  43. }
  44.     /* o_O */
  45.     offset++;
  46.     fseek (stat_tf,offset,SEEK_SET);
  47.   }
  48.   /* Ouh la la. Mais comment ca arrive a fonctionner tout ca  
  49.      Usine a gaz. */
  50.   fscanf(stat_tf, "%s", stat_user);
  51.  
  52.   /* Ok. En fait c'est pas une usine a gaz, c'est Tchernobyl */
  53.   for (compteur=0;compteur<8;compteur++){
  54. while (fgetc(stat_tf) != '\n'){
  55.  offset++;
  56.  fseek (stat_tf,offset,SEEK_SET);
  57. }
  58.     offset++;
  59.     fseek (stat_tf,offset,SEEK_SET);
  60.   }
  61.   fscanf(stat_tf, "%s", stat_size);
  62.  
  63.   printf("%d %s %d", stat_state, stat_user, stat_size);
  64. }


 

Citation :


C'est moche mais ça marche ! En attendant de trouver mieux, au moins je peux avancer ;)


 
C'est pire que ça.
Avancer sur une telle base, c'est courir à la catastrophe. Enfin "courir à la catastrophe", disons plutôt que tu viens de t'asperger d'essence, habillé par un pagne en paille, en train de tourner tes saucisses sur le barbecue, et que non content de la situation, tu décides d'allumer une clope en prime.
 
Sérieusement, commence par une base solide et bien plus saine que cela, parce que là c'est ignoble.
Vu ton fichier, je lirais tout bêtement le fichier ligne à ligne, en stockant au passage toutes les lignes non vides, pourquoi pas dans une liste chaînée.
Je me débrouillerais ensuite pour tester l'intégrité des données lues.
Une fois ça fait, le plus dur est passé. Il suffit de compléter la liste chaînée, et de la stocker dans un nouveau fichier.


Message édité par Elmoricq le 16-06-2005 à 19:30:15
Reply

Marsh Posté le 16-06-2005 à 19:55:44    

je ne suis pas d'accord pour
stat_file = "test";
 
c'est moche oui, mais le comportement n'est pas indefinis, tu affecte au pointeur l'adresse d'un tableau constant

Reply

Marsh Posté le 16-06-2005 à 19:55:44   

Reply

Marsh Posté le 17-06-2005 à 00:14:52    

- Oui oui pour le stat_file = "test", pas de soucis de mémoire, on mets juste à jour le pointeur vers une zone prédéfinie par le compilo !
Mais bon c'est pas fait comme ça dans le vrai soft (passage du nom par parametre, là c'est un soft de test !
- J'avais bien oublié le offset = 0 au début (pas vu car sous windows c'était mis à 0 sans init) !
- le r+, c'est parceque la suite de mon soft réécrit les infos, mais bon c'est pas mis dans la partie de test en effet :)
- pour fgets(), je ne connaissais pas, je vais regarder :jap:
- Et en effet, fichier mal formaté = cata :D
 
Merci pour ton analyse :jap:
 
J'ai fait quelques simplifications/protections :D

Code :
  1. #include <stdio.h>
  2. FILE *stat_tf;
  3. char *stat_file= (char*) 0;
  4. void main (void)
  5. {
  6.   int stat_state = 0;
  7.   char stat_user[80];
  8.   char stat_size[80];
  9.   char read_char;
  10.   int  i;
  11.   stat_file = "test";
  12.   stat_tf = fopen(stat_file, "r+" );
  13.       /* Get state */
  14.       fscanf(stat_tf, "%d", &stat_state);
  15.       /* Jump to owner line */
  16.   for (i=0;i<5;i++){
  17.    while ((((read_char=fgetc(stat_tf))) != '\n')&&(read_char != EOF));
  18.   }
  19.   fscanf(stat_tf, "%s", stat_user);
  20.   /* Jump to size line */
  21.    for (i=0;i<7;i++){
  22.    while ((((read_char=fgetc(stat_tf))) != '\n')&&(read_char != EOF));
  23.   }
  24.   fscanf(stat_tf, "%s", stat_size);
  25.   printf("%d %s %s", stat_state, stat_user, stat_size);
  26. }


Message édité par _Sylver_ le 17-06-2005 à 10:01:01
Reply

Marsh Posté le 18-06-2005 à 09:13:55    

Je rappelle que Taz a écrit

Citation :

(si tu sors une seule fois un eof, je me casse)


 :whistle:  
 
==> fgets...
 
Tout cela est bien moche, en effet.


Message édité par el muchacho le 18-06-2005 à 09:19:25
Reply

Marsh Posté le 18-06-2005 à 13:54:08    

C'est ça, le code qui va se retrouver dans ton appli ? Et tu dis dans le titre du topic que ton pb est réglé ?? :heink:

Reply

Marsh Posté le 20-06-2005 à 09:42:23    

En effet le code est pourri, mais pour l'instant, comme il fonctionne et qu'il est protégé, je me concentre sur d'autres problèmes !
Je pense que la solution que m'a donné Elmoricq (merci beaucoup Elmoricq au fait ;)) est la plus propre (lire toutes les lignes et les stocker soit dans une liste chainée, soit dans une structure), je réécrirai le code de cette façon quand le reste fonctionnera !

Reply

Sujets relatifs:

Leave a Replay

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