Datei zeilenweise in Array schreiben, (MFC)
-
Hallo!
Ich habe versucht (nach betätigen eines Buttons) eine Datei zu öffnen, die floatwerte zeilenweise aus der Datei auszulesen und dann in ein Array zu schreiben. (dabei soll jeder gerade (0,2,4,6,8,...) wert aus der Datei stammen, jeder ungerade wert eine 0 sein). Das soll später dem FFT-Algorithmus aus numerical recipes übergeben werden, aber ich habe erstmal genug Probleme um eine datei in ein array zu schreiben:void CtestDlg::OnBnClickedButton1() { CFileDialog cFile(TRUE); int iRet=cFile.DoModal(); CString strFileName; strFileName = cFile.GetPathName(); if(iRet == IDOK) MessageBox(strFileName); else { MessageBox("Keine Datei Ausgewählt"); return; } std::fstream inStream(strFileName.GetBuffer(), std::fstream::in); char buffer[256]; //Auslesen der 1.Zeile: //inStream.getline(buffer,256); //char *cstrText=buffer; // ist ein Textfeld im Dialog //MessageBox(buffer); //UpdateData(FALSE); for (int i = 0; i<linecount*2 && inStream.getline(buffer,256); i+2) // angelegtes array auf alle geraden stellen daten schreiben { float temp = (float) atof(buffer); // string in double in float data[i] = temp; } char anz[256]; itoa(linecount, anz, 10); //Umwandlung von uint nach string MessageBox(anz); }
Im prinzip bestimme ich erst mal die zeilenanzahl indem ich die datei einmal durchgeghe und dann möchte ich wieder von vorne anfangen, um die datei auszulesen.
Geht das so überhaupt? Ich habe das Gefühl das in dem Array später nicht das drinsteht was sollkann mir jemand helfen?
-
Huch, fast vergessen!!
Die einzulesende Datei sollte ausschliesslich floatwerte enthalten, und z.b. so aussehen:0.567 0.233 1.444 2.654 6.777 5.333 1.444 0.545 0.100 0.001 0.200
-
Erstens: Was genau ist eigentlich "data"? Wenn das ein STL-Container ist, kannst du ihn auch mitwachsen lassen, während du die Datei einliest.
(btw, bin ich blind oder wo berechnest du die Dateigröße?)Zweitens: Verwende lieber std::string anstelle des char-Arrays.
Drittens: Die Anweisung
i+2
in der for-Schleife hat keine bleibenden Effekte - wenn du den Ziel-Index weiterzählen willst, brauchst dui+=2
.
-
Huppsa, mir ist beim c&p was verloren gegangen :
void CtestDlg::OnBnClickedButton1() { CFileDialog cFile(TRUE); int iRet=cFile.DoModal(); CString strFileName; strFileName = cFile.GetPathName(); if(iRet == IDOK) MessageBox(strFileName); else { MessageBox("Keine Datei Ausgewählt"); return; } std::fstream inStream(strFileName.GetBuffer(), std::fstream::in); char buffer[256]; while (inStream.getline(buffer,256)) {//while-schleife zur bestimmung der Zeilenzahl linecount++; } data = new float[linecount*2] ; // new erzeugt objekt im heap, zeiger auf 1.element for(int k=0; k<linecount; k++) { data[k] = 0; } for (int i = 0; i<linecount*2 && inStream.getline(buffer,256); i+2) // angelegtes array auf alle geraden stellen daten schreiben { float temp = (float) atof(buffer); // string in double in float data[i] = temp; } char anz[256]; itoa(linecount, anz, 10); //Umwandlung von uint nach string MessageBox(anz); }
so sieht der code aus!
-
Wie schon gesagt, nimm lieber STL-Container (std::vector<> und std::string):
vector<float> data; // anstelle von float* data; ... std::fstream inStream(strFileName.GetBuffer(), std::fstream::in); string zeile; data.clear(); while(getline(inStream,zeile)) // angelegtes array auf alle geraden stellen daten schreiben { float temp = (float) atof(zeile.c_str()); // Alternativen findest du in der C++ FAQ data.push_back(temp); data.push_back(0); }
-
WOW!
Ich habe gerade in deiner Signatur eine kleine Einführung ins Thema Vektoren gefunden und ich muss sagen, das ist im Prinzip genau das was ich gebraucht habe!
Mich muss später nämlich noch die Liste auf die Länge 2^n mit weiteren 0en aufblasen, das geht ja mit dem Vektor auch ziemlich leicht.Dein Code macht ja genau das was ich will
einmal einen wert reinschreiben und einmal ne 0 ...Das blöde ist nur, das die FFT-Funktion ein Array data[] erwartet ...
-
heinerseiner schrieb:
Das blöde ist nur, das die FFT-Funktion ein Array data[] erwartet ...
Die saubere Lösung: Such dir eine bessere FFT-Funktion, die mit STL-Iteratoren auskommt
Für Notfälle und auf eigenes Risiko: mit
&data.front()
bekommst du den vector<>-Inhalt in Roh-Format.
-
hallo, ich bin´s nochmal!
Der Funktion, die ich benutzen möchte, wird wie schon gesagt ein Array data[] übergeben.
Eigentlich komme ich ja an die Einträge im vektor ebenfalls z.B. mit testvektor[5]
ran. Im Prinzip wäre doch dann keine Änderung nötig? Oder kommts darauf an, was genau die Funktion mit dem Array anstellt?
viele grüße und entschuldigung im vorraus für mein unwissen
-
Für den Aufruf der Funktion ist es ein Problem - vector<> hat keine implizite Umwandlung in ein "normales" Array (deswegen der obengenannte Umweg). Aber afik garantiert der vector, daß seine Elemente an einem Stück im Speicher untergebracht sind, deswegen mußt du dir die Adresse des ersten Elements holen, um etwas für die C-Funktion taugliches bereitzustellen.
Auf den Inhalt der Funktion kommt es insoweit an, daß du nicht über das Ende des vom vector reservierten Speichers hinausschreibst (d.h. die Funktion sollte auch eine Größenangabe entgegennehmen.
-
Hallo, falls es jemanden interessiert:
Ich habe mich ein wenig mit der konvertierung vektor nach array befasst und bin auf folgendes gekommen:
float a_data [v_data.size()]; for(int i = 0; i < v_data.size(); i++) a_data[i] = v_data[i];
funktioniert (zumindest auf meinem compiler) nicht, da die länge des arrays
zur compile-zeit nicht feststeht.
Ein bisschen rumbiegen (deref) mit zeigern erlaubt die konvertierung trotzdem:float* a_data = new float[v_data.size()]; for(int j=0;j<v_data.size();j++) { float* tempo = &v_data[j]; a_data[j] = *tempo; }
jetzt habe ich nur die frage : ist das "legal" ? Oder habe ich nur glück dass mein compiler das durchgehen lässt?
-
Bei einem std::vector ist garantiert (anders als bei der std::deque oder dem C++03-std::string), dass der Speicher in einem Bereich steht. Also kannst du Folgendes machen:
void f(float* data, size_t size); // Funktionsprototyp, nimmt einen float-Zeiger entgegen ... std::vector<float> data; // Elemente hinzufügen f(&data[0], data.size()); // &data[0] oder &data.front() ist die Adresse des ersten Elements
Du brauchst also nicht den Umweg zu gehen (und wenn es sich, wie in deinem Fall, um PODs handelt, wäre auch
memcpy
die bessere Wahl).