Vermeintliche einfache Aufgabe zu streams, aber sie hat es in sich, brauche Hilfe



  • Liebe Community,

    Ich möchte mich mit einer vermeintlich einfachen Frage an euch wenden die mich aber schon seit Tagen beschäftigt und bei deren Bearbeitung ich einfach nicht weiterkommen.

    Die Aufgabe liest sich mal sehr leicht:
    Schreibe ein C++ Programm welches die Datei faust.txt öffnet und die Anzahl der Zeilen und die Anzahl der Wörter GLEICHZEITIG!! in der Konsole ausgibt.

    Und dieses gleichzeitig ist es was mich in den Wahnsinn treibt.

    Die Lösung für hintereinander ausgeben also mit zweimaligem Ausführen des Programms war nicht schwierig.

    Hier meine Lösung

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <stdlib.h>
    using namespace std;
     
    int main(int argc, const char * argv[]) {
     
     
    int wordcounter = 0;
    int linecounter = 0;
     
     
        ifstream file ("E:\\Programmieren\\faust.txt");
     
        if (file.is_open()) {
            while (!file.eof()) {
     
                string b;
                string a;
                file >> a;
                getline(file, b);
                linecounter++;
                wordcounter++;
     
            }
     
     
            cout << linecounter <<endl;
             cout << wordcounter <<endl;
     
     
                    }
         else {
            cout << "Die Datei konnte nicht geoeffnet werden." << endl;
         }
     
    }
    

    Einmal wordcounter und file>>a auskommentiert füt die Zeilen, für die Wörter die anderen beiden.
    Bringt beides ein richtiges Ergebnis.

    Nun können aber file >>a und getline(file, b); nicht gleichzeitig ausgelesen werden,
    Ist mir klar, ich hab versucht es mit einem Char umzubauen für Leerzeichen bzw. Zeilenumbruch

    if (file.is_open()) {
     
        int linecounter = 0;
        int wordcounter = 0;
        char ch;
     
        while (!file.eof()) {
     
            // nächstes Zeichen einlesen
            ch = file.get();
     
            // bei einem Zeilenumbruch die Anzahl der Wörter und der Zeilen erhöhen
            if (ch == '\n') {
                linecounter++;
                wordcounter++;
            }
     
            // bei einem Leerzeichen die Anzahl der Wörter erhöhen	
            if (ch == ' ') {
                wordcounter++;
            }
    }
    cout << "Die Datei enthaelt " << linecounter << " Zeilen mit insgesamt " << wordcounter << " Woertern"<< endl;
    

    So damit bekomme ich zwar die Anzahl der Zeilen korrekt raus aber nicht die Anzahl der Wörter.

    Das Beispiel könnte man mit jeder beliebigen Textdatei lösen.

    Kann mir jemand einen Tipp geben wo mein Denkfehler ist und wie eine gemeinsame Ausgabe beider Parameter bei einem Programmlauf funktionieren könnte.
    Wie gesagt bin noch Anfänger und jetzt mit meinem Latein schon am Ende.



  • @montanistikus1 Wörter können auch dirch mehrere Whitespace hintereinander getrennt sein.

    Eine Zeile aus lauter Leerzeichen hat keine Wörter.
    Du darfst nur bei einem Wechsel (druckbares Zeichen nach Whitespace) zählen.



  • Hallo Dirk

    Danke für deine Antwort

    Ja es hapert an der if condition bei den Wörtern.
    Wie gieße ich das was du sagst in eine if condition

    If ( char=' ' && ??

    Da wirds schwierig



  • Das mehrere Leerzeichen ginge ja auch mit einer || Verknüpfung, was fehlt ist die condition wie Worte sicher erkannt werden

    Mit meiner Methode fehlen mir bei der Datei ganze 11.500 Worte



  • Grundsätzlich machst Du schonmal falsch:

    auf fehler (oder eof) prüfen
    lesen
    (eventuell mist) verarbeiten

    Richtig:

    lesen
    auf fehler (oder eof) prüfen
    wenn kein fehler: verarbeiten



  • @montanistikus1 sagte in Vermeintliche einfache Aufgabe zu streams, aber sie hat es in sich, brauche Hilfe:

    Mit meiner Methode fehlen mir bei der Datei ganze 11.500 Worte

    Was gilt denn ein Wort?
    Gehören Zahlen auch dazu?
    Wie werden Wörter getrennt?

    Du wirst dir den Zustand (im Wort, außerhalb vom Wort) merken müssen.



  • @Swordfish

    Kannst du mir erklären weshalb?
    Wieso nicht auf offene Datei prüfen vor dem Lesen?

    @DirkB

    Mein Gedanke war: Wenn 2 char hintereinander nicht ' ' sind muss es ein Wort sein. Dumm aber bei einem englischen File wo das I für ich ja auch ein Wort ist.

    Hab das mal probiert kam trotzdem Blödsinn raus hab es mit Word und Wörter zählen verglichen.

    Bei Methode 1 geht ja alles nur gleichzeitig geht's nicht und weiss nicht wieso



  • um das da gehts:

    @montanistikus1 sagte in Vermeintliche einfache Aufgabe zu streams, aber sie hat es in sich, brauche Hilfe:

        while (!file.eof()) {
     
            // nächstes Zeichen einlesen
            ch = file.get();
    
    

    file geht eof nachdem Du versuchst mit file.get() zu lesen. Das bekommst Du aber vor der Verarbeitung bei Deinem Code nicht mit.



  • @montanistikus1 sagte in Vermeintliche einfache Aufgabe zu streams, aber sie hat es in sich, brauche Hilfe:

    Wieso nicht auf offene Datei prüfen vor dem Lesen?

    Das schon. Aber dann kannst Du gleich abbrechen:

    if (!file.is_open()) {
        std::cerr << "Couldn't open file \"faust.txt\" for reading :(\n\n";
        return EXIT_FAILURE;
    }
    


  • @montanistikus1 sagte in Vermeintliche einfache Aufgabe zu streams, aber sie hat es in sich, brauche Hilfe:

    Mein Gedanke war: Wenn 2 char hintereinander nicht ' ' sind muss es ein Wort sein. Dumm aber bei einem englischen File wo das I für ich ja auch ein Wort ist.

    Dann reicht auch ein Buchstabe.

    aber was ist mit 123 oder a,b oder montanistikus1 oder r2d2 und verdammt nochmal!!1!11!

    was gilt da als Wort (und wie ist das bei Word)?



  • Um auf die eigentliche Fragestellung zurückzukommen: Falls du stringstreams verwenden darfst kannst du mit getline die Zeile lesen, mit der Zeile einen stringstream initialisieren und mit >> die Worte in der Zeile lesen.



  • Danke mittag wie gesagt mache einen udemy Kurs stringstreams kenne ich noch nicht bin jetzt erst bei vectoren

    Könntest du mir erklären wie das funktioniert?
    Danke



  • @montanistikus1 Das funktioniert wie beim fstream, nur dass du den stream nicht mit einer Datei initialisiert sondern mit einem String.

    also sowas:

    #include <sstream>
    ...
    ...
    string linestr;
    string wordstr;
    istringstream strm(linestr);
    while (strm >> wordstr)
         wordcounter++;
    

    linestr bekommst du natürlich von getline ..



  • @montanistikus1

    #include <iostream>
    #include <sstream>
    #include <string>
    
    using namespace std;
    
    int wordsinline(string &zeile)
    {
       istringstream is{zeile};
       string tmp;
       int count {0};
       
       while(is >> tmp)
         ++count;
       
       return count;
    }
    
    
    int main()
    {
       string zeile {"wieviel Wörter sind in dieser Zeile drin"}; // Zeilen aus Deiner Datei lesen kannst Du ja
       
       // Mit jeder gefundenen Zeile dann eine passende Funktion aufrufen:
       int wcount = wordsinline(zeile);
       
       // in einer geeigneten Variablen aufaddieren ...
       
       // ...
       
       // am Ende ausgeben
       
       cout << wcount;   
    }
    


  • Vielen Dank für eure Hilfe

    Wie gesagt bin ja noch Anfänger habe eigentlich C++ technisch wahrscheinlich erst das "Welpenstadium" abgeschlossen
    (hatte erst Operatoren, Schleifen, Funktionen,Arrays, Streams und jetzt Vektoren)

    Da kommt man noch nicht zu so eleganten Lösungen. Aber vielen Dank ich werd versuchen die Lösung von belli nachzuvollziehen und dann in ein Programm zu gießen.

    Danke an alle die mir hier mit Tipps und Hilfe zur Seite gestanden sind.



  • Obwohl die Definition von "Wort" immer noch nicht klar ist:

    #include <cstdlib>
    #include <cctype>
    #include <fstream>
    #include <iostream>
    
    int main()
    {
        auto input_filename{ "faust.txt" };
        std::ifstream is{ input_filename };
    
        if (!is.is_open()) {
            std::cerr << "Couldn't open \"" << input_filename << "\" for reading :(\n\n";
            return EXIT_FAILURE;
        }
    
        unsigned long long num_words = 0;
        unsigned long long num_lines = 1;
        bool in_word = false;
    
        for (;;) {  // forever
    
            int ch = is.get();
    
            if (ch == EOF) {
                if (in_word) {
                    in_word = false;
                    ++num_words;
                }
                break;
            }
    
            if (std::isspace(ch)) {
                if (in_word) {
                    in_word = false;
                    ++num_words;
                }
    
                if (ch == '\n')
                    ++num_lines;
                continue;
            }
    
            in_word = true;
        }
    
        std::cout << "Number of words: " << num_words << '\n'
                  << "Number of lines: " << num_lines << "\n\n";
    }
    
    


  • Vielen lieben Dank auch dir Swordfish

    Für mich persönlich war die Definition als ich an die Aufgabe ranging: Ein Wort ist ein String welches vom vorhergehenden durch ein ' ' getrennt ist und auch vom nachfolgenden mit einem ' ' getrennt ist.

    Warum das mit file >> a so gut funktioniert und die Zahl der Wörter mit der MS Word Zählung übereinstimmt und bei mir Mist rauskam ist mir noch nicht klar.


Anmelden zum Antworten