Filepointer nach getline zurücksetzen



  • Hallo Leute
    Kann mir jemand sagen, wo das problem bei folgendem Code liegt?:

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <fstream>
    
    using namespace std;
    
    int main()
    {
    
        int a[5];
    
        ifstream fin("input.txt");
    
        char c[100];
        int lines = 0;
    
        while(fin.good())    //Zeilen zählen
        {
            fin.getline(c, 10);
            lines++;
        }
    
        fin.seekg(0, ios::beg);
        int b;
        fin >> b;
    
        cout << b; 
    
        return 0;
    }
    

    "input.txt" ist eine Liste mit Zahlen.
    fin.seekg(0, ios::beg); scheint den filepointer nicht korrekt zurückzusetzen, weil fin >> b; nicht die erste Zahl in der Liste nach b schreibt.
    Komischerweise funktioniert aber dieser Code: (welcher abgesehen von der Schleife zum Zeilenzählen absolut identisch ist.

    int main()
    {
    
        int a[5];
    
        ifstream fin("input.txt");
    
        char c[100];
        int lines = 0;
    
        fin.getline(c, 10);
    fin.getline(c, 10);
    
        fin.seekg(0, ios::beg);
        int b;
        fin >> b;
    
        cout << b; 
    
        return 0;
    }
    

    Kann mir das nicht erklären.



  • Versuch mal zusaetzlich

    fin.clear();
    

    nach der Schleife. Das sollte den Fehlerzustand im fin Objekt zuruecksetzen.



  • Deine Schleife endet beim Einlesen von EOF, also wenn du am Ende der Datei angelangt bist. Das eofbit wird in deinem Stream gesetzt und ab da an sind weitere Operationen auf den Stream nicht mehr gesund. Daher sollte ein fin.clear() nach der Schleife ausreichen, um wieder sauber weiterzuarbeiten. Desweiteren folgendes dringend durchlesen: http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=eof#Answ



  • #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <fstream>
    
    using namespace std;
    
    int main()
    {
    
        int a[5];
    
        ifstream fin("input.txt");
    
        char c[100];
        int lines = 0;
    
        while( fin.getline(c, 10) )    //Zeilen zählen
        {
            lines++;
        } // Wenn du aus der Schleife rauskommst, ist der Stream fin in einem schlechten Zustand. Alle Operationen, die du auf den Stream anwendest, schlagen dann fehl.
    
        fin.clear(); // Stream fin in den Zustand gut überführen.
        fin.seekg(0, ios::beg);
        int b;
        fin >> b;
    
        cout << b;
    }
    


  • Anstatt eines char-Arrays solltest du in C++ std::string verwenden:

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using std::string;
    
    int main() 
    { 
      std::ifstream fin("input.txt"); 
    
      string c;
      int lines = 0; 
      while( getline(fin,c) )
      { 
          lines++; 
      }
      fin.clear();
    
      /* Der Rest des Codes */
    }
    


  • Außerdem könntest du die Zeilen in einem std::vector ablegen und dann std::vector.size() benutzen, um die Anzahl der Zeilen zu ermitteln. Mit der Methode brauchst du dann auch nur die erste Zeile aus dem std::vector nehmen, anstatt wieder die Datei von vorne zu lesen.



  • Schamote schrieb:

    Außerdem könntest du die Zeilen in einem std::vector ablegen und dann std::vector.size() benutzen, um die Anzahl der Zeilen zu ermitteln. Mit der Methode brauchst du dann auch nur die erste Zeile aus dem std::vector nehmen, anstatt wieder die Datei von vorne zu lesen.

    Nein, das mit dem std::vector ist nun wirklich nicht sinnvoll. Verbraucht bloss unnoetig Speicher.
    Um sich die erste Zeile zu merken und die Anzahl Zeilen zu zaehlen muss man nicht die gesamte Datei in einem std::vector speichern:

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using std::cout;
    using std::endl;
    using std::string;
    
    int main() 
    { 
      std::ifstream fin("input.txt"); 
    
      string firstline;
      getline(fin,firstline);
    
      string s;
      int nlines = 1;
      while( getline(fin,s) )
        ++nlines;
    
      cout << "Erste Zeile: " << firstline << endl;
      cout << "Anzahl Zeilen: " << nlines << endl;
    }
    


  • Apropos Speicherverbrauch:

    std::ifstream fin("input.txt");
    std::cout << "Anzahl Zeilen: "
              << std::count(std::istreambuf_iterator<char>(fin),
                            std::istreambuf_iterator<char>(), '\n') << '\n';
    


  • Eleganter finde ich ja das hier

    std::ifstream inFile("file"); 
      std::count(std::istreambuf_iterator<char>(inFile), 
                 std::istreambuf_iterator<char>(), '\n');
    

    Wenn die letzte Zeile nicht mit '\n' abgeschlossen ist, wird sie nicht mitgezählt.

    siehe http://stackoverflow.com/questions/3072795/how-to-count-lines-of-a-file-in-c/3072840#3072840



  • icarus2 schrieb:

    Schamote schrieb:

    Außerdem könntest du die Zeilen in einem std::vector ablegen und dann std::vector.size() benutzen, um die Anzahl der Zeilen zu ermitteln. Mit der Methode brauchst du dann auch nur die erste Zeile aus dem std::vector nehmen, anstatt wieder die Datei von vorne zu lesen.

    Nein, das mit dem std::vector ist nun wirklich nicht sinnvoll. Verbraucht bloss unnoetig Speicher.
    Um sich die erste Zeile zu merken und die Anzahl Zeilen zu zaehlen muss man nicht die gesamte Datei in einem std::vector speichern:

    #include <iostream>
    #include <fstream>
    #include <string>
      
    using std::cout;
    using std::endl;
    using std::string;
      
    int main() 
    { 
      std::ifstream fin("input.txt"); 
    
      string firstline;
      getline(fin,firstline);
    
      string s;
      int nlines = 1;
      while( getline(fin,s) )
        ++nlines;
    
      cout << "Erste Zeile: " << firstline << endl;
      cout << "Anzahl Zeilen: " << nlines << endl;
    }
    

    Das habe ich mal so pauschal gesagt, wenn er die Zeilenzahl wissen möchte, kann man durchaus damit rechnen, dass er die Datei noch über die erste Zeile hinaus verwenden möchte 🙂

    Falls das nicht der Fall ist, hast du natürlich recht.


Anmelden zum Antworten