Einzelne Werte aus Datei summieren



  • Hallo,
    ich habe folgendes Problem:
    Ich habe ein Modell geschrieben bei dem ich aus bestehenden Wetterdaten auf den Niederschlag zugreifen muss. Allerdings haben die Ausgangsdateien eine stündliche Auflösung und ich muss diese erst einmal als wöchentliche Werte in eine neue Datei schreiben.
    Die Ausgangsdatei sieht wie folgt aus und geht über 200 Jahre.(1,7 Mio Zeilen)

    Y M D H Rain Temp
    0 0 0 0 0 0.534247
    0 0 0 1 0 -0.896021
    0 0 0 2 0 -1.79512
    0 0 0 3 0 -2.10179
    0 0 0 4 0 -1.79512
    0 0 0 5 0 -0.896021

    Die erste Zeile muss ignoriert werden da dort ja nur Y M D H Rain Temp steht.
    Ab der zweiten Zeile muss ich auf das 5te Element jeder Zeile zugreifen und für eine Woche summieren, d.h. für 168(24*7) Zeilen immer den Wert summieren. Dann in die Ausgabe Datei speichern und den Wert wieder 0 setzen.
    Allerdings haben die Daten 365 Tage, ergo 52 Wochen plus 1 Tag, daher würde sich das Jahr immer um 1 Tag verschieben.
    Deswegen wird in der letzten Woche 1 Tag dazu gerechnet also 24 weitere Zeilen.
    So weit so gut. Mein Problem ist aber das ich noch nie Daten aus Dateien eingelesen habe und ich keine Ahnung habe wie ich einzelne Spalten und darin einzelne Elemente anspreche. Ich hoffe ihr könnt mir da weiter helfen.

    Hier ist mein Code.

    #include <iostream>
    #include <fstream>
    using namespace std;
    //-----------------------------------------------------------------------------------
    int main()
    
    // Öffnen/erstellen von Input und Output File
    //-----------------------------------------------------------------------------------
    {
        ifstream dateiRead;  /* Objekt der Eingabe-Datei */
        ofstream dateiWrite; /* Objekt der Ergebnis-Datei */
    
        dateiRead.open("sandveld_200_norm_0_cool.txt", ios::in);
           if (!dateiRead.good())
              {
                cout << "Konnte Datei zum Lesen nicht oeffnen" <<endl;
                return -1;
              }
    
        dateiWrite.open("sandveld_200_norm_0_cool_w.txt", ios::out); // ios:: app würde daten anhängen
           if (!dateiWrite.good())
              {
                  cout << "Konnte Datei zum Schreiben nicht oeffnen." << endl;
                  return -1;
              }
    //Einlesen aus Input und speichern in Output      
    //--------------------------------------------------------------------------------------------------------
        dateiWrite << "Y" << "\t" << "W" << "\t" << "Rain" << "\n" ;
        double w_rain;
    
    //Schleife für Jahr
        for (int year = 0; year<200; year++)
        {
    //Schleife für Wochen
            for (int week = 0; week<52; week++)
            {
                w_rain = 0;
    
                { //<--Schleife für die nächsten 168 (24*7) Zeilen (entspricht einer Woche) aus Input Datei und einlesen des 5ten Wertes pro Zeile
                     w_rain = w_rain; //+ Wert aus Inputdatei...Wie?
    //--------------------------------------------------------------------------------------------------------
                     //Die Daten haben 365 Tage, ergo 52 Wochen plus 1 Tag, daher würde sich das Jahr immer um 1 Tag verschieben.
                     //Deswegen wird in der letzten Woche 1 Tag dazu gerechnet also 24 weitere Zeilen.
                     if (week == 51)
                     {
                         //<--Schleife für die nächsten 24 Zeilen
                         w_rain = w_rain ; //+ Wert aus Inputdatei
                     }
    //--------------------------------------------------------------------------------------------------------
                }
                dateiWrite << year << "\t" << week << "\t" << w_rain << "\n" ;
                //fprintf(dateiWrite,"%5.2d %5.2d %5.2f \n ",year,week,w_rain); //warum funktioniert das nicht?
            }
        }
    }
    


  • Datei öffnen:

    ifstream in("dateiname.txt"); //#include <fstream>
    

    1. Zeile ignorieren:

    string dummy; //include <string>
    getline(in, dummy);
    

    aus den nächsten Zeilen die beiden letzten Werte lesen:

    int tmp;
    int wertRain;
    double wertTemp;
    while(in >> tmp >> tmp >> tmp >> tmp >> wertRain >> wertTemp)
    {
       machWasMitwertRainwertTemp();
    };
    

  • Mod

    Ab der zweiten Zeile muss ich auf das 5te Element jeder Zeile zugreifen und für eine Woche summieren, d.h. für 168(24*7) Zeilen immer den Wert summieren.

    Meinst du vielleicht die sechste?

    Ich mache jetzt zwei Annahmen: Alle Zahlen sind durch ein Leerzeichen getrennt. Am Anfang der Zeile gibt es keine Leerzeichen.

    Dann kannste probieren, ein wenig effizienter als Belli ranzugehen, nämlich die Zahlen als Wörter behandeln die durch Leerzeichen getrennt sind.

    #include <istream>
    #include <limits>
    
    double extract_one_line( std::istream& is )
    {
    	// ersten vier Spalten ignorieren
    	for( unsigned i = 0; i != 4; ++i )
    		is.ignore( std::numeric_limits<std::streamsize>::max(), ' ' );
    
    	double d; is >> d;
    
    	// letzte Spalte ignorieren
    	is.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
    
    	return d;
    }
    
    #include <fstream>
    #include <vector>
    
    int main()
    {
    	std::vector<double> weeklySum;
    	weeklySum.reserve( 52*200 );
    
    	std::ifstream stream("Datei.txt");
    	stream.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ); // first line
    
    	while( stream )
    	{
    		for( unsigned week = 0; week != 52; ++week )
    		{
    			double sum = 0;
    			for( unsigned hour = 0; hour != 168 && stream; ++hour )
    				sum += extract_one_line(stream);
    
    			if( !stream )
    				break;
    
    			weeklySum.push_back( sum );
    		}
    
    		weeklySum.back() += extract_one_line(stream);
    	}
    }
    

    (total ungetestet! habe ich lediglich heruntergetippt)



  • #include <iostream>
    #include <boost/range/istream_range.hpp>
    #include <boost/range/adaptors.hpp>
    int main() {
      std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
      int day=0, week=0, year=0;
      double rainsum=0;
      for (double rain : boost::istream_range<double>(std::cin).advance_begin(5) | boost::adaptors::strided(6)) {
        rainsum += rain;
        if (++day == 52*7 || (day%7!=0 && day != 52*7 + 1)) continue;
        std::cout << year << '\t' << week << '\t' << rainsum << '\n';
        rainsum=0;
        if (day == 52*7 + 1) {
          day=0;
          week=0;
          ++year;
        } else {
          ++week;
        }
      }
    }
    


  • Vielen Dank euch beiden das ihr so schnell geantwortet habt.
    Der Vorschlag von Belli funktioniert genau so wie ich es haben wollte.
    Auch Dank an Arcoth. Ich versuch da mal am Wochenende durchzusteigen. Aber der Vorschlag von Belli reicht dafür das ich die Daten heute weiter nutzen kann.

    Nur noch eine Frage:

    Belli schrieb:

    Datei öffnen:
    ...

    string dummy; //include <string>
    getline(in, dummy);
    

    ...

    Was macht genau der Dummy bzw. wozu braucht man ihn? Ohne funktioniert es bei mir nicht.



  • Die zwei Zeilen lesen die erste Zeil aus der Datei in dummy ein. Somit beginnt das Lesen erst danach.


Log in to reply