Problème sur un flux de lecture à partir d'un fichier .txt

Problème sur un flux de lecture à partir d'un fichier .txt - C++ - Programmation

Marsh Posté le 07-08-2006 à 11:46:22    

Bonjour,
 
Je rencontre une grande difficulté pour créer une fonction qui puisse lire à partir d'un fichier ".txt" une matrice trinagulaire supérieure et la stocker dans une variable matrice que j'ai définie préalablement.
 
N'étant pas expert en c++, j'ai codé en faisant abstraction de la gestion dynamique de la mémoire ce qui me joue des tours maintenant.
 
J'ai établi un code qui marche dans certains cas et qui est le suivant :
 
 

Code :
  1. #include "essai.h"
  2. #include <iostream>
  3. #include <fstream>
  4. #include <iomanip>
  5. using namespace std;
  6. using namespace std;
  7. int main()
  8. {
  9.   // Ouverture du fichier
  10.   ifstream fichierEntree("c:\\test1.txt", ios::in);
  11.   // Test d'ouverture du fichier
  12.     if (!fichierEntree) {
  13.         cerr << "Problème d'ouverture de fichier" << endl;
  14.         exit(1);
  15.     }
  16.     char* ligne;
  17.     int i = 0;
  18.     char * err = NULL;
  19. //double z;  
  20.     ligne = new char[10];
  21.     fichierEntree.getline(ligne, 4);
  22.     int conv1 = strtoul(ligne,0,10);
  23. ArrayLengthSpecifier dimension(conv1);
  24. cout << conv1 << endl;
  25. SymmetricMatrix covariance(dimension);
  26.     int longueur;
  27.     do
  28.   {
  29.   i = i + 1;
  30.   longueur = 9 * i + 1;
  31.   ligne = new char [longueur];//format "0.00E+00"
  32.   //donc 8 caractères; 9i=8i+ (i-1) espaces + élt nul terminal
  33.   fichierEntree.getline(ligne,longueur);
  34.   cout << ligne << endl;
  35.   
  36.   for (int j=1;j<=i;j++)
  37.  {
  38.   char temp[9];
  39.   for (int k=0;k<=7;k++)
  40.   {
  41.    temp[8]=0;
  42.    if (j==1)
  43.    temp[k] = ligne[k];
  44.    else
  45.    temp[k] = ligne[9* (j - 1) + k ];//attention dimension de 0 à n-1
  46.   }
  47.   const char* caractere=temp;
  48.   cout << caractere << endl;
  49.   covariance(i,j) = 2 * strtod(caractere, &err);
  50.   cout << covariance(i,j) << endl;
  51.   cout << covariance(j,i) << endl;
  52.  }
  53.  delete[] ligne;
  54.   }
  55.   while (!fichierEntree.eof());
  56.     fichierEntree.close();
  57. }


Ce code marche bien sur des matrices de types suivant :
 
 

Code :
  1. 3
  2. 1.23E-02
  3. 1.24E-02 1.26E-02
  4. 1.27E-02 1.23E-04 1.23E-03
  5. Par contre dès qu'il s'agit d'une matrice qui contient un nombre négatif (par exemple) :


 

Code :
  1. 3
  2. 1.23E-02
  3. -1.24E-02 1.26E-02
  4. 1.27E-02 1.23E-04 1.23E-03


 
Ma définition qui fixe la dimension de temp à 9, devient fausse puisque celle-ci avec le signe moins deviens égale à 10.
 
Aurriez vous une idée qui puisse contourner le problème??.  
 
J'ai pensé à imbriquer une instruction if à l'intérieure de ma boucle qui test si le premier caractère est "-" et à ce moment fait une réallocation de temp pour porter sa dimension à 10. Mais je ne sais pas comment coder ça en c++. Auriez vous une idée à me proposer, je suis vraiment bloquer la dessus ??
 
Merci de votre aide

Reply

Marsh Posté le 07-08-2006 à 11:46:22   

Reply

Marsh Posté le 07-08-2006 à 13:34:29    

Salut,
 
tu es en train de réinventer la roue en faisant à la main tes lectures de nombres. Il serait beaucoup plus simple d'utiliser les outils que te propose le C++.
 
Pour lire des nombres dans ton fichier d'entrée, il te suffit d'utiliser l'opérateur >> (exactement de la même manière que lorsque tu utilises l'opérateur << pour écrire sur un flux de sortie).
Exemple:

Code :
  1. ifstream fichierEntree( /*...*/ );
  2. double d;
  3. fichierEntree >> d;



---------------
TriScale innov
Reply

Marsh Posté le 07-08-2006 à 13:55:59    

franceso a écrit :

Salut,
 
tu es en train de réinventer la roue en faisant à la main tes lectures de nombres. Il serait beaucoup plus simple d'utiliser les outils que te propose le C++.
 
Pour lire des nombres dans ton fichier d'entrée, il te suffit d'utiliser l'opérateur >> (exactement de la même manière que lorsque tu utilises l'opérateur << pour écrire sur un flux de sortie).
Exemple:

Code :
  1. ifstream fichierEntree( /*...*/ );
  2. double d;
  3. fichierEntree >> d;



 
Merci pour ta réponse je savais bine que je me trompais dans ma démarche ça ne pouvais pas être aussi complqiué que ça. Mais comme je suis débutant en c++ je butte encore sur la facçon d'utiliser l'opératuer par exemple je voudrais traiter un à un les éléments issus de mon fichier txtx pour les stcoker dans une classe matrice prédifini auparavant par une bibliothèque mathématique.
Par exmple le premier élément représente la dimension. Il faudrait que je le recupère et ensuite qu'il définisse la dimension grace au code :  
element1 représente ici le premier element issu de moin fichier .txt en l'occurence dans l'exemple ci-dessus : 3  

Code :
  1. ArrayLengthSpecifier dimension(element1);
  2. cout << element1 << endl;
  3. SymmetricMatrix covariance(element1);


 
Puis pour les autres éléments je voudrais les stocker dans la matrice :  
 

Code :
  1. covariance(i,j)


 
Bien sur SymmetricMatrix est déjà défini dans une librairie attaché à mon projet.
 
Peux-tu m'aider car vraiment je butte sur cette partie?
 
Merci

Reply

Marsh Posté le 07-08-2006 à 14:13:48    

Par exemple pour la lecture de la taille de ta matrice, tu devrais remplacer les lignes suivantes

Citation :

Code :
  1. ligne = new char[10];
  2. fichierEntree.getline(ligne, 4);
  3. int conv1 = strtoul(ligne,0,10);
  4. ArrayLengthSpecifier dimension(conv1);



par une simpel utilisation de l'opérateur >> :

Code :
  1. int conv1;
  2. fichierEntree >> conv1;
  3. ArrayLengthSpecifier dimension(conv1);


 
Apres, pour remplir la matrice, c'est pareil : il te suffit de lire tes nombres un par un dans le fichier. En gros ça te donnera quelque chose dans ce style là :

Code :
  1. /* boucle sur i */
  2. for( i=0 ; /*...*/ ; /*...*/ )
  3. {
  4.   /* boucle sur j */
  5.   for( j=0 ; /*...*/ ; /*...*/ )
  6.   {
  7.     fichierEntree >> covariance(i,j);
  8.   }
  9. }


---------------
TriScale innov
Reply

Marsh Posté le 07-08-2006 à 14:19:32    

franceso a écrit :

Par exemple pour la lecture de la taille de ta matrice, tu devrais remplacer les lignes suivantes

Citation :

Code :
  1. ligne = new char[10];
  2. fichierEntree.getline(ligne, 4);
  3. int conv1 = strtoul(ligne,0,10);
  4. ArrayLengthSpecifier dimension(conv1);



par une simpel utilisation de l'opérateur >> :

Code :
  1. int conv1;
  2. fichierEntree >> conv1;
  3. ArrayLengthSpecifier dimension(conv1);


 
Apres, pour remplir la matrice, c'est pareil : il te suffit de lire tes nombres un par un dans le fichier. En gros ça te donnera quelque chose dans ce style là :

Code :
  1. /* boucle sur i */
  2. for( i=0 ; /*...*/ ; /*...*/ )
  3. {
  4.   /* boucle sur j */
  5.   for( j=0 ; /*...*/ ; /*...*/ )
  6.   {
  7.     fichierEntree >> covariance(i,j);
  8.   }
  9. }



 
merci pour ta réponse. Effectivement c'est ce que j'ai commencé à faire je te tiens au courant et encore merci pour ton aide

Reply

Marsh Posté le 07-08-2006 à 14:40:19    

Par contre au niveau des boucles ça coince toujours, voilà ce que j'ai mis, mais apparament il n'arrive pas à lire l'élément (i,j) = (2,2) = 1.26E-02
Je dois me tromper dans la mise en place des boucles, mais pour moi ca devrai marcher, qu'en penses-tu???
 
 

Code :
  1. #include "essai.h"
  2. #include <iostream>
  3. #include <sstream>
  4. #include <fstream>
  5. #include <iomanip>
  6. #include <string>
  7. using namespace std;
  8. int main()
  9. {
  10. ifstream FichierMatrice("c:\\test1.txt",ios::in);
  11. if (!FichierMatrice)
  12. {
  13.  cerr << "Ouverture du fichier impossible" << endl;
  14.  exit(1);
  15. }
  16. double val;
  17. double valj;
  18. int val1;
  19. int i = 0;
  20. FichierMatrice >> val1;
  21. ArrayLengthSpecifier dimension(val1);
  22. SymmetricMatrix covariance(dimension);
  23. cout << val1 << endl;
  24. do
  25. {
  26. i = i + 1;
  27. for (int j=1;j<=i;j++);
  28. {
  29. FichierMatrice >> covariance(i,j);
  30. cout << covariance(i,j) << endl;
  31. cout << covariance(j,i) << endl;
  32. }
  33. }
  34. while (!FichierMatrice.eof());
  35. return 0;
  36. }

Reply

Marsh Posté le 07-08-2006 à 14:49:50    

Est-ce que c'est normal que tes indices i,j commencent à 1 ?
 
Que veux tu dire par "il n'arrive pas à lire l'élément (2,2)" ? Qu'est-ce qui se passe juste avant l'erreur ; qu'est-ce qui se passe au moment où tu tentes de lire l'élément (2,2) ?
 
Pourquoi ta boucle en i n'est-elle pas un simple for( int i=1 ; i<=val1 ; ++i ) ?


---------------
TriScale innov
Reply

Marsh Posté le 07-08-2006 à 15:05:04    

franceso a écrit :

Est-ce que c'est normal que tes indices i,j commencent à 1 ?
 
Oui c'est normal ma matrice covariance est définie à partir de l'élément (1,1).
 
Que veux tu dire par "il n'arrive pas à lire l'élément (2,2)" ? Qu'est-ce qui se passe juste avant l'erreur ; qu'est-ce qui se passe au moment où tu tentes de lire l'élément (2,2) ?
 
Lorsque j'affiche le résultat sur la fenêtr dos (cette manipumation est du au fait que je ne peux pas déboguer mon code en le parcourant  ligne à ligne pour des raisons que j'ignore??) c'est pour ça que je met des cout partput c'est pour voir à quel niveau il se plante alors en mettant le code suivant  
[code]
#include "essai.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <string>
 
using namespace std;
 
 
 
int main()
{
 ifstream FichierMatrice("c:\\test1.txt",ios::in);
 if (!FichierMatrice)
 {
  cerr << "Ouverture du fichier impossible" << endl;
  exit(1);
 }
 double val;
 int val1;
 int i = 0;
 
 FichierMatrice >> val1;
 ArrayLengthSpecifier dimension(val1);
 SymmetricMatrix covariance(dimension);
 cout << val1 << endl;  
 
 do  
 {
 i = i + 1;  
 for (int j=1; j<=i; j++);
 {
 FichierMatrice >> val;
 cout << val << endl;
 covariance(i,j) = val;
 cout << covariance(i,j) << endl;
 cout << covariance(j,i) << endl;
 }
 }
 while (!FichierMatrice.eof());
 return 0;
}
 
[code]
 
Il plante dans les boucles à i=2 et à j= 2.
En elevant les cout<<covariance(i,j)<<endl il ne plante pas du tout et sort tout les éléments.
 
Pourquoi ta boucle en i n'est-elle pas un simple for( int i=1 ; i<=val1 ; ++i ) ?


Je ne pense pas que ça chnage grand chose en comparaisant avec le do.
 
N'hésite pas si tu as d'autres question ça me permet de vérifier de mon côté si je suis sur la bonne voie, Je pense que ça vient du fait qu'un à moemnt covariance(i,j) est mal incrementrée???  
 
 

Reply

Marsh Posté le 07-08-2006 à 15:22:00    

Hmm, tout cela ressemble fort à une erreur de segmentation...
 
Peux-tu me dire un peu mieux comment marche ta classe SymmetricMatrix ? C'est toi qui l'as programmée, ou elle vient d'une bibliothèque extérieure déjà testée ?
 
Si tu enlèves uniquement la ligne cout << covariance(j,i) << endl; (mais pas le cout << covariance(i,j) ) est-ce que ça plante ou pas ?


---------------
TriScale innov
Reply

Marsh Posté le 07-08-2006 à 15:44:59    

franceso a écrit :

Hmm, tout cela ressemble fort à une erreur de segmentation...
 
Peux-tu me dire un peu mieux comment marche ta classe SymmetricMatrix ? C'est toi qui l'as programmée, ou elle vient d'une bibliothèque extérieure déjà testée ?
 
Si tu enlèves uniquement la ligne cout << covariance(j,i) << endl; (mais pas le cout << covariance(i,j) ) est-ce que ça plante ou pas ?


 
Oui, oui ca plante toujours, mais la classe SymmetricMatrix est bien définie car je la teste autre part et ça marche donc cela ne vient pas de sa définition d'utant plus que comme elle est définie comme étant une matrice symétrique .
Le test avec cout << covariance(j,i) << sert seulement à voir si elle marche bien mais comme c'est le cas des deux premier éléments je ne me pose pas trop de questions la dessus je pense plutôt que c'est une errreur d'incrémentation de boucle.  
 

Reply

Marsh Posté le 07-08-2006 à 15:44:59   

Reply

Marsh Posté le 07-08-2006 à 16:36:33    

franceso a écrit :

Hmm, tout cela ressemble fort à une erreur de segmentation...
 
Peux-tu me dire un peu mieux comment marche ta classe SymmetricMatrix ? C'est toi qui l'as programmée, ou elle vient d'une bibliothèque extérieure déjà testée ?
La classe SymmetricMatrix est bien définie je l'ai pris de la bibliothèque Newmat et je l'ai testé autre part (pas de problème elle marche) Je pense que cela ne vient pas de sa définition  
 
 
Si tu enlèves uniquement la ligne cout << covariance(j,i) << endl; (mais pas le cout << covariance(i,j) ) est-ce que ça plante ou pas ?


 
Le test avec cout << covariance(j,i) << sert seulement à voir si elle marche bien mais comme c'est le cas des deux premier éléments je ne pense que cela vienne de la classe SmmetricMatrix.
 
Par contre j'ai remplacé le <= de la boucle j par le < tout court et bizarrement ça compile jusqu'à l'élément (3,1) en tenant compte de l'élément (2,1).
Je ne comprend pas la raison ???

Reply

Marsh Posté le 07-08-2006 à 16:46:26    

iamora a écrit :

Par contre j'ai remplacé le <= de la boucle j par le < tout court et bizarrement ça compile jusqu'à l'élément (3,1) en tenant compte de l'élément (2,1).
Je ne comprend pas la raison ???

Tu veux dire que le programme tourne jusqu'à i=3, j=1  et met dans covariance(3,1) la valeur que tu t'attendrais à avoir dans covariance(2,2) ?
 
La raison est que tel que ton programme est écrit, il ne tient pas compte de l'agencement des données dans le fichier. Il lit juste la suite des valeurs dans l'ordre sans se soucier de la ligne sur laquelle elles sont. Du coup, si ta boucle saute directement de 2,1 à 3,1 la valeur mise dans 3,1 est celle qui suit immédiatement la valeur mise dans 1,2. J'ai l'impression de ne pas être très clair, mais je ne sais pas trop comment l'expliquer mieux.


---------------
TriScale innov
Reply

Marsh Posté le 07-08-2006 à 17:05:26    

franceso a écrit :

Tu veux dire que le programme tourne jusqu'à i=3, j=1  et met dans covariance(3,1) la valeur que tu t'attendrais à avoir dans covariance(2,2) ?
 
La raison est que tel que ton programme est écrit, il ne tient pas compte de l'agencement des données dans le fichier. Il lit juste la suite des valeurs dans l'ordre sans se soucier de la ligne sur laquelle elles sont. Du coup, si ta boucle saute directement de 2,1 à 3,1 la valeur mise dans 3,1 est celle qui suit immédiatement la valeur mise dans 1,2. J'ai l'impression de ne pas être très clair, mais je ne sais pas trop comment l'expliquer mieux.


 
En fait que veut tu dire par "Il lit juste la suite des valeurs dans l'ordre " est ce par ordre croissant comment marche  >> ???
J'ai remarqué en testant que pour mon programme  
covariance(1,2) est équivalent à l'élément (1,1)
covariance(2,3) ou covariance(3,2) est équivalent à l'élément (2,1)  
covariance(3,4) est équivalent à l'élément (2,2)  
Je ne sais pas pourquoi il saute comme ça??


Message édité par iamora le 07-08-2006 à 17:07:12
Reply

Marsh Posté le 07-08-2006 à 17:14:31    

franceso a écrit :

Tu veux dire que le programme tourne jusqu'à i=3, j=1  et met dans covariance(3,1) la valeur que tu t'attendrais à avoir dans covariance(2,2) ?
 
La raison est que tel que ton programme est écrit, il ne tient pas compte de l'agencement des données dans le fichier. Il lit juste la suite des valeurs dans l'ordre sans se soucier de la ligne sur laquelle elles sont. Du coup, si ta boucle saute directement de 2,1 à 3,1 la valeur mise dans 3,1 est celle qui suit immédiatement la valeur mise dans 1,2. J'ai l'impression de ne pas être très clair, mais je ne sais pas trop comment l'expliquer mieux.


 
Bon je vois ce que tu veux dire. Est ce que je peux par changer le code de telle façon à ce que val stocke les valeurs qu'elle prend dans des adresses qui se suivent grâce à une boucle genre un tableau puis dire à covariance(i,j) de prendre ses valeurs???

Reply

Sujets relatifs:

Leave a Replay

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