Einlesen CSV-Datei - for-Schleife kombiniert mit switch-case
-
Hallo,
ich möchte eine CSV-Datei, die aus mehreren Zeilen und vier Spalten besteht, einlesen und die Werte in den einzelnen "Zellen" in einem struct ablegen.
Das Trennen der Werte funktioniert, doch das richtige Ablegen nicht. Hier der Code dazu (nicht erschrecken, ist noch ziemlich hässlich...^^):int lines = 0; const int COLUMNS = 4; // vier Spalten MagicFile* magicarray = new MagicFile[50]; string inputValue = ""; // ein Wert ifstream file; // Datei-Objekt zum Einlesen file.open( "magic.txt", ios::in ); if ( file.is_open() != true ) { cerr << "Fehler beim Lesen der magic.txt-Datei!" << endl; file.close(); } else { while ( getline( file, inputValue ) != 0 ) { cout << endl << "-----------------------" << endl; stringstream streaminput; // Stream-Objekt streaminput << inputValue; // ganze Zeile in Stream-Objekt inputValue.clear(); while ( getline( streaminput, inputValue, ';' ) != 0 ) { cout << "Wert: " << inputValue << endl; for ( int i=0; i<COLUMNS; i++ ) { switch(i) { case 0: { magicarray[lines].filetype = inputValue; break; } case 1: { magicarray[lines].defExt = inputValue; break; } case 2: { magicarray[lines].mNumber = inputValue; break; } case 3: { magicarray[lines].programm = inputValue; break; } default: { cout << "Hier hat was nicht geklappt" << endl; break; } } } } lines++; } file.close(); }
Falls ihr weitere Infos braucht, einfach kurz Bescheid sagen. Ansonsten wäre ich super dankbar, wenn mir jemand helfen kann!
Ein anderer (eleganterer) Vorschlag ist auch ok
-
1. "Geht nicht" bzw "funktioniert nicht" ist keine Fehlerbeschreibung.
2. Den code aufräumen (ohne jetzt mal irgendwelche Fehler zu beheben, und ohne Anspruch darauf, das ich alles entfernt habe):int lines = 0; MagicFile* magicarray = new MagicFile[50]; // das kann man noch als "nicht völlig unnötig" durchgehen lassen, fallst du den magicarray als rückgabewert der Funktion hast string inputValue = ""; // ein Wert ifstream file("magic.txt", ios::in ); // Datei-Objekt zum Einlesen if ( file.is_open() != true ) { cerr << "Fehler beim Lesen der magic.txt-Datei!" << endl; } else { while ( getline( file, inputValue ) != 0 ) { cout << endl << "-----------------------" << endl; stringstream streaminput(inputValue); // Stream-Objekt inputValue.clear(); while ( getline( streaminput, inputValue, ';' ) != 0 ) { cout << "Wert: " << inputValue << endl; magicarray[lines].filetype = inputValue; magicarray[lines].defExt = inputValue; magicarray[lines].mNumber = inputValue; magicarray[lines].programm = inputValue; } lines++; } }
3. Sobald eine genauere Fehlerbeschreibung kommt (Was soll passieren, was passiert stattdessen? Wie lautet die Fehlermeldung, falls es eine gibt?), kommt auch ne genauere Antwort.
-
eule23 schrieb:
ich möchte eine CSV-Datei, die aus mehreren Zeilen und vier Spalten besteht, einlesen
Das ist schön. Schön wäre es auch, wenn in deinem Beitrag stehen würde, wie der genaue Aufbau der Datei ist.
eule23 schrieb:
und die Werte in den einzelnen "Zellen" in einem struct ablegen.
Auch das ist schön. Schön wäre es auch, wenn ich die Definition der
struct
sehen könnte.eule23 schrieb:
Das Trennen der Werte funktioniert
Das mit dem funktionieren ist immer so eine Sache. Es gibt viele Wege, um etwas zum Funktionieren zu bringen. Viele Wege sind oft schlecht, und nur wenige sind gut.
eule23 schrieb:
Hier der Code dazu (nicht erschrecken, ist noch ziemlich hässlich...^^)
So hat doch jeder mal angefangen.
-
KMT schrieb:
int lines = 0; MagicFile* magicarray = new MagicFile[50]; // das kann man noch als "nicht völlig unnötig" durchgehen lassen, fallst du den magicarray als rückgabewert der Funktion hast string inputValue = ""; // ein Wert ifstream file("magic.txt", ios::in ); // Datei-Objekt zum Einlesen if ( file.is_open() != true ) { cerr << "Fehler beim Lesen der magic.txt-Datei!" << endl; } else { while ( getline( file, inputValue ) != 0 ) { cout << endl << "-----------------------" << endl; stringstream streaminput(inputValue); // Stream-Objekt inputValue.clear(); while ( getline( streaminput, inputValue, ';' ) != 0 ) { cout << "Wert: " << inputValue << endl; magicarray[lines].filetype = inputValue; magicarray[lines].defExt = inputValue; magicarray[lines].mNumber = inputValue; magicarray[lines].programm = inputValue; } lines++; } }
Da hilft doch nur refactoring.
Edit: Ja, geht:
std::array<std::vector<int>, 4> arr; std::ifstream stream("magic.txt"); for(size_t a(0);a < 4;++a) { for(size_t ct(0);stream.peek() != '\n' && stream.good();++ct) if(ct % 2) stream.get(); else arr.at(a).push_back(*std::istream_iterator<int>(stream)); stream.get(); }
-
Vielen Dank schon mal für eure Antworten!
Also, ich möchte folgendes machen: Ich habe diese CSV-Datei:
Dateityp;Default Extension;Magic Number (hex-Digits);Programm Adobe PDF;pdf;0x255044462d;evince %1 Postscript;ps;0x2521;evince %1 jpg, jpeg;jpg;0xffd8ffe0;gimp %1 tiff;tif;0x49492a00;gimp %1 zip;zip;0x504b0304;file-roller %1 gzip;gz;0x1f8b;file-roller %1 Truetype font;ttf;0x0001000000;gnome-font-viewer %1 bash;sh;0x2321202f62696e2f62617368;jedit %1
Diese Werte sollen eingelesen und in diesem struct abgelegt werden:
typedef struct MagicFile { std::string filetype; std::string defExt; std::string mNumber; std::string programm; }MagicFile;
In "filetype" soll dabei jeweils der Inhalt der ersten Spalte der Datei stehen (beginnend ab der 2.Zeile), also z.B. "Adobe PDF". "defExt" soll den Inhalt der 2.Spalte enthalten ("pdf") usw.
Momentan bekomme ich zwar keine Fehlermeldung, doch wird in allen strings des structs immer nur der Inhalt der jeweils 4.Spalte abgelegt (z.B. "evince %1"), d.h.
for (int i = 1; i < lines; i++) { cout << "Datei: " << magicarray[i].filetype << endl; cout << "Extension: " << magicarray[i].defExt << endl; cout << "Nummer: " << magicarray[i].mNumber << endl; cout << "Prog: " << magicarray[i].programm << endl; }
ergibt für die erste Zeile:
Datei: evince %1
Extension: evince %1
Nummer: evince %1
Prog: evince %1...und für die anderen Zeilen das ganze analog.
Es soll aber drin stehen:Datei: Adobe PDF
Extension: pdf
Nummer: 0x255044462d
Prog: evince %1Ich hoffe, das ist halbwegs verständlich, ansonsten einfach nochmal nachfragen
-
Jo, nimm doch
std::vector<MagicFile> v; std::ifstream stream("magic.txt"); for(MagicFile temp;stream.good();v.push_back(temp)) { std::getline(stream, temp.filetype, ';'); std::getline(stream, temp.defExt, ';'); std::getline(stream, temp.mNumber, ';'); std::getline(stream, temp.programm); }
-
Das sieht gut aus, klappt auch alles mit dem Einlesen
Hab nur noch nie mit Vektoren gearbeitet (blutiger Anfänger^^) und weiß nicht so richtig, wie's dann weitergeht...
Eigentlich sollen die eingelesenen Werte in ein dynamisches ArrayMagicFile* magicarray = new MagicFile[50];
geht das? Muss diese Werte nämlich später mit anderen Werten aus einem zweiten dynamischen Array vergleichen, das ähnlich aufgebaut ist.
-
eule23 schrieb:
geht das? Muss diese Werte nämlich später mit anderen Werten aus einem zweiten dynamischen Array vergleichen, das ähnlich aufgebaut ist.
Autsch. Ich versichere dir, die STL ist sehr nützlich, es lohnt sich definitiv sie zu lernen. Mit dynamischen Arrays zu arbeiten ist allerdings ziemlich schlecht und eher C-Style (also selbst Speicher allokieren).
Du kannst das zweite Array ja so in einen vector packen:std::vector v(darray, darray + 50);//Angenommen, die Größe ist 50
Und dann einfach per
==
die beiden Vektoren vergleichen (Operatorüberladung lernste später).