ifstream an den Dateianfang zurücksetzen?



  • out schrieb:

    Und du darfst einen ifstream ruhig mehr als 1x erstellen.

    An anderer Stelle im Programm nutze ich einen zweiten ifstream um die Zeilen in der Datei zu zählen - wollte das ursprünglich alles mit einem ifstream machen (den ich immer wieder zurücksetze), aber eben weil csvread immer wieder dort anfängt wo es beim letzten Aufruf geendet hat, hab ich einen zweiten ifstream eingeführt.

    Das Problem hier ist aber, dass ich gerne hätte dass ich eine Datei auswählen kann und mir die Spalte in der "e" steht anzeigen lassen kann, dann möchte ich eine andere Datei auswählen und mir anzeigen lassen in welcher Spalte in dieser Datei ein "e" steht - wobei aber die Hauptschleife neu gestartet wird, d.h. ich wüsste nicht wie es helfen würde hier noch mehr ifstreams zu erstellen.

    Oder versteh ich einfach nicht was du mir sagen wolltest? 😉



  • Das Problem liegt bestimmt viel tiefer als du denkst. Mal ganz von vorne: Du willst einfach eine csv-Datei auslesen? Nicht mehr und nich weniger. Dann gibt mal ein Paar Zeilen der Datei her und beschreib die Datei ein bissel.



  • out schrieb:

    Fragnix schrieb:

    volkard schrieb:

    Warum ist der ifstream eine globale Variable?
    Denke, der sollte lokal sein.

    Hi,

    hatte den ifstream ursprünglich als lokale variable, direkt in der Funktion getcolumns definiert, das Problem hat da aber auch schon bestanden. Hab das dann in die Hauptschleife verlegt, weil ich in der Funktion nur das zählen der Spalten lassen wollte.

    Wenn du den genauen Aufbau deiner csv-Datei sagen würdest, könnte man dir wirklich helfen. 😉

    also die .csv schaut z.B. so aus:

    row;x1;x2;x3;e;RHS
    r1;1;2;3;<;100
    r2;3;2;1;>;1
    zf;80;;90;;

    Die erste Reihe und die erste Spalte sind einfach nur Beschriftungen, der Rest sind (Un)gleichungen die ein lineares Programm darstellen und eingelesen werden sollen. Im Moment bin ich eben erst soweit, dass mein Code einmal die Anzahl der Zeilen und Spalten des Problems herausfinden soll.



  • Ich hab mir das Leben mal ein bisschen einfacher gemacht, indem ich leere Zellen mit 0 oder = augefüllt habe, dann lässt sich das relativ einfach parsen:

    CSV-Datei:
    `row;x1;x2;x3;e;RHS

    r1;1;2;3;<;100

    r2;3;2;1;>;1

    zf;80;0;90;=;0`

    #include <fstream>
    #include <iostream>
    #include <limits>
    #include <string>
    #include <vector> 
    using namespace std;
    
    struct record
    {
    	string beschriftung;
    	int x1;
    	int x2;
    	int x3;
    	char e;
    	int rhs;
    };
    
    template<unsigned ANZ>
    istream& skip_line( istream& in )
    {
    	for(unsigned i=0; i!=ANZ; ++i)
    		 in.ignore( numeric_limits<streamsize>::max(), '\n' );
    	return in;
    }
    
    template<char C>
    istream& skip_char( istream& in )
    {
        char c;
        if( in >> c && c != C )
            in.setstate( std::ios_base::failbit );
        return in;
    }
    
    istream& operator>>( istream& in, record& r )
    {
    	getline( in>>std::ws, r.beschriftung, ';' );
    	in >> r.x1  >> skip_char<';'>;
    	in >> r.x2  >> skip_char<';'>;
    	in >> r.x3  >> skip_char<';'>;
    	in >> r.e   >> skip_char<';'>;
    	in >> r.rhs;
    	return in;
    }
    
    int main()
    {
    	ifstream file( "test.csv" );
    	vector<record> zeilen;
    
    	file >> skip_line<1>;
    	for(record r; file>>r; zeilen.push_back(r));
    
    	// Fertig
    }
    

    Und was sagst dazu. Schon viel besser oder?



  • Hi,

    ja sieht zugegebenermaßen um einiges besser aus, auch wenn ich nicht alles ganz verstehe;-) Auf jeden Fall vielen Dank für die Hilfe! Bei mir müsste das ganze aber für eine variable Anzahl an Spalten/Zeilen funktionieren, und das ist bei deinem Code ja nicht der Fall?

    Und um noch einmal zurück zu meiner ursprünglichen Frage zu kommen: Wieso funktioniert denn

    csvread.seekg(0,ios::beg)
    

    oder noch einfacher

    csvread.clear
    

    denn eigentlich nicht um den ifstream zurückzusetzen und beim nächsten Durchlauf wieder am Anfang der Datei anzufangen?? Mag sein dass das eine dumme Frage ist, aber nach allem was ich zu dem Thema im Internet gefunden habe, müsste das doch eigentlich relativ einfach gehen...

    Jedenfalls nocheinmal vielen Dank für deine Hilfe!



  • Fragnix schrieb:

    Bei mir müsste das ganze aber für eine variable Anzahl an Spalten/Zeilen funktionieren, und das ist bei deinem Code ja nicht der Fall?

    Also variable Anzahl an Zeilen funktioniert natürlich schon. Bei einer variablen Anzahl an Spalten... da hast du doch immer ein Problem... die Datentypen müssen ja fest sein. Dein Programm muss ja wissen, welche Spalte welchen Datentypen hat. Es sein denn, du meinst eine variable Anzahl an unbekannten, dann ist klar, dass alle denselben Typen haben.

    Fragnix schrieb:

    Und um noch einmal zurück zu meiner ursprünglichen Frage zu kommen: Wieso funktioniert denn

    csvread.seekg(0,ios::beg)
    

    oder noch einfacher

    csvread.clear
    

    denn eigentlich nicht um den ifstream zurückzusetzen und beim nächsten Durchlauf wieder am Anfang der Datei anzufangen??

    Eigentlich geht das schon. Du ließt etwas, rufst dann vorsichtshalber file.clear() auf, und danach machst du file.seekg(0,std::ios::beg). Das geht schon. Wenn es bei dir nicht geht, liegt der Fehler wo anders.



  • out schrieb:

    Fragnix schrieb:

    Bei mir müsste das ganze aber für eine variable Anzahl an Spalten/Zeilen funktionieren, und das ist bei deinem Code ja nicht der Fall?

    Also variable Anzahl an Zeilen funktioniert natürlich schon. Bei einer variablen Anzahl an Spalten... da hast du doch immer ein Problem... die Datentypen müssen ja fest sein. Dein Programm muss ja wissen, welche Spalte welchen Datentypen hat. Es sein denn, du meinst eine variable Anzahl an unbekannten, dann ist klar, dass alle denselben Typen haben.

    Ja, hab eine variable Anzahl an unbekannten gemeint.

    out schrieb:

    Fragnix schrieb:

    Und um noch einmal zurück zu meiner ursprünglichen Frage zu kommen: Wieso funktioniert denn

    csvread.seekg(0,ios::beg)
    

    oder noch einfacher

    csvread.clear
    

    denn eigentlich nicht um den ifstream zurückzusetzen und beim nächsten Durchlauf wieder am Anfang der Datei anzufangen??

    Eigentlich geht das schon. Du ließt etwas, rufst dann vorsichtshalber file.clear() auf, und danach machst du file.seekg(0,std::ios::beg). Das geht schon. Wenn es bei dir nicht geht, liegt der Fehler wo anders.

    Hmmm....gut dann wird ich mein glück wohl noch einmal mit dieser Methode versuchen... Nochmals danke!



  • Kannst ja nochmal deinen aktuellen Quellcode zeigen.



  • Der Quellcode ist immer noch genauso wie im Original-Posting. Ich konnte mittlerweile ein wenig eingrenzen wo das Problem zu liegen scheint - weiß aber nicht ob das so viel weiterhilft: wenn die Funktion getcolumns das erste mal durchlaufen wird dann wird korrekterweise die sechste Spalte als die mit dem "e" angegeben, wenn ich die Funktion dann noch einmal auslöse füllt sich die Variable "Ecol" aber überhaupt nicht mehr bzw. wird die kurze if-Schleife dann einfach nicht mehr ausgelöst, nachdem "Ecol" in Zeile 18 gecleared wird. 😕



  • Die Funktion getcolumns verstehe ich nicht ganz, musst du mir mal erklären, was sie genau machen soll? Willst du damit alle Spaltenüberschrichten erhalten?

    if (colx[i]=="e")
             {
    
                       Ecol<<i-1;
    
             }
    

    Und was soll das sein? Was macht Ecol<<i-1 ?



  • Also innerhalb der for-Schleife soll das Programm durch

    getline(csvread,cols,';')
    

    von Spaltenüberschrift zu Spaltenüberschrift springen, die dann immer in

    colx[i]
    

    geschrieben wir. Wenn

    colx[i]=="e"
    

    dann soll Ecol den Wert von i-1 annehmen, dass ergibt nämlich die Anzahl der Spalten die auf der linken Seite der Gleichungen stehen.

    Ich weiß, das ist sicher ganz furchtbarer Code, aber ich versuch das halt mit den Mitteln und Verständnis eines Anfängers 😉



  • Meinst du das?

    string cols, colx[1000];
    ifstream csvread("test.csv");
    
    void getcolumns()
    {
         for(int i=0; i!=1000; ++i)
         {
    		 getline( csvread, cols,';' );
    
    		 if( !csvread )
    			 break;
    
             if( cols=="e" )
             {
    			 colx[i] = i-1+48; // +48 --> ASCII Korrektur
             }
    		 else
    		 {
    			 const size_t ende = cols.find('\n');
    
    			 if( ende!=string::npos )
    			 {
    				 cols = cols.substr(0, cols.size()-ende);
    			 }
    			 colx[i] = cols;
    
    			 if( ende!=string::npos )
    				 break;
    		 }
         }
    }
    


  • Hi,

    hab jetzt eine Lösung gefunden und die war natürlich so einfach, dass es erst recht ärgerlich ist 🙄 Am Ende der getcolumns Funktion hat einfach nur

    csvread.close()
    

    gefehlt.

    Jetzt funktioniert seekg(ios::beg) problemlos zum zurücksetzen.

    Jedenfalls vielenvielen Dank für deine Hilfe!...wird mir deinen Code auch ausprobieren, der nämlich wieder besser aus;-)



  • Fragnix schrieb:

    Am Ende der getcolumns Funktion hat einfach nur

    csvread.close()
    

    gefehlt.

    Deswegen erstellt man files auch nicht als globale Objekte.

    void getcolumns()
    {
         ifstream csvread("test.csv");
    
         for(int i=0; i!=1000; ++i)
               ...
    
         // automatisches csvread.close();
    }
    

Anmelden zum Antworten