Einlesen einer Datei und Übergabe an Array ab einer bestimmten Zeile



  • Hallo C++ Experten,

    ich versuche derzeit eine Datei einzulesen, bin mir aber nicht sicher wie ich das an einer bestimmten Zeile auslesen soll. Meine Datei besitzt folgendes Format:
    ------------------------------------------------------------------------
    Berechnung
    Anzahl der Punkte: 200 # Atome: 10

    Punkt 1 : 0.00000000 0.00000000 0.00000000 Gewichtung = 0.00500000

    Energie 1 # mit Gewichtung 1.00000000

    Atom a b c d
    1 0.476 0.000 0.000 0.100
    2 0.476 0.000 0.000 0.100
    1 0.000 -0.000 -0.000 0.200
    2 -0.000 -0.000 0.000 0.200

    Energie 2 # mit Gewichtung 1.00000000

    Atom a b c d
    1 0.476 0.000 0.000 0.300
    2 0.476 0.000 0.000 0.300
    1 0.000 -0.000 -0.000 0.400
    2 -0.000 -0.000 0.000 0.400

    Energie 2 # mit Gewichtung 1.00000000

    Atom a b c d
    1 0.476 0.000 0.000 0.500
    2 0.476 0.000 0.000 0.500
    1 0.000 -0.000 -0.000 0.600
    2 -0.000 -0.000 0.000 0.600

    ....
    ------------------------------------------------------------------------

    Der Code, den ich mir bislang zusammengeschrieben habe, summiert über alle letzten Spalten:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <vector>
    
    using namespace std;
    
    int main()
    {
        int reihen = 0;
        int spalten = 0;
        string line;
        int ersteZahl = 0;
        vector<vector<double> > werte;
        vector<vector<double> > ergebnis;
        vector<double> reihentotal;
        ofstream Datei;
        ifstream in("datei.txt");
        Datei.open("ausgelesene_datei.txt",ios::app);
        Datei.setf(ios::fixed);
        Datei.setf(ios::showpoint);
        Datei.precision(3);
    
        if(in.fail()) 
        {
            cerr << "Datei kann nicht geoffnet werden" << endl;
            return -1;
        }
    
        Datei << "\n" << endl;
    
        // Speichere jede Zahl
        while(in.good()) 
        {
    
            while(getline(in, line)) 
            {            
    
                istringstream stream(line);
                vector<double> tmp;
                double x;
    
                while (stream >> x)
                  tmp.push_back(x);
    
                if (tmp.size() > 0)
                  werte.push_back(tmp);
    
            }
        }
    
        // Pruefe ob die Spaltenanzahl sich veraendert hat oder nicht
        spalten = werte[0].size();
        for (unsigned i = 1; i < werte.size(); ++i)
        {
            if (werte[i].size() != spalten)
            {
                cerr << "Reihe mit unterschiedlicher Spaltennummer" << endl;
                return -1;
            }
        }
    
        for (unsigned i = 0; i < werte.size(); ++i)
    	{
            // Wenn eine Zahl mit 1 beginnt, fuege es der Reihe hinzu
            if (werte[i][0] == 1.0)
              ergebnis.push_back(werte[i]);
    
            // Wenn eine Zahl bzw. Zeile mit 2 beginnt, fuege es ebenfalls der Reihe hinzu
            if (werte[i][0] == 2.0)
            {
                for (unsigned j = 0; j < werte[i].size(); ++j)
                  ergebnis.back()[j] += werte[i][j];
            }
        }
    
        reihen = ergebnis.size();
    
        Datei << "Anzahl der Reihen # " << reihen << endl;
        Datei << "Anzahl der Spalten # " << spalten << endl;
        Datei << " " << endl;
    
        for(int i=0; i < reihen; i++) 
        {
            for(int j=4; j < spalten; j++) 
            {
                Datei << ergebnis[i][j]  <<  "	 " << "  " << endl;
            }
        }
    
        for(int i=0; i < reihen; i++)
        {  
            reihentotal.push_back(0.0);
            for (int j=1; j < spalten; j++) 
            {
                reihentotal[i] += ergebnis[i][j];
            }
        }
    
    	Datei.close();
        in.close();
        return 0;
    }
    

    Die Ausgabe erfolgt als:

    Anzahl der Reihen # 6
    Anzahl der Spalten # 5

    0.200
    0.400
    0.600
    0.800
    1.000
    1.200

    Ich würde aber gerne über nur über die Blöcke mit Aufschrift "Energie 2 #" summieren, d.h. es sollte dann folgendes ausgegeben werden (unter Vernachlässigung des Blocks "Energie 1 #":

    0.600
    0.800
    1.000
    1.200

    Ich habe versucht eine "*.find function" mit String-Inhalt einzubauen, bevor die Werte bei "werte[i][0] == 1.0" und "werte[i][0] == 2.0" eingelesen werden, kriege es aber irgendwie nicht hin, obwohl es nur noch ein kleiner Schritt ist :(.

    Ich wäre sehr dankbar, wenn mir jemand helfen könnte, wie ich es richtig zu parsen bzw. zu "tokenizen" habe.

    Viele Dank im Voraus für jegliche Hilfe,

    ThOr_Asgard



  • Der Code sieht einigermaßen furchtbar aus (was soll y.B. die while(in.good()) -Schleife?), dennoch sollte man das schnell einbauen können:

    Ersetze

    while(getline(in, line)) 
            {
    

    Durch:

    bool inErgebnis2 = false;
            while(getline(in, line)) 
            {             
                if (boost::begins_with(line, "Ergebnis ")) {
                    inErgebnis2 = boost::begins_with(line, "Ergebnis 2 #"));
                }
                if (!inErgebnis2) continue;
    

    (und #include <boost/algorithm/string.hpp> )

    Alles ungetestet.



  • Vielen Dank schon mal für den Hinweis wob! Ich hatte auch schon daran gedacht an dieser Stelle mit "bool" es einzulesen, bekam aber als Fehlermeldung segmentation fault heraus.

    Mich würde aber interessieren, ob es eine andere Lösung gibt, ohne dass ich "Boost" Header benutzen muss!?

    Vielen Dank im Voraus!



  • Klar geht das ohne. Das ist sehr einfach nachzubauen. Habe aber keine Lust dazu, wenns schon ne fertige Lösung gibt und überlasse dir das als Übung.



  • Ähm, ich merke gerade, dass es starts_with statt begins_with heißt. Verdammt, immer diese unterschiedlichen String-Bibliotheken! Das kommt davon, wenn man ohne IDE im Forumseditor programmiert 😞


Anmelden zum Antworten