C++ unter Linux aus Tabelle einlesen
-
Skym0sh0 schrieb:
Entweder in einem zweidimensionalen Vector oder einer Map (ob Hash- oder Baummap ist erstmal egal).
Aber zweidimensionalen Vector wenn ich 4 spalten habe?
Wie wird der denn angesprochen und deklariert?
-
Onubub schrieb:
Aber zweidimensionalen Vector wenn ich 4 spalten habe?
Wie wird der denn angesprochen und deklariert?Wenn es immer 4 Spalten sind eher ein vector<array>. Also
vector<array<datenyp, 4>>. Weiterhin brauchst du dann auch nicht erst alle Zeilen einzulesen, lies einfach 4 Werte nacheinander, dann hast du doch automatisch eine Zeile.Ob obiger Datentyp wirklich richtig ist, kommt drauf an, was die Spalten bedeuten und was du damit machen willst. Modellier nicht nach dem Typ der Daten, sondern nach der logischen Bedeutung. Wären Beispielsweise die ersten drei Spalten Koordinaten und die letzte ein zugehöriger Wert, dann wäre obiger Vorschlag mit dem vector<array> eher falsch, denn dann würden drei dieser Werte logisch zusammen gehörten zu einer Positionsangabe und das sollte auch so modelliert werden. Ob ein vector zur Sammlung der Zeilen richtig ist hängt ebenfalls davon ab, was hinterher passieren soll. vector ist gut zum Durchiterieren und dranhängen, und auch für Allroundaufgaben. Aber er kann für gewisse Anwendungen viel schlechter sein als spezialisierte Datenstrukturen.
-
Gehen wir mal hiervon aus:
xxx; Spalte1;Spalte2; Spalte3; Spalte4; A; 1; 1000; 2485; 535; B; 5761; 10050; 244585; 534575; C; 1457; 100750; 24855; 5354;Dann geht das in etwa so: Code
Aber ist nicht ganz richtig, hab jetzt nur keine Zeit da weiter zu gucken.
-
Vielen Dank für eure schnelle Hilfe.
Skym0sh0 schrieb:
Gehen wir mal hiervon aus:
xxx; Spalte1;Spalte2; Spalte3; Spalte4; A; 1; 1000; 2485; 535; B; 5761; 10050; 244585; 534575; C; 1457; 100750; 24855; 5354;Dann geht das in etwa so: Code
Aber ist nicht ganz richtig, hab jetzt nur keine Zeit da weiter zu gucken.Ich bekomme den Fehler in der Main kannst du mir da weiterhelfen ich bin noch nicht so recht vertraut mit den verschiedenen Versionen.
Fehler: bereichsbasierte »for«-Schleifen sind im C++98-Modus nicht erlaubt
Also allgemein habe habe ich hier das Problem das er den auto Typ nicht haben will.

-
Als Compileroption noch std=c++0x angeben.
-
Ich kann ja mal die ersten Zeilen der Tabelle hier zeigen:
ARC_ID_DVSN;ARC_ID_CITY;SHARE_DVSN;ARC_ID_Ret_Flow
40121;43973;1;43973
40121;43974;1;43974
40121;43975;1;43975
40121;43976;1;43976
429438;44005;0,25;44005
45235;44005;0,25;44005
45236;44005;0,25;44005
45533;44005;0,25;44005
429438;44006;0,25;44006
45235;44006;0,25;44006
45236;44006;0,25;44006
45533;44006;0,25;44006
429438;44007;0,25;44007
45235;44007;0,25;44007
45236;44007;0,25;44007
45533;44007;0,25;44007
-
Vermutlich fehlt folgender Compiler-Switch: -std=c++11
-
Skym0sh0 schrieb:
Als Compileroption noch std=c++0x angeben.
Ich denke mal das du unter Windows programmierst oder? Wenn nicht kannst du mir da
weiter helfen also wie gesagt ich Programmier mit eclipse CDT unter Ubuntu.
-
Ok ich habs gefunden wie ich es in Eclipse einstelle. Code läuft fehlerfrei durch.
Danke.
Ich hab nur noch das Problem das er hier wohl die File gar nicht findet oder ich noch einen fehler habe.
std::ifstream file("./change_eu_utf.txt"); auto table = readTable(file);
-
So das funktioniert auch.
#include <iostream> #include <fstream> #include <vector> #include <string> std::vector<std::vector<std::string> > readTable(std::istream & is) { std::vector<std::vector<std::string> > table; while ( is ) { std::vector<std::string> line; for(std::size_t i = 0; i < 4; ++i) { std::string col; if ( std::getline(is, col, ';') ) { line.push_back(col); } } table.push_back(line); } return table; } int main() { std::ifstream file("./change_eu_utf.txt"); auto table = readTable(file); std::cout<<table.size(); // for(auto const& line : table) // { // std::cout<<std::endl<<"Zeile: "<<i++<<" "; // for(auto const& element : line) // { // // std::cout << element << '\t'; // } // //std::cout << std::endl; // } return 0x0; }Aber wenn ich mir jetzt die größe der tabell ausgeben lasse habe ich nur 6080 einträge aber es sollten 8105 sein.oder sehe ich das falsch?
-
Hallo Onubub,
Willkommen im C++-Forum!
Onubub schrieb:
So das funktioniert auch. ....
Nö - so funktioniert das nicht, da ich mir nicht vorstellen kann, dass Du direkt mit den Strings, die Ziffern enthalten weiter arbeiten kannst bzw. möchtest.
Wenn Du ints möchtest, so lese ints!
Und wenn ich das richtig sehe, so kann die dritte Spalte auch Fließkommazahlen enthalten und für diese wird das Komma als Dezimaltrenner benutzt (deutsche Schreibweise). Das gilt es alles zu beachten.
SeppJ hat schon erwähnt, dass es sinnvoll ist, die Werte einer Zeile zu einer Struktur zusammen zu fassen. Da sie allen Anschein nach auch noch von unterschiedlichen Typ sind, bietet sich einestructan.Anbei eine Skizze, die die von Dir gepostete Tabelle aus einer Datei einliest:
#include <iostream> #include <fstream> #include <vector> #include <limits> // numeric_limits struct EineStruct // eine struct, da ich nicht weiß was es ist halt 'EineStruct' { int id_dvsn; int id_city; double share_dvsn; // 3.Spalte ist eine Fließkommazahl int id_ret_flow; }; template< char C > // Helferlein zum Überlesen eines Zeichens 'C'; z.B.: ';' std::istream& Char( std::istream& in ) { char c; if( in >> c && c != C ) in.setstate( std::ios_base::failbit ); return in; } int main() { using namespace std; vector< EineStruct > table; // da kommt später die Tabelle rein, jede Zeile entspricht einem Element { // -- Tabelle lesen ifstream file("./change_eu_utf.txt"); if( !file.is_open() ) { cerr << "Fehler beim Oeffnen der Datei" << endl; return -2; } file.imbue( locale( "german" ) ); // auf ',' als Dezimaltrenner umschalten; ACHTUNG: 'german' kann in anderen IDEs anders heißen file.ignore( numeric_limits< streamsize >::max(), '\n' ); // erste Zeile überspringen for( EineStruct s; file >> s.id_dvsn >> Char<';'> >> s.id_city >> Char<';'> >> s.share_dvsn >> Char<';'> >> s.id_ret_flow; ) table.push_back( s ); if( !file.eof() ) // falls bis End-Of-File gelesen wurde, ist alles iO { cerr << "Fehler beim Lesen der Datei" << endl; return -1; } } cout << table.size() << " Eintraege gelesen" << endl; // usw. return 0; }Gruß
Werner
-
Werner Salomon schrieb:
Hallo Onubub,
Willkommen im C++-Forum!
Onubub schrieb:
So das funktioniert auch. ....
Nö - so funktioniert das nicht, da ich mir nicht vorstellen kann, dass Du direkt mit den Strings, die Ziffern enthalten weiter arbeiten kannst bzw. möchtest.
Wenn Du ints möchtest, so lese ints!
Und wenn ich das richtig sehe, so kann die dritte Spalte auch Fließkommazahlen enthalten und für diese wird das Komma als Dezimaltrenner benutzt (deutsche Schreibweise). Das gilt es alles zu beachten.
SeppJ hat schon erwähnt, dass es sinnvoll ist, die Werte einer Zeile zu einer Struktur zusammen zu fassen. Da sie allen Anschein nach auch noch von unterschiedlichen Typ sind, bietet sich einestructan.Anbei eine Skizze, die die von Dir gepostete Tabelle aus einer Datei einliest:
#include <iostream> #include <fstream> #include <vector> #include <limits> // numeric_limits struct EineStruct // eine struct, da ich nicht weiß was es ist halt 'EineStruct' { int id_dvsn; int id_city; double share_dvsn; // 3.Spalte ist eine Fließkommazahl int id_ret_flow; }; template< char C > // Helferlein zum Überlesen eines Zeichens 'C'; z.B.: ';' std::istream& Char( std::istream& in ) { char c; if( in >> c && c != C ) in.setstate( std::ios_base::failbit ); return in; } int main() { using namespace std; vector< EineStruct > table; // da kommt später die Tabelle rein, jede Zeile entspricht einem Element { // -- Tabelle lesen ifstream file("./change_eu_utf.txt"); if( !file.is_open() ) { cerr << "Fehler beim Oeffnen der Datei" << endl; return -2; } file.imbue( locale( "german" ) ); // auf ',' als Dezimaltrenner umschalten; ACHTUNG: 'german' kann in anderen IDEs anders heißen file.ignore( numeric_limits< streamsize >::max(), '\n' ); // erste Zeile überspringen for( EineStruct s; file >> s.id_dvsn >> Char<';'> >> s.id_city >> Char<';'> >> s.share_dvsn >> Char<';'> >> s.id_ret_flow; ) table.push_back( s ); if( !file.eof() ) // falls bis End-Of-File gelesen wurde, ist alles iO { cerr << "Fehler beim Lesen der Datei" << endl; return -1; } } cout << table.size() << " Eintraege gelesen" << endl; // usw. return 0; }Gruß
WernerDanke für die Hilfe.
Ja hast recht so wird es mich wohl weiter bringen, doch bekomm ich immer den fehler.terminate called after throwing an instance of 'std::runtime_error' what(): locale::facet::_S_create_c_locale name not validLiegt das an "german"? Ich kann die Tabellen aber auch so modifizieren das die Dezimalstellen mit '.' dargestellt werden.
-
Onubub schrieb:
Ja hast recht so wird es mich wohl weiter bringen, doch bekomm ich immer den fehler.
terminate called after throwing an instance of 'std::runtime_error' what(): locale::facet::_S_create_c_locale name not validLiegt das an "german"? Ich kann die Tabellen aber auch so modifizieren das die Dezimalstellen mit '.' dargestellt werden.
Ja - steht ja da: "locale name not valid"
Versuche mal "deu" (das ist nach ISO 639-2/3) - ansonsten verrate uns Deine Entwicklungsumgebung und dann weiß hier bestimmt jemand, was da einzustellen ist.Wenn Du die Datei auf '.' umstellen kannst, so geht das natürlich auch. Lasse in diesem Fall die Zeile 33 einfach weg.
Gruß
Werner
-
PS.:
.. unter Linux-Systemen soll man die locale-Namen mit
locale -aherausfinden können.
evt. geht auch "de_DE" oder "de_DE.UTF-8"
-
Ja klappt! Vielen Dank.