Parser un fichier simple en C++

Parser un fichier simple en C++ - C++ - Programmation

Marsh Posté le 07-07-2007 à 00:16:29    

Bonjour à tous!
 
Je voulais savoir s'il existait un moyen simple de parser un fichier en C++ avec les stream? Je m'explique :
au début j'avais fait un code sous VC en C qui utilisait très simplement la fonction fscanf pour parser mon fichier. Ca marchait très bien en debug, mais en release ça ne marche plus du tout. Je voulais donc passer aux classes en c++, et utiliser (ifstream & cie) mais je n'ai rien trouvé d'aussi simple que:
fscanf(file,"%lf[ \t]%lf",double1,double2);
 
Mon fichier à parser est constitué de la façon suivante :
<un double><espace(s) ou tabulation(s)><un double>
<un double><espace(s) ou tabulation(s)><un double>
etc...
 
Quelqu'un aurait-il une solution?
 
Merci d'avance!


---------------
**** |\/|¤¤] [ F®££t ****
Reply

Marsh Posté le 07-07-2007 à 00:16:29   

Reply

Marsh Posté le 07-07-2007 à 08:50:41    

Code :
  1. double d;
  2. mon_stream >> d >> std::ws >> d ;
  3. mon_stream >> d >> std::ws >> d ;
  4. mon_stream >> d >> std::ws >> d ;


 
Peut etre ?

Reply

Marsh Posté le 08-07-2007 à 23:09:36    

Ou alors, tu devrais pouvoir passer par std::copy comme ça par exemple:

Code :
  1. vector mesDoubles;
  2. copy(istream_iterator<double>(mon_stream), istream_iterator<double>(), back_inserter(mesDoubles));

Reply

Marsh Posté le 09-07-2007 à 00:12:46    

Ace17 a écrit :

Code :
  1. double d;
  2. mon_stream >> d >> std::ws >> d ;
  3. mon_stream >> d >> std::ws >> d ;
  4. mon_stream >> d >> std::ws >> d ;


 
Peut etre ?


Merci pour ta reponse :)
Alors soit je comprend pas le code, soit ca marche pas... J'ai essaye de faire un truc du genre :

Code :
  1. ifstream MonFichier;
  2. MonFichier.open(nom_du_fichier);
  3. MonFichier >> d1 >> std::ws >> d2; // 1er essai
  4. MonFichier.get() >> d1 >> std::ws >> d2; // 2eme essai
  5. MonFichier.getline() >> d1 >> std::ws >> d2; // 3eme essai...


et le tout dans une boucle pour recuperer chaque double et chaque ligne...

Reply

Marsh Posté le 09-07-2007 à 00:13:41    

IrmatDen a écrit :

Ou alors, tu devrais pouvoir passer par std::copy comme ça par exemple:

Code :
  1. vector mesDoubles;
  2. copy(istream_iterator<double>(mon_stream), istream_iterator<double>(), back_inserter(mesDoubles));



Oula c'est un peu technique pour moi, tu pourrais detailler s'il te plait?
Merci pour ta reponse
++

Reply

Marsh Posté le 09-07-2007 à 00:29:05    

Moolfreet a écrit :

Oula c'est un peu technique pour moi, tu pourrais detailler s'il te plait?
Merci pour ta reponse
++


Disons que tu vas stocker toutes les valeurs dans un conteneur, le vector n'étant qu'un exemple typique. Ensuite, tu as ton instance de ifstream (mon_stream), qui dérive d'istream. On se sert de copy pour copier (qui l'eut cru) tout les doubles contenus dans mon_stream dans le conteneur choisi en premier.
Les 2 helpers utilisés sont:
> istream_iterator qui te permet d'utiliser un flux par le biais d'un itérateur, et par extension d'utiliser les algos de la stl
> back_inserter qui instancie un itérateur d'"additions" d'objets pour tout conteneur offrant la possibilité d'ajouter un objet à la fin du conteneur (par le biais de push_back() par exemple).
 
Ensuite, il te suffit d'itérer sur ton conteneur pour faire ce que tu veux de ces valeurs.
 
Pour plus de détails sur chaque notion, je t'invite à consulter le site de sgi qui offre de bonnes explications illustrées par des exemples.

Reply

Marsh Posté le 09-07-2007 à 01:04:45    

IrmatDen a écrit :

Disons que tu vas stocker toutes les valeurs dans un conteneur, le vector n'étant qu'un exemple typique. Ensuite, tu as ton instance de ifstream (mon_stream), qui dérive d'istream. On se sert de copy pour copier (qui l'eut cru) tout les doubles contenus dans mon_stream dans le conteneur choisi en premier.
Les 2 helpers utilisés sont:
> istream_iterator qui te permet d'utiliser un flux par le biais d'un itérateur, et par extension d'utiliser les algos de la stl
> back_inserter qui instancie un itérateur d'"additions" d'objets pour tout conteneur offrant la possibilité d'ajouter un objet à la fin du conteneur (par le biais de push_back() par exemple).
 
Ensuite, il te suffit d'itérer sur ton conteneur pour faire ce que tu veux de ces valeurs.
 
Pour plus de détails sur chaque notion, je t'invite à consulter le site de sgi qui offre de bonnes explications illustrées par des exemples.


 
Merci bcp pour ta réponse, je vais essayer de voir ça :)
Sinon, par curiosité, tu ne saurais pas pourquoi fscanf ne marche pas sous VC6 en mode release?
++

Reply

Marsh Posté le 09-07-2007 à 01:14:15    

Euh, pas vraiment; mais je doute que ce soit fscanf qui ne marche pas, il faudrait voir comment tu as écrit cette ligne, ainsi que les types des paramètres concernés...

Reply

Marsh Posté le 09-07-2007 à 01:23:28    

IrmatDen a écrit :

Euh, pas vraiment; mais je doute que ce soit fscanf qui ne marche pas, il faudrait voir comment tu as écrit cette ligne, ainsi que les types des paramètres concernés...


Code :
  1. int iNbRecords(char * sFileName)
  2. {
  3. FILE * file;
  4. double x,y;
  5. int i = 0;
  6. file = fopen(sFileName, "r" );
  7. if (!file) {
  8.  // ...
  9.  return -1;
  10. }
  11.    
  12. /* %[a-zA-Z] => Indique que l'on lit uniquement les lettres de a à z, en majuscules ou non */
  13. /* %d        => indique que l'on lit un entier, que l'on place dans le second argument     */
  14. /* %*[ ]     => L'étoile (*) située après le pourcent indique que les caractères lus       */
  15. /*              (ici des espaces) ne sont pas placé dans l'argument correspondant          */
  16. /* %lf       => on lit un long float que l'on place dans le dernier argument               */
  17. while (!feof(file) && fscanf(file, "%lf%*[ \t]%lf\n" , &x, &y))
  18.  i++;
  19. fclose(file);
  20. return i;
  21. }


 
Voila l'une des fonctions que j'ai écrite pour calculer le nombre de lignes au format <double><esp/tab><double>, pour compter le nombre de points en fait (ce sont des coordonnées).
En isolant chaque partie du programme, c'est bien l'appel à fscanf qui provoque une erreur (access violation)...
++

Reply

Marsh Posté le 09-07-2007 à 01:30:36    

Là, je ne vois pas, désolé :/ (en plus je ne connaissais pas ces notations %*[...] :))

Reply

Marsh Posté le 09-07-2007 à 01:30:36   

Reply

Marsh Posté le 09-07-2007 à 01:34:23    

IrmatDen a écrit :

Là, je ne vois pas, désolé :/ (en plus je ne connaissais pas ces notations %*[...] :))


Arf pas grave, en tout cas merci beaucoup pour ton aide!
++

Reply

Marsh Posté le 09-07-2007 à 08:16:29    

J'avais pas vu l'histoire de debug et release...
Ca m'etonnerait beaucoup que ce soit fscanf, la cause de ton probleme. A mon avis t'as un probleme ailleurs, c'est meme a peu pres certain.
 
Ce que je te conseille de faire : tu vas dans les options de ton projet pour le mode release et tu actives la debug info. Ensuite tu lances le debug et tu vois la ou ca plante.

Reply

Marsh Posté le 09-07-2007 à 15:33:29    

Ace17 a écrit :

J'avais pas vu l'histoire de debug et release...
Ca m'etonnerait beaucoup que ce soit fscanf, la cause de ton probleme. A mon avis t'as un probleme ailleurs, c'est meme a peu pres certain.
 
Ce que je te conseille de faire : tu vas dans les options de ton projet pour le mode release et tu actives la debug info. Ensuite tu lances le debug et tu vois la ou ca plante.


J'ai essayé d'activer le debug info, mais je n'arrive pas à trouver plus précisément là où ça plante, car c'est juste avant l'appel à fscanf, mais c'est tout en assembleur...
 
Sinon j'ai créé un projet rapidement sous VC, "Hello Word", dans lequel j'ai remplaçé l'appel à la dialogbox dans le menu par une fonction test() dont voici le code :

Code :
  1. void test(void)
  2. {
  3.           FILE * file;
  4.           double x = 0.0;
  5.           double y = 0.0;
  6.           file = fopen("c:\\test.txt", "r" );
  7.           if (file == NULL)
  8.               return;
  9.           MessageBox(NULL,"Avant le fscanf","Info",MB_OK);
  10.           fscanf(file, "%lf%*[ \t]%lf\n" , &x, &y))
  11.           MessageBox(NULL,"Apres le fscanf","Info",MB_OK);
  12.           fclose(file);
  13.           return;
  14. }


 
En mode debug, tout se passe bien, les deux box s'affichent. En release, la première s'affiche, puis une jolie boite de dialogue "Hello.exe a rencontré une erreur blabla... signalez ce problème à microsoft...". Lorsque je lance avec "Start Debug->Go" (F5), après avoir activé comme tu m'as dit la debug info, il me dit qu'il y a une violation d'accès et me balance sur le code assembleur où ça plante...
 
Merci pour ton aide
++

Reply

Marsh Posté le 09-07-2007 à 16:00:31    

Je ne vois pas de raisons d'avoir fscanf qui foire ici et je ne reproduis pas le probleme chez moi (mais sous Linux).  Tu peux donner un programme console complet et le contenu de ton fichier de test?
 
(Si ton fichier contient autre chose, et que tu boucles avec une lecture comme celle-ci, tu risques d'avoir une boucle infinie).

Reply

Marsh Posté le 09-07-2007 à 16:04:08    

mais allez vous pendre avec vos scanf bordel !

Reply

Marsh Posté le 09-07-2007 à 16:25:31    

Un Programmeur a écrit :

Je ne vois pas de raisons d'avoir fscanf qui foire ici et je ne reproduis pas le probleme chez moi (mais sous Linux).  Tu peux donner un programme console complet et le contenu de ton fichier de test?
 
(Si ton fichier contient autre chose, et que tu boucles avec une lecture comme celle-ci, tu risques d'avoir une boucle infinie).


Voila un programme en mode console qui pose le même problème :

Code :
  1. #include <stdio.h>
  2. int main(int argc, char* argv[])
  3. {
  4.        FILE * file;
  5.        double x=0.0;
  6.        double y=0.0;
  7.        file = fopen("c:\\essai.txt","r" );
  8.        if(file == NULL)
  9.               return -1;
  10.        printf("Avant fscanf" );
  11.        fscanf(file,"%lf%*[ \t]%lf\n",&x,&y);
  12.        printf("Apres fscanf" );
  13.        printf("Valeurs lues : %lf,%lf",x,y);
  14.        return 0;
  15. }


 
Dans le fichier essai.txt il y a:
1  2
2  3
3  4
4  5
5  1
En mode débug, ça marche normalement, en mode release ça plante sur le fscanf...


Message édité par Moolfreet le 09-07-2007 à 16:28:38
Reply

Marsh Posté le 09-07-2007 à 16:35:19    

IrmatDen a écrit :

Ou alors, tu devrais pouvoir passer par std::copy comme ça par exemple:

Code :
  1. vector mesDoubles;
  2. copy(istream_iterator<double>(mon_stream), istream_iterator<double>(), back_inserter(mesDoubles));



Décidément le mode release n'est pas mon ami!!!
J'ai essayé avec ta solution, voici mon code :
 

Code :
  1. vector<double> vecDoubles;
  2. ifstream fInFile("C:\\essai.txt" );
  3. int i=0;
  4. copy(istream_iterator<double>(fInFile), istream_iterator<double>(), back_inserter(vecDoubles));
  5. i = vecDoubles.size();


Le fichier contient :
1  2
2  3
3  4
4  5
5  1  
Et en mode débug pas de problème, i vaut 10 à la fin. En mode release... i vaut 0 à la fin :'(

Reply

Marsh Posté le 09-07-2007 à 16:50:51    

Ca s'execute sans probleme ici, que ce soit en debug ou en optimise.
 

Reply

Marsh Posté le 09-07-2007 à 16:53:57    

Un Programmeur a écrit :

Ca s'execute sans probleme ici, que ce soit en debug ou en optimise.


Sous nux je veux bien le croire, j'ai essayé avec le compilo de DevCpp, pas de problème non plus, mais j'aimerais savoir ce qui pose problème avec le compilo de VC6...

Reply

Marsh Posté le 09-07-2007 à 17:16:55    

il est foireux :P

Reply

Marsh Posté le 09-07-2007 à 17:19:12    

lol

Reply

Marsh Posté le 09-07-2007 à 17:20:39    

Sinon, IrmatDen, tu vois ce qui pose problème dans mon code avec les stream?

Reply

Marsh Posté le 09-07-2007 à 17:26:10    

A mon avis il n'y a rien de problematique dans l'autre code non plus.  Le probleme doit venir d'une difference de l'environnement entre debug/optimise, mais je n'y connais rien sous Windows.

Reply

Marsh Posté le 09-07-2007 à 17:28:35    

Snif... y'a personne dans le coin (coin) qui aurait une idée?

Reply

Marsh Posté le 09-07-2007 à 17:29:23    

Bah si: VC++ 6 :/
Ca passe nickel sur le 2005 Express, et je doute que ça foire avec le 2003 ou encore g++.

Reply

Marsh Posté le 09-07-2007 à 21:55:18    

IrmatDen a écrit :

il est foireux :P

Faut pas abuser non plus. C'est vrai qu'il comporte pas mal de bugs, mais ca ne le rend pas inutilisable a ce point. Je vais lancer l'exemple de Moolfreet chez moi et on verra.

Reply

Marsh Posté le 09-07-2007 à 22:02:56    

Volontier; c'est surtout que je ne peux pas tester, et que les autres environnements que j'utilise n'ont jamais posé le moindre souci ;)

Reply

Marsh Posté le 09-07-2007 à 22:05:15    

Bon, c'est bien ce qui me semblait. Je viens de tester chez moi sur VC6, ca marche nickel, en debug comme en release. Moi je dis qu'il y a une erreur autre part dans ton code.
 
Et pour info, Taz a raison sur le fait qu'il ne faut pas utiliser scanf.
 

Code :
  1. ifstream fp("fichier.txt" );
  2.   fp >> x >> ws >> y;
  3.   fp >> x >> ws >> y;


 
fait tres bien l'affaire (je viens de tester). Tu as dit que tu avais teste mais tu n'as pas donne le resultat de ton test.

Reply

Marsh Posté le 09-07-2007 à 22:30:55    

Ace17 a écrit :

Bon, c'est bien ce qui me semblait. Je viens de tester chez moi sur VC6, ca marche nickel, en debug comme en release. Moi je dis qu'il y a une erreur autre part dans ton code.


Je ne comprend pas comment il pourrais y avoir une erreur ailleurs dans mon code, vu que quand je l'isole totalement ca pose le meme probleme (voir le code console plus haut)

Ace17 a écrit :


Et pour info, Taz a raison sur le fait qu'il ne faut pas utiliser scanf.


Ouep desole, vieille mauvaise habitude...

Ace17 a écrit :


Code :
  1. ifstream fp("fichier.txt" );
  2.   fp >> x >> ws >> y;
  3.   fp >> x >> ws >> y;


 
fait tres bien l'affaire (je viens de tester). Tu as dit que tu avais teste mais tu n'as pas donne le resultat de ton test.


Comme je l'ai mis plus haut ce code ne fait pas d'erreur (ni en Debug, ni en release), en debug il marche tres bien, mais en release... il renvoie x=0.000000, et y=0.000000... (precisement lol)

Message cité 1 fois
Message édité par Moolfreet le 09-07-2007 à 22:31:55
Reply

Marsh Posté le 09-07-2007 à 23:13:07    

Moolfreet a écrit :

Je ne comprend pas comment il pourrais y avoir une erreur ailleurs dans mon code, vu que quand je l'isole totalement ca pose le meme probleme (voir le code console plus haut)

Quand tu dis "isoler totalement" c'est bien creer un autre projet completement separe, on est bien d'accord?   :o  
 
Parce que toi et moi on a meme OS meme compilo meme code et ca donne pas la meme chose, y'a de quoi s'inquieter ... surtout si chez toi ni fscanf ni les ifstreams ne fonctionnent en mode release ..... :heink:  

Reply

Marsh Posté le 09-07-2007 à 23:18:55    

Oui oui, ce que j'appel isoler totalement, c'est bien créer un autre projet completement séparé. Donc pour le fscanf je comprend pas...
Apres, les ifstreams je les ai pas testé séparément, j'ai pas encore eu le temps.  
Pour ce qui est d'avoir le même OS, ce n'est encore moins sur, car je viens de m'appercevoir que le pc sur lequel je compilais (je suis en stage) était sous WinXP sans SP installé. Je viens de mettre à jour le SP2 et par la même occasion, j'ai aussi installer VC 2005 express pour voir si ça marche...
Affaire à suivre...

Reply

Marsh Posté le 09-07-2007 à 23:20:43    

T'as essaye comme je t'ai dit d'activer la debug info en mode release pour voir ce qui provoque l'erreur ?

Reply

Marsh Posté le 09-07-2007 à 23:22:41    

Oui oui, et comme je t'ai répondu, je tombe sur du code assembleur dans tout les coins, et je sais pas trop où chercher précisément...

Reply

Marsh Posté le 09-07-2007 à 23:33:43    

Au temps pour moi, j'avais loupe ta reponse. C'est bizarre ton probleme. A mon avis, si on teste un peu, on va trouver d'autres trucs qui ne marchent pas en release chez toi ... Tu veux pas faire un zip avec un mini projet qui plante ou tu incluerais source+dsw/dsp+binaires ?

Reply

Marsh Posté le 10-07-2007 à 01:06:32    

Voilou : y'a tout là dedant : http://y.lemaout.free.fr/public/test_scanf.rar
 
Sinon je voulais savoir, vu que là il va falloir que je reprenne tout mon code pour VC 2005 express (mon code qui marchait en Debug sous VC6 a plein d'incompatibilités) si le compilo de VC 2005 Express était mieux ou pas que celui de VC++ 6 Pro. Je pense que certains vont me dire que on peut pas trop comparer, mais mon programme effectue des opérations lourdes en temps de calcule et en mémoire... donc j'aimerais bien savoir...

Message cité 1 fois
Message édité par Moolfreet le 10-07-2007 à 21:32:00

---------------
**** |\/|¤¤] [ F®££t ****
Reply

Marsh Posté le 10-07-2007 à 21:33:04    

Bon sinon j'ai repris le même code et tout recompilé sous VC 2005 express et tout marche bien !

Reply

Marsh Posté le 10-07-2007 à 22:01:41    

Moolfreet a écrit :

Voilou : y'a tout là dedant : http://y.lemaout.free.fr/public/test_scanf.rar
 
Sinon je voulais savoir, vu que là il va falloir que je reprenne tout mon code pour VC 2005 express (mon code qui marchait en Debug sous VC6 a plein d'incompatibilités) si le compilo de VC 2005 Express était mieux ou pas que celui de VC++ 6 Pro. Je pense que certains vont me dire que on peut pas trop comparer, mais mon programme effectue des opérations lourdes en temps de calcule et en mémoire... donc j'aimerais bien savoir...


 
VC6 Comme VS2005 peuvent tous deux traiter des "opérations lourdes" sans problème ...
C'est pas vraiment comparable [:god]


---------------
Töp of the plöp
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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