Problem mit Vektoren und Auslesen einer Textdatei
-
Ich habe mir grade eine Funktion geschrieben, um mir Datei aus einer Textdatei auszulesen. Diese sieht so aus:
\tx \ty 1\t432\t234 2\t424\t798Das '\t' soll einen Tab-darstellen.
Ich lese die File so aus:
ifstream xyCoordinatesIfS; xyCoordinatesIfS.open(path,ios::in); vector <string> lineT (100); int i = 1; while ( getline(xyCoordinatesIfS,lineT[i], '\t')) { if (i > 3 && i % 2 == 0 ) { cout << lineT[i] << "\t" << i << endl; //Die hier ist gemeint } i++; } xyCoordinatesIfS.close(); lineT.shrink_to_fit(); int test = lineT.size(); cout << test << endl;Bie der Anzeige in der Konsole bekomme ich immer nur den x-Wert, obwole eig. auch der y-Wert, getrennt von einem \n enthalten sein müsse. Dies weiss ich, weil wenn man das modulo entfernt, kann man dies sehen.
Die Ausgabe mit modulo lautet bei der obigen bsp. Datei:432 4 424 6ohne Modulo:
432 4 234 2 5 424 6 798Kann es nun sein, das das 234 und 798 aus der Wert 6,5 oder so liegt?
(ich weiss gibt es nicht, aber ich hoffe ihr wisst, was mich meine)So meine zweite Frage ist , wie man den Vektor auf seine besetzten Elemente verkleinen kann. Also bei der obigen Datei 6 anstatt der 100, die ich bei der Initialisierung angegeben habe, denn ohne geht es nicht.
IDE ist MS VC++ Express auf Win7
Ich hoffe ihr könnt mir weiterhelfen.
-
Problem gelöst!!!
-
Hallo Crysis_02,
ich schließe aus der von Dir beschriebenen Ausgabe, dass die Datei so aussieht:
x y 432 234 424 798also ohne die Nummerierung am Anfang der Zeile.
Wobei als Trennzeichen der Tabulator benutzt wird, was aber für das Einlesen irrelevant ist.
Ich unterstelle weiter, dass Du an den Zahlen (Koordinaten) interessiert bist, und diese nicht als Strings brauchst. Dann wäre das eine brauchbare Lösung:#include <iostream> #include <fstream> #include <limits> // numeric_limits #include <vector> struct XY // diese Struktur nimmt eine Koordinate auf { int x_, y_; }; int main() { using namespace std; vector< XY > coordinates; // leeren(!) Container anlegen const char* path="input.txt"; ifstream xyCoordinatesIfS( path ); // ios::in ist überflüssig, wg. (I)fstream if( !xyCoordinatesIfS.is_open() ) { cerr << "Fehler beim Oeffnen von " << path << endl; return -2; } xyCoordinatesIfS.ignore( numeric_limits< streamsize >::max(), '\n' ); // erste Zeile überlesen for( XY c; xyCoordinatesIfS >> c.x_ >> c.y_; ) // Koordinaten als ZAHLEN lesen coordinates.push_back( c ); // push_back fügt ein Element hinzu if( xyCoordinatesIfS.eof() ) // bis EOF, dann ok { cout << "Ok; " << coordinates.size() << " Koordinaten gelesen" << endl; } else cerr << "Lesefehler" << endl; return 0; }Du brauchst den Vektor auch nicht verkleinern - schon gar nicht mit shrink_to_fit() - das macht was anderes. std::vector ist eine dynamische Datenstruktur, die z.B. mit push_back sukzessive vergrößert wird. Die Methode size() gibt Dir dann die Anzahl der im vector enthaltenen Elemente zurück.
Um das Einlesen etwas eleganter zu gestalten, kannst Du noch für die struct XY einen Streamingoperator hinzufügen:
std::istream& operator>>( std::istream& in, XY& c ) { return in >> c.x_ >> c.y_; }dann vereinfacht sich Zeile 23 zu
for( XY c; xyCoordinatesIfS >> c; )Gruß
Werner
-
Nee. Die Datei hat vorne noch die Zahlen.
X Y 1 287 454 2 587 789zur Zeit habe ich es so gelöst.
vector <int> solarCoordinateTransformation::GetXYCoordinates(string path) { ifstream xyCoordinatesIfS; xyCoordinatesIfS.open(path,ios::in); vector <string> lineV (10); int b = 0; if (xyCoordinatesIfS.is_open()) { //Hier mit den Limits? while(!xyCoordinatesIfS.eof()) { lineV.resize(b+1); xyCoordinatesIfS >> lineV[b]; b++; } } xyCoordinatesIfS.close(); int test = lineV.size(); int VectorSize = lineV.size()-3; int VectorS = VectorSize/3*2; vector <string> line (VectorS); int e = 0; int f = 1; for (int d = 0; d < lineV.size() -1; d++) { if (d > 2) { if (f != 3) { line[e] = lineV[d]; e++; f++; } else { f = 1; } } } vector <int> returnValue (line.size()); for (int h = 0; h < line.size(); h++) { returnValue[h] = atoi(line[h].c_str()); } return returnValue; }Jedoch finde ich das mit den "limits" sehr cool. Wo muss ich dies jedoch in meinem code hinschreiben? Hab mal oben nen Kommentar reingemacht, wo ich denke, wo es hinkommt

Ich weiss es sieht nicht so gut aus, aber er funktioniert bei einer gewissen Ordnerstrunktur, die ich überall habe. Das Programm ist ja nur für mich ^^
-
Hallo Crysis_02,
Crysis_02 schrieb:
Nee. Die Datei hat vorne noch die Zahlen.
X Y 1 287 454 2 587 789Dann erweitere die Zeile 23 in meinem ersten Posting zu:
int nr; for( XY c; xyCoordinatesIfS >> nr >> c.x_ >> c.y_; ) // Koordinaten als ZAHLEN lesenCrysis_02 schrieb:
zur Zeit habe ich es so gelöst. ...
Jedoch finde ich das mit den "limits" sehr cool. Wo muss ich dies jedoch in meinem code hinschreiben? Hab mal oben nen Kommentar reingemacht, wo ich denke, wo es hinkommt

ja genau da, Du musst natürlich den Code dahinter entsprechend anpassen. Suche hier im Forum mal nach skipline.
Crysis_02 schrieb:
Ich weiss es sieht nicht so gut aus, aber er funktioniert bei einer gewissen Ordnerstrunktur, die ich überall habe. Das Programm ist ja nur für mich ^^
Nein, es funktioniert nicht. Und zwar genau dann nicht, wenn hinter der letzten Zahl kein Zeilenende, sondern bereits ein EOF steht. Probier's aus.
Ursache dafür ist zum einen der sehr verbreitete Fehler auf EOF statt auf Fail abzufragen und zum anderen die wahrlich kryptische Methode, wie Du die Strings weiter verarbeitest. Du benötigst drei Container für das Einlesen - nötig wäre maximal einer.
Ganz einfache Regel: lese das was Du brauchst - nur das und mit dem richtigen Typ (was sonst).vector <int> solarCoordinateTransformation::GetXYCoordinates(string path) { ifstream xyCoordinatesIfS; xyCoordinatesIfS.open(path,ios::in); // ios::in ist überflüssig, das ist bereits ein i(nput)fstream vector <string> lineV (10); // diese Vorbelegung ist überflüssig und fehlerträchtig int b = 0; if (xyCoordinatesIfS.is_open()) { //Hier mit den Limits? while(!xyCoordinatesIfS.eof()) { // NACH(!) dem Lesen immer auf !fail() abfragen -> endlos-Loop bei Lesefehler und undefiniertes Ende lineV.resize(b+1); // Oje - Performance-loch xyCoordinatesIfS >> lineV[b]; // Du brauchst Zahlen, warum dann Texte lesen? b++; } } xyCoordinatesIfS.close(); // überflüssig int test = lineV.size(); int VectorSize = lineV.size()-3; int VectorS = VectorSize/3*2; // wenn hier jetzt der letzte String fehlt (s.o.), ist 'VectorS' um 1 zu klein -> Programmfehler // der Code der hier kommt, wäre überflüssig, wenn Du gleich nur das liest, was benötigt wird // das würde auch das Code-Verständnis wesentlich erhöhen vector <string> line (VectorS); int e = 0; int f = 1; for (int d = 0; d < lineV.size() -1; d++) { if (d > 2) { if (f != 3) { line[e] = lineV[d]; e++; // gewöhne Dir prefix statt postfix an. f++; } else { f = 1; } } } vector <int> returnValue (line.size()); for (int h = 0; h < line.size(); h++) { returnValue[h] = atoi(line[h].c_str()); } return returnValue; }Du fährst sicher mit mit einer Struktur XY besser, als die Koordinaten X und Y hinter einander in einen vector<int> zu schreiben.
Und GetXYCoordinates macht als Methode keinen Sinn, da sie weder lesend noch schreibend auf irgendwelche Klassenmeber zugreift. Mache daraus besser eine Funktion.Crysis_02 schrieb:
Das Programm ist ja nur für mich ^^
Trotzdem sollte es korrekt sein und kürzere Programme lassen sich auch einfacher lesen - auch von einem selbst.
Gruß
Werner
-
Werner Salomon schrieb:
Suche hier im Forum mal nach skipline.
Es gibt so viele nette Helfer von dir, aber ich habe leider keinen Überblick.
Gibt es irgendwo Werners IO-Suite, in der sie alle zentral aufgelistet sind?
-
Danke. der Code ist echt fürzer und besser zu verstehen ^^
Jedoch gind das mit den limits nicht. Hab jetzt einfach 100 eingegeben. Reicht auf jeden Fall.
Sieht jetzt so aus:
vector <XY> solarCoordinateTransformation::GetXYCoordinates(string path) { ifstream xyCoordinates; vector <XY> coordinates; int nr; xyCoordinates.open(path); if(xyCoordinates.is_open()) { xyCoordinates.ignore(100 /*numeric_limits< streamsize >::max()*/, '\n' ); // erste Zeile überlesen for( XY c; xyCoordinates >> nr >> c.x >> c.y; ) // Koordinaten als ZAHLEN lesen coordinates.push_back( c ); // push_back fügt ein Element hinzu //if( xyCoordinates.eof() ) // bis EOF, dann ok //{ // cout << "Ok; " << coordinates.size() << " Koordinaten gelesen" << endl; //} //else { // cerr << "Lesefehler" << endl; //} } return coordinates; }
-
Crysis_02 schrieb:
Jedoch ging das mit den limits nicht.
Hallo Crysis_02,
.. mögliche Ursachen: Du hast ein
#include <limits>vergesen, oder Du arbeitest mit dem Visual Studio und hast oben ein#include <windows.h>oder#include <stdafx.h>stehen. Im letzteren Fall füge als erste Zeile instdafx.hoder in Deinem Sourcefile vorwindows.h, falls Du keinstdafx.hbenutzt, ein #define NOMINMAX ein.Gruß
Werner
-
Ja benutze die windows.h
Werde es morge probieren. Danke.
-
super jetzt geht alles
