variablen mit daten aus csv-datei initialisieren
-
hi,
bin noch ein absoluter neuling in sachen c++.
ich möchte aus einer csv-file ...
aufbau:Date, USD, JPY, DKK, <= 1. zeile 25 February 2005, 1.3165, 138.74, 7.4418, <= 2. zeile --- mehr zeilen gibt es nicht ---
variablen ( z.b. float USD ) mit dem zugehörigen dezimalwert aus der csv-datei setzen.
d.h.USD = 1.3165; JPY = 138.74; ...
meine bisherigen versuche scheitern bis zum einlesen über eine while-iteration
... // Filestream deklarieren fstream filestr; // Datei öffnen filestr.open(filename, fstream::in); // Datei auf Existenz prüfen if (! filestr ) { cout << "Datei: " << filename << " existiert nicht!" << endl; return 1; } while ( filestr.get(c) ) { <= hier hörts auf } ...
perl war viel einfacher ...cu...
daniel
-
perl war viel einfacher
Dann verwende doch Perl.
Schau mal in der C++-FAQ. Dort findest du Beispiele für das Lesen und Schreiben aus / in Files.
-
hi,
interessante antwort ???, ich beabsichtige meinen horizont mit c++ zu erweitern und dachte es wäre ein forum wo man hilfe findet.
im übrigend die normale ein- und ausgabe von dateien ist nicht die frage <schuldigung, wenn ich mich falsch ausdrückte> hier geht es um variablenzuordung.
möglich wäre hier ja eine matrix, diesbezüglich kenne ich mich nicht so aus.
wäre für jede hilfe dankbar.
-
So in etwa:[cpp]stf::istream f("cvsdatei.xyz",ios::in);
//die erste Zeile weg:
char c='X';
while(c!='\n')
f.get();
std::string str;
std::getline(f,str); //jetzt ist die 2. Zeile in str
std::string::iterator iter=str.begin();
for(;*iter!=','&&iter!=str.end();++iter);
++iter;
std::string::iterator iter2=iter;
for(;*iter2!=','&&iter2!=str.end();++iter2);
std::string fltstr=str.substr(iter-str.begin(),iter2-iter);
float f=atof(fltstr.c_str());[cpp]...
Keine Garantie, bin in Eile...
-
Hi,
naja das ist in c++ nicht ganz so einfach. Die werte in der datei sind strings die müsstest du erst entsprechend konvertieren. C++ hat feste typen es geht ein bisschen über scalar und nonscalar hinaus.
Also auf anhieb würd ich dir raten die datei zeilenweise auszulesen und
um es dir so einfach wie möglich zu machen boost::tokenizer benutzen.#include<boost/tokenizer.hpp> #include<boost/lexical_cast.hpp> //---- snip alles was du auch schon gemacht hast std::string line; boost::tokenizer<boost::escaped_list_separator<char> > tokens; boost::tokenizer<boost::escaped_list_separator<char> >::iterator it; while(std::getline(in,line)){ tokens.assign(line); for(it=tokens.begin();it!=tokens.end();++it){ //da du weisst welcher art deine werte in der datei sind //kannst du entsprechend umwandeln z.B. mit boost::lexical_cast some_int_val=boost::lexical_cast<int>(*it); some_float_val=boost::lexical_cast<float>(*it); some_string_val=*it; } } //---- snap ------
Das muss natürlich alles angepasst werden .. aber so könnte es gehen.
bad_cast-exception müssten natürlich gefangen werden uns sowas. Soll ja nur den groben plan vermitteln.sofar
-
prolog: Nimm es mir net übel aber imho ist es n schlechter Vorschlag nem C++ Noob boost vorzuführen.
MfG
-
Hi,
geb ich dir grundsätzlich ja recht. Ich hab auch überlesen dass es sich ja nur um eine zeile handelt. Aber ich dacht mir warum was neu machen wenns das schon gibt.
Mir ist auch eben grad noch was aufgefallen..
variablen ( z.b. float USD ) mit dem zugehörigen dezimalwert aus der csv-datei setzen.
Die variablen müssen natürlich in deinen program vorhanden sein, das ist klar oder ? Wenn ich das falsch verstanden hab, vergiss die frage einfach.
sofar ...
-
Auf die Schnelle:
daten.txt:
Date, USD, JPY, DKK,
25 February 2005, 1.3165, 138.74, 7.4418,#include <iostream> #include <fstream> // Datei-Handling #include <string> // C++-Klasse string (Teil der STL) using namespace std; void wait() { std::cin.clear(); std::streambuf * pbuf = std::cin.rdbuf(); std::streamsize size = pbuf->in_avail(); std::cin.ignore(size); std::cin.get(); } int main() { string FN = "daten.txt"; struct data { string date; string USD; string JPY; string DKK; }; ifstream in; in.open( FN.c_str() ); if(!in) { cerr << "Datei kann nicht geoeffnet werden." << endl; } else { // Zahl der Zeilen int N = 2; // dynamisches Array auf dem heap reservieren data * pData = new data[N]; in.clear(); // EOF-Status loeschen //cout << in.tellg() << endl; // Lesezeiger Kontrolle in.seekg(0); // Lesezeiger auf Dateianfang setzen //cout << in.tellg() << endl; // Lesezeiger Kontrolle int count = 0; for( string s; getline(in, s); ++count ) { int dest0 = s.find(",", 0); /* sucht Substring ab Position ( hier: 0 ) */ int dest1 = s.find(",", dest0 + 1); int dest2 = s.find(",", dest1 + 1); int dest3 = s.find(",", dest2 + 1); pData[count].date = s.substr(0 , dest0 ); pData[count].USD = s.substr(dest0 + 2 , dest1-dest0 - 2 ); pData[count].JPY = s.substr(dest1 + 2 , dest2-dest1 - 2 ); pData[count].DKK = s.substr(dest2 + 2 , dest3-dest2 - 2 ); } in.close(); for( int i=1; i<count; ++i ) { cout << pData[i].date << '\n' << atof(pData[i].USD.c_str() ) << '\n' << atof(pData[i].JPY.c_str() ) << '\n' << atof(pData[i].DKK.c_str() ) << endl << endl; } // dynamisches Array auf dem heap freigeben delete[] pData; pData = 0; } wait(); }
Ausgabe auf Konsole:
25 February 2005
1.3165
138.74
7.4418Wenn du die Daten wirklich als float-Variablen benötigst, dann ordnest du diese einfach zu:
float DKK = atof( pData[i].DKK.c_str() );
Ich hoffe, das hilft ein wenig. Kann man auch einfacher und sauberer machen.
-
hallo Erhard Henkes,
vielen dank für den sauberen code.
was mir aufgefallen ist:
die funktion wait (zum löschen des ausgabepuffers) ist ja nicht zwingend erforderlich, oder?cu.
daniel
-
wait (zum löschen des ausgabepuffers)
... brauchst du nur bei der Windows-Konsole, sonst klatscht die gleich wieder zu.
vielen dank für den sauberen code.
Gern geschehen.
Ich habe einen vorhandenen Code auf die Schnelle angepasst, damit du weiter kommst, ist echt *würg*