[solved]Formatierte Datei lesen?



  • Hallo, wie kann ich eine Formatierte Datei wie z.B.

    Erstes Element|Zweites Element|Drittes Element|1.66|6.4|6
    

    leicht einlesen, wobei die Zahlen auch in entsprechende double oder int Variablen gespeichert werden?

    Kann man das irgendwie über fstream.read() lösen?? Weil so wirklich komme ich da grad nicht auf des Rätsels Lösung... 😞 Ich nehme auch gerne ein Tutorial oder ähnliches 🙂

    Danke schon mal im voraus.
    Blackskyliner



  • Ich lenke Deine Aufmerksamkeit mal gerne auf std::string::find_first_of()
    http://www.cppreference.com/wiki/string/find_first_of
    Damit lassen sich solche strings super zerlegen :).

    edit:
    Alternativ Konsolenprogramm mit wxWidgets:

    wxStringTokenizer tokens(theString, "|");
    wxString token1 = tokens.GetNextToken();
    wxString token2 = tokens.GetNextToken();
    

    rya.



  • Wenn du allerdings schon einen Stream hast, wäre getline noch besser geeignet, dort kann man optional ein Trennzeichen als 3. Parameter angeben.
    Das könnte dann so aussehen:

    fstream file;
    string s;
    
    while(std::getline(file, s, '|'))
        ...;
    


  • Danke ipsec zusammen mit einem vector und meiner über stringbuffer realisierten convert funktion für string to int, double, etc. fluppt das super, ich danke dir. 🙂

    Das andere ist auch interessant, jedoch muss die Lösung ohne wx auskommen...



  • Hab grade gemerkt, dass er mir jedoch bei diese Lösung hier:

    template<class T>
    T convert(string s)
    {
    	std::stringstream stream(s);
    	T temp;
    
    	stream >> temp;
    	return temp;
    }
    void loadText(){
    	string singleResult;
    	vector<string> results;
    
    	tStud einStudent;
    	fstream f("test2.txt", ios::in);
    	while(f.good()){
    		while(std::getline(f, singleResult, '|')) 
    			results.push_back(singleResult);
    
    		einStudent.name = results[0];
    		einStudent.matrikel = convert<int>(results[1]);
    		einStudent.beleg = convert<int>(results[2]);
    		einStudent.pruef = convert<int>(results[3]);
    
    		cout << endl;
    		// Ausgeben der Daten.
    		cout << einStudent.name << endl;
    		cout << einStudent.matrikel << endl;
    		cout << einStudent.beleg << endl;
    		cout << einStudent.pruef << endl;
    	}
    	f.close();
    }
    

    Die Datei sieht so hier z.B: aus:

    asd|1|2|3
    dsa|4|5|6
    qwe|6|7|8
    fff|444|555|666
    rrr|457|234|32
    

    Jetzt da entsprechend mir alle in den Vector pushed... wie kann ich das ganze jetzt auch noch Zeilenweise limitieren?



  • std::string line;
    std::ifstream in;
    
    while(std::getline(in, line)) {
      std::istringstream parser(line);
      std::string token;
    
      while(std::getline(parser, token, '|')) {
        // Token verarbeiten
      }
    }
    

    std::istringstream befindet sich im Header <sstream>.



  • Ich danke dir seldon 👍



  • Blackskyliner schrieb:

    ..., wobei die Zahlen auch in entsprechende double oder int Variablen gespeichert werden?

    Hallo Blackskyliner,

    wenn Du Zahlen willst, so solltest Du auch Zahlen lesen. Oder allgemeiner: lese das, was Du nachher haben willst.

    Blackskyliner schrieb:

    Kann man das irgendwie über fstream.read() lösen??

    Nein, dass ist u.U. die schlechteste aller denkbaren Lösungen, denn die Methode 'read' liest unformatiert. Genau wie getline; wobei getline hier Sinn macht, um den ersten Namen bis zum '|'-Zeichen zu lesen, wie ipsec schon erwähnt hat.

    .. ach so, und wenn man Studenten haben will, so sollte man Studenten lesen. Dazu baut man sich für die Struktur seiner Wahl:

    struct tStud
    {
        std::string name;
        int matrikel, beleg, pruef;
    };
    

    Streaming-operatoren für das Einlesen und Ausgeben.

    std::istream& operator>>( std::istream& in, tStud& stud );
    std::ostream& operator<<( std::ostream& out, const tStud& stud );
    

    Implementierung kommt später (s.u.)

    So ausgerüstet lassen sich jetzt die Studenten aus der Datei lesen:

    int main()
    {
        using namespace std;
        vector< tStud > studenten;
        ifstream f( "test2.txt" );
        for( tStud student; f >> student; )
            studenten.push_back( student );
        if( f.eof() )   // bis 'End Of File' gelesen -> dann ist alles iO.
        {
            // alles richtig gelesen; hier weiter machen
            copy( studenten.begin(), studenten.end(), ostream_iterator< tStud >( cout, "\n" ) );
            cout << endl;
        }
        return 0;
    }
    

    .. jetzt 'nur' noch die Implementierung, um einen(!) Studenten zu lesen und zu schreiben. Den Namen mit getline(...,'|') lesen und die int als int lesen. Bleiben nur noch die (lästigen) '|'-Zeichen zwischen den Zahlen. Ein Leerzeichen wäre hier die bessere Wahl gewesen.

    std::istream& pipe( std::istream& in ) // liest das '|'-Zeichen; falls keines kommt, geht der Stream in den Fehlerzustand
    {
        char c;
        if( in >> c && c != '|' )
            in.setstate( std::ios_base::failbit );
        return in;
    }
    std::istream& operator>>( std::istream& in, tStud& stud ) // Student einlesen
    {
        // Format z.B.: "dsa|4|5|6"
        return getline( in >> std::ws, stud.name, '|' ) >> stud.matrikel >> pipe >> stud.beleg >> pipe >> stud.pruef;
    }
    std::ostream& operator<<( std::ostream& out, const tStud& stud ) // Student ausgeben
    {
        const char pipe = '|';
        return out << stud.name << pipe << stud.matrikel << pipe << stud.beleg << pipe << stud.pruef;
    }
    

    Die notwendigen includes sind:

    #include <algorithm> // copy
    #include <fstream>
    #include <iostream>
    #include <iterator> // ostream_iterator
    #include <string>
    #include <vector>
    

    Gruß
    Werner


Anmelden zum Antworten