Datei formatiert einlesen
-
Hi,
ich würde gern aus einer Datei
Datei.txt
a(2,2) = -1.835417e+06 [1/s]
a(3,2) = 1.835417e+06 [1/s]
die Zahlen auslesen.
Versucht habe ich es mit 3 Schleifen durchläufe vonscan = fscanf(datei,"a(%d,%d) = %e [1\\s] ",&(Zeile[i]),&(Spalte[i]),&(Wert[i]));
printf("a(%d,%d) = %e und scan: %d \n",Zeile[i],Spalte[i],Wert[i],scan);
Doch das Ergebnis war:
a(1,1) = -2.849212e-41 und scan: 3
a(0,-1216006536) = 4.852668e-270 und scan: 0
a(0,134513496) = -3.044647e-41 und scan: 0Meine Fragen sind : Was muss ich korrigieren und wie hätte man es eleganter machen können. Ich würde mich sehr über eine Antwort freuen und nach google zu urteilen auch einige andere. Vielen Dank
-
1. ist es 1/s und nicht 1\\s, dein scan ist also falsch
2. ist Wert vermutlich ein double-Array, du liest und schreibst hier aber floats.
-
white flow schrieb:
wie hätte man es eleganter machen können.
Falls du hier nicht versehentlich im falschen Unterforum geschreieben hast (hier ist C++, nicht C): Mit C++ Mittel dürfte sich das, wenn auch nicht unbedingt eleganter, so doch auf jeden Fall allgemeiner machen lassen. Und das ist dann doch auch wieder eine Form von Eleganz.
-
Vielen Dank für eure Hilfe:
Mit
scan = fscanf(datei,"a(%d,%d) = %lf [1/s] ",&(Zeile[i]),&(Spalte[i]),&(Wert[i]));
hat es funktioniert.
P.S. Falsches Forum ? Ich glaube nicht
ihr konntet mir doch helfen.
-
SeppJ schrieb:
white flow schrieb:
wie hätte man es eleganter machen können.
Falls du hier nicht versehentlich im falschen Unterforum geschreieben hast (hier ist C++, nicht C): Mit C++ Mittel dürfte sich das, wenn auch nicht unbedingt eleganter, so doch auf jeden Fall allgemeiner machen lassen. Und das ist dann doch auch wieder eine Form von Eleganz.
So etwa?
#include <iostream> #include <fstream> #include <streambuf> struct text { text( const char* txt ) : m_txt( txt ) {} friend std::istream& operator>>( std::istream& in, const text& t ) { using namespace std; istream::sentry ok( in ); if( ok ) { ios_base::io_state state = ios_base::goodbit; const char* ref = t.m_txt; for( istream::int_type m = in.rdbuf()->sgetc(); *ref; ++ref, m = in.rdbuf()->snextc() ) { typedef istream::traits_type traits; if( traits::eq_int_type( m, traits::eof() ) ) { state |= ios_base::eofbit | ios_base::failbit; break; } if( traits::to_char_type( m ) != *ref ) { state |= ios_base::failbit; break; } } in.setstate( state ); } return in; } private: const char* m_txt; }; int main() { using namespace std; ifstream datei("Datei.txt"); int zeile, spalte; for( double wert; datei >> text("a(") >> zeile >> text(",") >> spalte >> text(") =") >> wert >> text("[1/s]"); ) cout << "a(" << zeile << "," << spalte << ") = " << wert << " [1/s]" << endl; return 0; }Gruß
Werner
-
Werner fielen Dank für dein wahrscheinlich
sehr elegante Struktur, die im Moment noch meine Kenntnisse, der verwendeten
Klassen überflügelt, doch einige Anregungen zum Vertiefen gibt.Leider bin ich bin mit einem weitern etwas merkwürdigen C++ Problem konfrontiert.
Die aus der Datei ausgelesen Daten werden durch die Funktion einlesen() wie gewollt zur Kontrolle ausgegeben, doch die main Funktion gibt nichts aus.
Benutze ich aber den konkreten Pfad funktioniert es, was ich sehr merkwürdig finde.Ist die Art und Weise wie ich in der main Funktion auf die Matrix zu greife, ok?
struct Matrix {
int dim;
double **Wert;
};Matrix* einlesen(void)
{int Zeile[400];
int Spalte[400];
double Datenwert[400];char* Dateipfad;// = "/konkreter Dateipfad";
cout<<"Geben Sie bitte den Dateipfad ein."<<endl;
scanf("%s",Dateipfad);FILE datei;
datei = fopen(Dateipfad/"/konkreter Dateipfad"*/,"r");int i = 0;
while(fscanf(datei,"a(%d,%d) = %lf [1/s] ",&(Zeile[i]),&(Spalte[i]),&(Datenwert[i])) != 0 ){
printf("a(%d,%d) = %e [1/s] \n",Zeile[i],Spalte[i],Datenwert[i]);
i++;
}fclose(datei);
cout<<"Es sind: "<<i<<" Datensaetze."<<endl;
int AnzahlDaten;
AnzahlDaten = i;double Zwischenspeicher;
Zwischenspeicher = ((i - 4)/3) +2;int Anz_Dia_Ele;
Anz_Dia_Ele = (int)Zwischenspeicher;cout << "Es sollen "<< Anz_Dia_Ele <<" Eigenwerte berechnet." <<endl;
cout<<endl;Matrix* DatenMatrix;
DatenMatrix = new Matrix;
DatenMatrix->dim = Anz_Dia_Ele;DatenMatrix->Wert = new double*[Anz_Dia_Ele];
for(int i = 0;i<Anz_Dia_Ele;i++){
*(DatenMatrix->Wert + i) = new double[Anz_Dia_Ele];
}for(int t=0;t < AnzahlDaten; t++)
{
((DatenMatrix->Wert + (Zeile[t]-1))+(Spalte[t]-1))= Datenwert[t];
}return DatenMatrix;
}int main()
{
cout<<((einlesen()->Wert+0)+0)<<((einlesen()->Wert+1)+1)<<((einlesen()->Wert+2)+2)<<endl;
}
-
Nur mal eben in die richtigen Tags:
struct Matrix { int dim; double **Wert; }; Matrix* einlesen(void) { int Zeile[400]; int Spalte[400]; double Datenwert[400]; char* Dateipfad;// = "/konkreter Dateipfad"; cout<<"Geben Sie bitte den Dateipfad ein."<<endl; scanf("%s",Dateipfad); FILE *datei; datei = fopen(Dateipfad/*"/konkreter Dateipfad"*/,"r"); int i = 0; while(fscanf(datei,"a(%d,%d) = %lf [1/s] ",&(Zeile[i]),&(Spalte[i]),&(Datenwert[i])) != 0 ){ printf("a(%d,%d) = %e [1/s] \n",Zeile[i],Spalte[i],Datenwert[i]); i++; } fclose(datei); cout<<"Es sind: "<<i<<" Datensaetze."<<endl; int AnzahlDaten; AnzahlDaten = i; double Zwischenspeicher; Zwischenspeicher = ((i - 4)/3) +2; int Anz_Dia_Ele; Anz_Dia_Ele = (int)Zwischenspeicher; cout << "Es sollen "<< Anz_Dia_Ele <<" Eigenwerte berechnet." <<endl; cout<<endl; Matrix* DatenMatrix; DatenMatrix = new Matrix; DatenMatrix->dim = Anz_Dia_Ele; DatenMatrix->Wert = new double*[Anz_Dia_Ele]; for(int i = 0;i<Anz_Dia_Ele;i++){ *(DatenMatrix->Wert + i) = new double[Anz_Dia_Ele]; } for(int t=0;t < AnzahlDaten; t++) { *(*(DatenMatrix->Wert + (Zeile[t]-1))+(Spalte[t]-1))= Datenwert[t]; } return DatenMatrix; } int main() { cout<<*(*(einlesen()->Wert+0)+0)<<*(*(einlesen()->Wert+1)+1)<<*(*(einlesen()->Wert+2)+2)<<endl; }
-
white flow schrieb:
Die aus der Datei ausgelesen Daten werden durch die Funktion einlesen() wie gewollt zur Kontrolle ausgegeben, doch die main Funktion gibt nichts aus.
Benutze ich aber den konkreten Pfad funktioniert es, was ich sehr merkwürdig finde.Das ist nicht merkwürdig, wenn man sich darüber Gedanken hat, wo die Zeichen aus dem String 'DateiPfad' überhaupt hingespeichert werden. Du hast dafür keinerlei Memory zur Verfügung gestellt.
Da wir hier in der C++-Ecke sind - schlage ich Dir folgendes Vorgehen vor (ab Zeile 13 in Fellhuhns Posting):// #include <string> // noch inkludieren string Dateipfad;// = "/konkreter Dateipfad"; cout<<"Geben Sie bitte den Dateipfad ein."<<endl; getline( cin, Dateipfad );Bitte inkludiere noch <string> damit es funktioniert. Die std::string-Klasse nimmt Dir das Besorgen des benötigten Speichers ab und viel einfacher zu benutzten, als wenn Du selbst mit new/alloc versuchst es zu organisieren.
white flow schrieb:
Ist die Art und Weise wie ich in der main Funktion auf die Matrix zu greife, ok?
Nicht so ganz. Jedes mal, wenn Du einlesen() aufrufst, wird es auch ausgeführt. D.h. Die Matrix wird im besten Fall auch dreimal gelesen, was ja völlig unnötig ist, außerdem wird für drei Matrizen Speicher allokiert, der auch nie wieder frei gegeben wird.
Besser Du änderst zunächst die Matrix so ab, dass Du Dich um den Speicher nicht mehr sorgen musst.
#include <vector> #include <cassert> struct Matrix { explicit Matrix( std::size_t dim ) : m_anzSpalten( dim ) , m_werte( dim * dim ) {} double* operator[]( std::size_t idxZeile ) { assert( idxZeile < m_werte.size() / m_anzSpalten ); return &m_werte[ idxZeile * m_anzSpalten ]; } private: std::size_t m_anzSpalten; std::vector< double > m_werte; };Der Zugriff auf ein Element funktioniert dann einfach mit
Matrix mx(20); mx[4][1] = 3.14; // Element mit Index Zeile 4 und Index Spalte 1 setzenDer Code ab Zeile 44 vereinfacht sich dann zu:
Matrix DatenMatrix( Anz_Dia_Ele ); for(int t=0;t < AnzahlDaten; ++t ) { assert( Zeile[t] <= Anz_Dia_Ele ); // Indizes checken assert( Spalte[t] <= Anz_Dia_Ele ); DatenMatrix[ Zeile[t]-1 ][ Spalte[t]-1 ] = Datenwert[t]; } return DatenMatrix;Die Signatur von einlesen muss dann noch angepasst werden
Matrix einlesen() { // usw.und schließlich wird das main() zu:
int main() { using namespace std; Matrix mx = einlesen(); cout << mx[0][0] << " " << mx[1][1] << " " << mx[2][2] << endl; }Gruß
Werner