Textdatei einlesen und zeilenweise in Vektoren speichern



  • Hey Leute,

    ich versuche mittlerweile seit einigen Tagen mehrere Textdateien(je Textdatei eine Funktion) einzulesen und die einzelnen Zeilen in Vektoren zu speichern.

    Bei einer ist mir dies bereits gelungen, da in dieser nur eine relevante Zeile ist.
    Das habe ich nach folgendem Muster gemacht:

    [/code]

    vector<double> stoffdaten_wasser(){
        ifstream stoffdaten_wasser("C:/Users/maxko/Documents/Code Blocks/Texdokument/Textdokument einlesen/stoffdaten_wasser.txt"); //"Ansprechen" der Datei
        string zeile;   //Variable zum Speichern von jeweils einer Zeile
        vector<double> dichte_viskositaet_var; //Vektorvariable zum Speichern der Daten
    //Schleife zum Einlesen der Zeilen
        while(getline(stoffdaten_wasser,zeile)){
           //Kommentarzeilen werden nicht ausgelesen
           if(zeile.find("//")==0)
           continue;
           else{
           //Zeilenstream wird in einzelnen Streams (durch Leerzeichen getrennt) eingelesen
           stringstream zeilenpuffer(zeile);
           //Initialisierung der Speichervariablen
           double dichte;
           double viskositaet;
           //den Speichervariablen werden die Werte aus der Textdatei zugewiesen
           zeilenpuffer>>dichte>>viskositaet;
           //die Stoffdaten werden in den Vektor gespeichert
           dichte_viskositaet_var.push_back(dichte);
           dichte_viskositaet_var.push_back(viskositaet);
        }
        }
        return dichte_viskositaet_var;
    }
    

    Nun habe ich eine Textdatei mit variabel vielen relevanten Zeilen. Diese sieht so aus:

    //Rohrleitungsdaten der Verbraucher
    ////////////////////////////////////////////////////////////////////////
    //Wenn die Daten eines Verbrauchers verändert werden sollen, bzw. ein neuer Verbraucher hinzugefügt werden soll,
    //so müssen die betreffenden Daten jeweils an der gleichen Stelle (1 bis n) eingetragen werden
    ////////////////////////////////////////////////////////////////////////
    //Durchfluss [l/s]; Verbraucher von 1 bis n
    110 60 30 68 75 88
    //Druckdifferenz [bar]; Verbraucher von 1 bis n
    0.25 0.2 0.1 0.15 0.21 0.3
    //Länge Rorhleitung [m]; Verbraucher von 1 bis n
    60 25 40 35 20 30
    //Rohrrauhigkeit [mm]; Verbraucher von 1 bis n
    0.4 0.4 0.4 0.4 0.4 0.4

    wie in der ersten Funktion, leiten "//" quasi Kommentarzeilen ein. Die Textdatei soll so gestaltet sein, dass ein Benutzer des Programms, der den Code nicht kennt, in dieser Parameter verändern kann, ohne dass der Code dadurch nicht mehr funktioniert.

    Mein Problem ist nun dieses Datei so einzulesen, dass meine Funktion die Parameter als Vektormatrix ausspuckt.

    Ich hoffe mein Problem ist verständlich geworden und ich entschuldige mich schonmal im voraus für die schwammigen Formulierungen, ich bin neu hier.

    Vielen Dank schonmal

    Gruß Max



  • Wenn du deinen Code in passende Codetags packst, schaut sich das vielleicht jemand an. So eher nicht.



  • was meinst du mit passenden Codetags? Das ist meine erste Forumerfahrung..



  • Markiere Deinen Code/Quelltext und drücke dann unterhalb des Edit-Fensters auf den Button 'C++', dann sieht das ganze etwa so aus:

    #include <iostream>
    
    using namespace std;
    
    int main()
    {
       cout << "Bla";
    }
    

    und dann ist es auch leserlich. Sicherheitshalber drückst Du dann erst auf 'Vorschau' und kontrollierst das Ganze, wenn alles gut aussieht, dann auf 'Abschicken'.



  • okay super. vielen dank schonmal für die info! das sieht schon viel besser aus



  • Sind die Anzahl der Spalten denn fix?
    Variabel kannst du einfach folgenden Datentyp zum Einlesen aller Werte benutzen

    vector<vector<double>>
    

    Je Zeile erzeugst du dir ein

    vector<double> row_values;
    

    liest die Werte ein und fügst sie dem Vector mittels push_back hinzu - und nach jeder Zeile fügst du dann diesen Vector (wieder per push_back) zu dem Gesamtvector hinzu.

    Wenn fix dann kannst du stattdessen ein array<double, X> benutzen:

    vector<array<double, X>>
    


  • Ah, deutlich lesbarer.

    Mehrere Kommentare:
    1. bei

    schleife { if (test) continue; else { anweisungen; } }
    

    kannst du das "else { anweisungen; }" durch "anweisungen;" ersetzen, d.h. den else-Zweig entfernen. Er führt nur dazu, dass man eigentlich tiefer einrücken müsste, was du dann aber nicht machst.

    2. Zum Problem:
    Wenn die Werte alle variabel sind, musst du wohl auch die //-Zeilen auslesen. Denn wenn ich dich richtig verstehe, sollen die ja die folgende Zeile beschreiben. Es ist also ungünsig, für Kommentare und beschreibende Dinge denselben Zeilenanfang zu nutzen. Sonst würde ich sagen, dass du eine map<string, vector<float>> nehmen könntest. Oder sind in jeder Datei immer und in derselben Reihenfolge Durchfluss, Druckdifferenz, Länge Rorhleitung, Rohrrauhigkeit, Verbraucher enthalten? Dann könntest du entweder eine vector einer struct mit diesen Werten erzeugen oder für jeden dieser Werte einen eigenen vector erzeugen.



  • Ich habe mich da vertan. In der Textdatei sind die Zeilen fix. Es soll einem Benutzer jedoch möglich sein einen alternativen Verbraucher hinzuzufügen. Er soll also jede Wertezeile um je einen Wert erweitern können.

    So wie du es jetzt beschrieben hast Th69 habe ich es bereits probiert. Ich schaffe es jedoch nicht eine Zeile auszulesen, die Werte in einem Vektor_1 zu speichern und anschließen die nächste Zeile auszulesen und die Werte in Vektor_2 zu speichern. Kannst du mir da einen Tipp geben, wie ich das am besten bewerkstellige?

    Was meinst du damit das es ungünstig ist Kommentarzeilen und beschreibende Dinge nicht auslesen zu lassen wob?

    In den folgenden Textdateien sind andere Daten enthalten, welche ich ebenfalls als Matrix ausgeben möchte. Ich denke wenn ich verstehe wie man es bei dieser ersten macht, sollten die dann auch kein Problem mehr sein!

    Vielen Dank schonmal 🙂



  • Hallo,

    ich denke ein schlaueres Dateiformat wäre, pro Zeile für alle Wertekategorien einen Wert zu verwenden, also:

    rohrleitungsdaten_verbraucher.txt

    Format: Durchfluss [l/s] | Druckdifferenz [bar] | Länge Rorhleitung [m] | Rohrrauhigkeit [mm]
    110 0.25 60 0.4
    60 0.2 25 0.4
    

    Man könnte auch optional die einzelnen Werte noch durch Kommata trennen, oder sonstige Syntax einführen. Fände ich aber vom Prinzip her einfacher. Dann packst du das wie vorgeschlagen in ein struct, definierst den >> operator, welcher einfach 4 doubles einließt. IMHO wäre das einfacher. Dann einfach die erste Zeile ignorieren, wo dann so ein Kommentar (Spezifikation des Formats) steht. Praktisch gesehen muss man auch einfach 1 Zeile dazu schreiben, anstatt an 4 verschiedenen Stellen der Datei einen Wert einzufügen. Man sieht auch auf einen Blick welche Werte zusammengehören.

    Schnell zusammengeworfenes Beispiel:

    #include <iostream>
    #include <fstream>
    #include <limits>
    
    struct Rohrdaten {
        double durchfluss {};
        double druckdifferenz {};
        double laenge {};
        double rauhigkeit {};
    };
    
    std::istream& operator>>(std::istream& is, Rohrdaten& daten)
    {
        return is >> daten.durchfluss >> daten.druckdifferenz >> daten.laenge >> daten.rauhigkeit;
    }
    
    std::ostream& operator<<(std::ostream& os, const Rohrdaten& daten)
    {
        return os << daten.durchfluss << ' '
                  << daten.druckdifferenz << ' '
                  << daten.laenge << ' '
                  << daten.rauhigkeit;
    }
    
    int main()
    {
        std::ifstream file {"input.txt"};
        if (!file)
        {
            std::cerr << "Datei konnte nicht geoeffnet werden\n";
            return -1;
        }
        // erste Zeile als Kommentarzeile
        file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        for (Rohrdaten daten; file >> daten; )
        {
            // evtl. prüfen(Daten): z.B: negative Länge macht keinen Sinn
            // verarbeiten(Daten)
            std::cout << daten << '\n';
        }
    
        return 0;
    }
    


  • Hm ok. Das mit den structs hatte ich mir auch mal angeschaut, bin aber nicht so ganz schlau draus geworden. Du magst recht haben, dass das so einfach wäre. Mein Problem ist nur, dass es eine Gruppenprojekt ist und von mir die Ausgabe in Form einer Vektormatrix gefordert ist.
    Trotzdem, vielen Dank!

    Btw. was hat es eigentlich immer mit den "std::..." auf sich? Ist das quasi ne alternative zu "using namespace std"?


Anmelden zum Antworten