Zeilenanzahl einer Textdatei (geöffneter Stream) ermitteln



  • Hallo zusammen,

    ich möchte in meinem Code eine csv-Datei als ifstream öffnen und anschließend ermitteln, wie viele Zeilen die Datei aktuell hat. Dazu war mein Gedanke, die Zeilenumbrüche mittels einer Funktion zu zählen, die eine Referenz des Streams übernimmt und die Anzahl der zeilen als int zurückgibt. Folgender Code:

     unsigned int anzahlZeilenInDateiBestimmen (&ifstream stream) {
        unsigned int zeilenanzahl = 0;
        while (!stream.eof) {
            string zeile;
            getline(stream, zeile, '\n');
            cout << zeile; //zur Kontrolle in Konsole
            zeilenanzahl++;
        }
        return zeilenanzahl;
    }
    
    

    1.) Ist das über diesen weg sinnvoll bzw. habt ihr eine bessere Idee (im Netz habe ich leider nichts anderes gefunden).
    2.) Ich bekomme vom Compiler dauerhaft folgende Fehlermeldung, weiß aber nicht, warum... (stimmt evtl. mit &ifstream nicht?)

    Line 1 | error: expected ‘,’ or ‘;’ before ‘{’ token
    Line 1 | error: expected primary-expression before ‘stream’
    
    

    Bitte verzeiht mir falls die Frage trivial ist, aber ich bin Anfänger und komme da wirklich nicht weiter.
    Danke schonmal!



  • Ist eof eine Membervariable?

    Selbst wenn das übersetzt würde: du zählst eine Zeile zu viel. Benutze while(getline(stream, zeile))



  • @cmoe sagte in Zeilenanzahl einer Textdatei (geöffneter Stream) ermitteln:

    (&ifstream stream)

    => (ifstream& stream)
    (bzw. noch allgemeingültiger (istream& stream))



  • @th69 sagte in Zeilenanzahl einer Textdatei (geöffneter Stream) ermitteln:

    => (ifstream& stream)
    (bzw. noch allgemeingültiger (istream& stream))

    Merci! Das hat den Fehler beseitigt.

    @manni66 sagte in Zeilenanzahl einer Textdatei (geöffneter Stream) ermitteln:

    Ist eof eine Membervariable?

    Sollte doch eigentlich, oder? Habe es zumindest so im Code-Snippet meines Profs gesehen :smiling_face_with_open_mouth: .
    Allerdings beschwert sich der Compiler:

    Line 3 | error: cannot convert ‘std::basic_ios<_CharT, _Traits>::eof<char, std::char_traits<char> >’ from type ‘bool (std::basic_ios<char>::)() const’ to type ‘bool’
    Line 3 | |error: in argument to unary !|
    


  • Lösung:

    unsigned int anzahlZeilenInDateiBestimmen (istream& stream) {
        unsigned int zeilenanzahl = 0;
        while (getline(stream,zeile)) {
            zeilenanzahl++;
        }
        return zeilenanzahl;
    }
    

    danke!



  • @cmoe sagte in Zeilenanzahl einer Textdatei (geöffneter Stream) ermitteln:

    Sollte doch eigentlich, oder? Habe es zumindest so im Code-Snippet meines Profs gesehen .

    Möglicherweise ein Tippfehler?

    https://en.cppreference.com/w/cpp/io/basic_ios/eof


  • Mod

    Ein paar grundsätzliche Anmerkungen:

    1. Warum getline? Du willst schließlich nicht den Inhalt der Datei lesen, sondern wissen, wie viele Zeilen sie hat. getline ist eine ungeheuer aufwändige Funktion, da dort allerlei Speicher dynamisch angefordert und verschoben werden muss. Dabei willst du doch bloß die Anzahl der '\n' zählen (und dir dann eventuell noch Gedanken machen, wie du es zählst, wenn die Datei als letztes Zeichen ein '\n' hat oder die Datei gar keine Zeichen hat, aber das ist eine andere Baustelle). Das ist trivial, indem du einfach die Datei zeichenweise durchgehst. Brauchst du nicht einmal selber machen, da gibt es was in algorithm dafür.
    2. Das was ich oben in Klammern als 'andere Baustelle; beschrieb, solltest du dir mal Gedanken drum machen.
    3. Die wohl wichtigste Anmerkung: Warum? Ich behaupte mal: In über 80% der Fälle, in denen hier jemand mit einer solchen Frage kommt, ist das Zählen von Zeilen unnötig umständlicher Quatsch. Wenn es nicht dem Selbstzweck dient, zu wissen, wie viele Zeilen eine Datei hat (So wie das Linuxtool wc), dann ist das Wissen um die Anzahl der Zeilen einer Datei unnötig. Die meisten Programmierer, die so etwas machen wollen, wollen damit dann irgendwelche Arrays passender Größe mit new reservieren. Dabei wäre es viel besser, einen dynamisch mitwachsenden Container zu benutzen, wie vector. Daher: Was hast du eigentlich vor?


  • @seppj sagte in Zeilenanzahl einer Textdatei (geöffneter Stream) ermitteln:

    1. Was hast du eigentlich vor?

    Dazu verweise ich mal auf meinen anderen Thread: https://www.c-plusplus.net/forum/topic/348178/name-für-neues-objekt-aus-stream-auslesen
    Schau dir dort mal das Snippet im ersten Beitrag an. Ich möchte die Anzahl der Zeilen deshalb bestimmen, damit ich in einer anderen Funktion als Schleifenbedingung angeben kann, wie viele Objekte insgesamt erstellt werden sollen (entsprechend der Anzahl der Zeilen, da jede Zeile ein Objekt werden soll).
    Vielleicht gibt es ja dazu eine bessere Lösung?


  • Mod

    @cmoe sagte in Zeilenanzahl einer Textdatei (geöffneter Stream) ermitteln:

    @seppj sagte in Zeilenanzahl einer Textdatei (geöffneter Stream) ermitteln:

    1. Was hast du eigentlich vor?

    Dazu verweise ich mal auf meinen anderen Thread: https://www.c-plusplus.net/forum/topic/348178/name-für-neues-objekt-aus-stream-auslesen
    Schau dir dort mal das Snippet im ersten Beitrag an. Ich möchte die Anzahl der Zeilen deshalb bestimmen, damit ich in einer anderen Funktion als Schleifenbedingung angeben kann, wie viele Objekte insgesamt erstellt werden sollen (entsprechend der Anzahl der Zeilen, da jede Zeile ein Objekt werden soll).
    Vielleicht gibt es ja dazu eine bessere Lösung?

    Genau das was ich befürchtet hatte. Das ist eine Wahnsinnsaktion, die ganze Datei zu lesen, damit man hinterher eine schlechte Schleifenbedingung schreiben kann, bloß um die Datei noch einmal auszulesen. Das Lesen der Datei ist mit Abstand die teuerste Aktion deines ganzen Programms und du machst es nun doppelt. Außerdem hast du dann all die Probleme, die ich bei 2. genannt habe.

    Eine Schleife muss nicht immer eine bestimmte Anzahl Durchläufe als Bedingung haben. Man kann alles mögliche als Bedingung nehmen. Richtig ist hier

    while(Zeile wurde erfolgreich gelesen)
    {
      verarbeite(zeile);
    }
    

    Das ist effizient, narrensicher, und das Grundmuster jeder datenverarbeitenden Schleife in C++ (und in anderen Sprachen auch).

    Oder etwas weniger abstrakt, probier mal folgendes aus und verstehe es:

    ifstream in("test.cpp");
    for(string line; getline(in, line);)
    {
      cout << line << '\n';
    }
    

Anmelden zum Antworten