Ifstream -> Ende der Datei in nächster Zeile?



  • Der Titel sagt wohl schon das meiste.

    Ich will ein Programm schreiben, welches mir eine 2-spaltige txt-Datei einließt und den Mittelwert der 2. Spalte bildet.
    Das Problem welches ich noch lösen will ist folgendes:
    Ich verwende if-Stream und will mit eof() prüfen ob ich das Ende der Datei erreicht habe. Das Problem ist nun aber, dass der stream immer einen Wert zu viel ausließt. Er läuft also noch einen schleifendurchlauf zu viel durch und gibt mir den letzten Wert doppelt zurück (der ja in tmp gespeichert ist.)

    Hier mein Code:

    float average(string filename, int row){
    
    	ifstream in(const_cast<char*>(filename.c_str()) );
    	int tmp;
    	int N = 0;
    	float sum = 0;
    	float average = 0;
    
    	while( !(in >> tmp) ) {
    		in.clear();
    		in.ignore(numeric_limits<streamsize>::max(), '\n');
      }
    	in.unget();
    
    	for( int i = 0; !(in.eof()); i++ ){
    		for( int j = 1; j < 3; j++ ){			
    			in >> tmp;
    			if( j == row ){
    				cout << tmp << endl;
    				sum+=tmp;
    				N++;
    			}
    		}
    	}
    
    	average = sum/N;
    	cout << "The sum is " << sum << endl;
    	cout << "The average of the " << N << " datapoints is: " << average << endl;
    	cout << "_________________" << endl;
    
    	return average;
    
    }
    


  • ifstream in(const_cast<char*>(filename.c_str()) ); //Zeile 3
    

    Wieso zum Teufel castest du?
    (P.S.: Seit C++11 kann man auch direkt 'nen string übergeben)

    Wie ist die Datei aufgebaut?
    So?

    0   8
    2   9
    684 654
    5   1.4
    6   ....
    16
    ...
    


  • Die Konstruktion

    while( !EOF ) {
            in >> irgendwas;
            // mache was mit 'irgendwas'
    

    .. ist derart verbreitet - ich habe sie auch schon in Lehrbüchern gesehen, dass sie viele unbedacht übernehmen.
    Trotzdem ist sie fehlerhaft und führt u.a. zu dem von Tom_12345 beschriebenen Verhalten.

    Besser:
    - Lese ein was auch immer Du willst
    - prüfe danach(!), ob das gut gegangen ist

    in diesem Fall in etwa so:

    float average(string filename, int row) 
    {
        ifstream in( filename.c_str() );
        int tmp;
        while( !(in >> tmp) ) { 
            in.clear();
            in.ignore(numeric_limits<streamsize>::max(), '\n');
        }
        in.unget(); // das Verfahren funktioniert nicht, wenn row==1 und tmp >9 ist
    
        int N = 0;
        float sum = 0;
        for( float tmp1, tmp2; in >> tmp1 >> tmp2; ++N )
        {
            if( row == 1 ) 
                sum += tmp1;
            else if( row == 2 ) 
                sum += tmp2;
        }
    
        float average = sum/N;
        cout << "The sum is " << sum << endl;
        cout << "The average of the " << N << " datapoints is: " << average << endl;
        cout << "_________________" << endl;
    
        return average;
    }
    


  • Danke für die Antowrt Werner Solomon, damit hat sich mein Problem geklärt.

    @Sone
    Wenn ich nur den String filename übergebe, ohne den cast, bekomme ich für diese Zeile den Fehler

    no matching function for call to ‘std::basic_ofstream<char>::basic_ofstream(std::string&)’
    

    .

    Was müsste ich denn verändern, damit ich dem Konstruktor mit ohne einen cast aufrufen kann? z.B.
    ofstream out(file_out); wobei file_out ein String ist.


  • Mod

    Tom_12345 schrieb:

    ofstream out(file_out); wobei file_out ein String ist.

    ofstream out(file_out.c_str()); oder den C++11-Standard benutzen.



  • SeppJ schrieb:

    Tom_12345 schrieb:

    ofstream out(file_out); wobei file_out ein String ist.

    ofstream out(file_out.c_str()); oder den C++11-Standard benutzen.

    👍
    Das const_cast ist einfach total überflüssig.


Log in to reply