Dateiinhalte richtig formatieren und auslesen



  • Hallo liebe Comm,

    ich möchte gerne, wie es im Titel schon steht, eine Datei haben, die ich gezielt auslesen kann. Angenommen die Datei sieht folgendermaßen aus:

    Item 1:
    Holzschild
    Kosten 300 Gold
    10 Verteidigung
    
    Item 2:
    Eisenschild
    Kosten 700 Gold
    15 Verteidigung
    

    Stellt euch vor, es würden noch viele mehr Items gleich aufgebaut folgen.

    Wie mache ich nun, dass das Programm alles ausliest und dabei die Items büdelt und so weiß, was zu was gehört. Außerdem muss er irgendwie kontrollieren, ob auch alles korrekt angegeben ist, sodass, wenn z.b. die Datei beschädigt ist und der Inhalt nicht richtig ist, sagen wir, bei Item 2 fehlt das "Gold" Feld, er das auch merkt.
    Da muss ich doch die Datei irgendwie formatieren, oder?

    Ich bitte um eure Ratschläge und vielleicht hat sowas ja schonmal jemand gemacht.

    Danke im Voraus.



  • ich würde mir eine grammatik bauen die sowas alles vorsieht, dazu kann man sich dann einen parser konfigurieren (z.B. boost::spirit, google ruhig mal) und den lässt man das auch noch verarbeiten

    soviel zur theorie, praktisch wird es da aber sicher das ein oder andere problem geben



  • Wäre eine Möglichkeit, kommt drauf an wie komplex die Datei ist.
    Du könntest die Datei einfach zeilenweise einlesen. Dann die einzelnen Zeilen überprüfen ob es ein neues Item ist, ansonsten einfach dem letzten Item zuordnen (und überprüfen ob die Zeile korrekt ist oder was fehlt).



  • Hallo Kralo9,

    mache Dir für jedes Attribut eine kleine struct , und füge einen Streaming-Operator hinzu, so daß Du eine Instanz dieser struct Lesen und ggf. auch schreiben kannst. Dort kannst Du dann auch abfragen, ob die erwarteten Schlüsselwörter in der Datei stehen.
    Daneben ist es sinnvoll eine kleine Helferstruktur (hier check s.u) zu bauen, die bestimmte Worte überprüft. Alles zusammen etwa so:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <algorithm> // std::find
    #include <vector>
    
    struct Schild
    {
        enum Art { Holz=0, Eisen, Titan };
        Art art;
    };
    std::istream& operator>>( std::istream& in, Schild& schild )
    {
        static std::string const arten[] = {"Holzschild", "Eisenschild", "Titanschild"};
        std::string s;
        int idx;
        if( in >> s && (idx = std::find( arten, arten+sizeof(arten)/sizeof(*arten), s ) - arten) >= sizeof(arten)/sizeof(*arten) )
            in.setstate( std::ios_base::failbit ); // Lesefehler, eingelesener Schildtyp ist unbekannt
        else if( in ) // alles ok
            schild.art = Schild::Art( idx );
        return in;
    }
    
    struct check
    {
        check( const std::string& key ) : key_( key ) {}
        std::string key_;
    };
    std::istream& operator>>( std::istream& in, check c )
    {
        std::string w;
        if( in >> w && w != c.key_ )
            in.setstate( std::ios_base::failbit ); // das erwartet Wort 'wort' folgte nicht
        return in;
    }
    
    struct Preis
    {
        int wertInGold_;
    };
    std::istream& operator>>( std::istream& in, Preis& preis )
    {
        return in >> preis.wertInGold_ >> check("Gold");
    }
    
    class Item
    {
    public:
        friend std::istream& operator>>( std::istream& in, Item& item );
    private:
        int nr_;
        Schild schild_;
        Preis preis_;
        int staerke_;
    };
    
    // --   ein Item einlesen
    std::istream& operator>>( std::istream& in, Item& item )
    {
        in >> check("Item") >> item.nr_ >> check(":");
        in >> item.schild_;
        in >> check("Kosten") >> item.preis_;
        in >> item.staerke_ >> check("Verteidigung");
        return in;
    }
    
    int main()
    {
        using namespace std;
        vector< Item> items;
        ifstream datei("input.txt");
        if( !datei.is_open() )
        {
            cerr << "Fehler beim Oeffnen der Datei" << endl;
            return -2;
        }
        for( Item i; datei >> i; )
            items.push_back( i );
        cout << items.size() << " Eintraege gelesen" << endl;
        return 0;
    }
    

    Gruß
    Werner


Anmelden zum Antworten