Substrings aus Datei prüfen, um festzustellen, ob Satz "deutsch" ist



  • Hallo!

    Seit einigen Tagen schon versuche ich ein kleines Problem zu lösen, bei dem ihr mir sicher weiterhelfen könnt.

    Ich schreibe ein Programm, das ein recht große Anzahl an "Sätzen" generiert. Circa 99% dieser Sätze sind jedoch sinnlose Buchstabensalate, wie "agjaoisfjregkn". Leerzeichen und Umbrüche kommen nicht vor.

    Die Generierung klappt soweit gut. Die Übersicht nicht.

    Um etwas Übersicht zu schaffen, möchte ich nun überprüfen, ob im entsprechenden Satz mindestens ein deutsches Wort vorhanden ist. Wegen Bedenken bezüglich der Geschwindigkeit habe ich eine Liste mit den 10.000 häufigsten Wörtern unserer Sprache gesucht, die abfallend sortiert ist. Die Datei ist schlicht aufgebaut. Jedes Wort ist in einer einzigen Zeile eingetragen, wenn man soviel muss man die Datei nur noch Zeilen trennen.

    Dies tue ich, indem ich die Datei öffne und mittels

    getline
    

    jede Zeile auslese. Dann prüfe ich mittels

    string.find()
    

    , ob das eben ausgelesene Wort als Unterstring im zu prüfenden Satz vorhanden ist.

    Müsste doch eigentlich klappen, oder? Pustekuchen! Das Programm scheint nur eine Zeile zu finden, die in jedem Fall "" lautet. Diese ist zudem in jedem String vorhanden. Somit ist jeder Satz, auch "agjaoisfjregkn", gültiges Deutsch.

    Ich bin schon ziemlich am Verzweifeln und bitte um schnelle Hilfe. Ich danke schon mal im Voraus.

    Der Code meiner Funktion lautet wie folgt:

    bool checkSolution(string solution) {
        // Prüfen, ob gültiger deutscher Satz
        // Lade TOP1000-Wortliste
        fstream list(WORDFILE);
        if(!list) {
            cout << "Datei nicht da!" << endl;
            return false;
        } else {
            // String mit dem zu prüfenden Wort
            string word;
            // Wort gefunden?
            bool found = false;
            // Solange, bis kein Wort gefunden wurde und noch Zeilen vorhanden sind
            while(!list.eof() && !found) {
                getline(list, word, '\n');
                cout << word;
                if(solution.find(word) != string::npos) {
                    cout << " (bei " << solution.find(word) << ")";
                    found = true;
                    cout << " gefunden!";
                }
                cout << endl;
            }
            // Datei wieder schließen
            list.close();
            return found;
        }
    }
    

    Die Liste sieht so aus: (Auszug mit den ersten 100 Wörtern):

    der
    die
    und
    in
    den
    von
    zu
    das
    mit
    sich
    des
    auf
    für
    ist
    im
    dem
    nicht
    ein
    Die
    eine
    als
    auch
    es
    an
    werden
    aus
    er
    hat
    daß
    sie
    nach
    wird
    bei
    einer
    Der
    um
    am
    sind
    noch
    wie
    einem
    über
    einen
    Das
    so
    Sie
    zum
    war
    haben
    nur
    oder
    aber
    vor
    zur
    bis
    mehr
    durch
    man
    sein
    wurde
    sei
    In
    Prozent
    hatte
    kann
    gegen
    vom
    können
    schon
    wenn
    habe
    seine
    Mark
    ihre
    dann
    unter
    wir
    soll
    ich
    eines
    Es
    Jahr
    zwei
    Jahren
    diese
    dieser
    wieder
    keine
    Uhr
    seiner
    worden
    Und
    will
    zwischen
    Im
    immer
    Millionen
    Ein
    was
    sagte
    

    (Auf Anfrage schicke ich gerne die komplette Datei!)

    Vielen Dank und Viele Grüße
    Dominik



  • Mach mal '\n' bei getline() weg:

    while(!list.eof()) { //warum überprüfst du hier "found", wenn es nur false sein kann?
                getline(list, word);
                cout << "\n" << word;
                size_t wordPos = solution.find(word);
                if(wordPos != string::npos) {
                    cout << " (bei " << static_cast<int>(wordPos) << ") gefunden!\n";
                    found = true;
                }
            }
    

    Edit: Besser wär's die ganze Datei einzulesen (z.B. in std::list) und dann drüber iterieren.



  • Deine wesentliche Änderung, nämlich das Weglassen von '\n', hatte ich in meiner ursprünglichen Version schon benutzt. Der von dir gepostete Code funktionierte genauso wenig wie der meine. Genau das war es ja, was mich so verzweifelt macht. Alles was ich versuche, funktioniert einfach nicht.

    Ich prüfe found nur aus dem Grund, damit die Schleife nach dem ersten gefundenen Wort verlassen wird. Schließlich soll das Programm ja nur prüfen, ob min. 1 Wort vorhanden ist, eine weitere Prüfung würde dann nichts mehr bringen.

    Trotzdem danke ich für deine Hilfe. Den Typ size_t zu nutzen, daran hatte ich eig. noch nicht gedacht. Worin lägen denn die Vorteile dieser Methode?

    Dominik



  • Sorry, da habe ich mich mit dem found verguckt. Ansonsten funktioniert der Code bei mir.



  • Hallo,

    Machs doch mal so

    while(getline(list, word) && !found)
    


  • Hallo Leute,

    ich habe heute herausgefunden, woran es lag, dass es vorher nie klappte. Ich hatte mein Programm immer mit den Debug-Einstellung kompiliert. Heute morgen habe ich es auch mit den Release-Einstellungen versucht - und voila, es funktionierte perfekt. Genau so, wie ich es mir vorgestellt hatte. Ich werde mein Programm jetzt also weitermachen und danke euch für eure tatkräftige Unterstützung.

    Sollte jemanden etwas ähnlichen passieren (btw., ich nutze die QT Creator-Umgebung unter Windows XP), dann kann es helfen, auf den Debugger zu verzichten und das Programm direkt mit den Release-Einstellungen auszuführen.

    Vielen Dank und angenehmes Coden
    Dominik



  • Dann hast aber noch einen Fehler drin. Normalerweise sollte ein Programm in der Debug und in der Releaseeinstellung gleich funktionieren.



  • dominik_the_fischjunge schrieb:

    Wegen Bedenken bezüglich der Geschwindigkeit habe ich eine Liste mit den 10.000 häufigsten Wörtern unserer Sprache gesucht, die abfallend sortiert ist.

    Wenn du dir Sorgen um Geschwindigkeit machst, solltest du hier noch etwas tiefer in die Trickkiste greifen und nach dem Beuteil mit Tries und verwandten Datenstrukturen suchen. Momentan sind ternäre Suchbäume da der letzte Schrei, und in Boost.Spirit gibt es etwas versteckt (hinter der symbols-Klassenvorlage) sogar eine Implementation unter Boost-Lizenz. Allerdings ist Spirit für Anfänger ziemlich überwältigend, also weiß ich nicht, ob du das bei dir sinnvoll eingebaut kriegst. Der Wikipedia-Artikel hat unten zwei Links zu anderen C++-Implementationen; wahrscheinlich sind die einfacher zu benutzen - ich kenne sie nur halt nicht.



  • Keinen endlichen Automaten oder Präfixbaum?



  • volkard schrieb:

    Keinen endlichen Automaten oder Präfixbaum?

    Ternäre Suchbäume sind eine Unterart von Präfixbäumen. Ob Präfixbaum oder endlicher Automat dürfte Jacke wie Hose sein; es ist davon auszugehen, dass der Zustandsgraph des Automaten dem Suchbaum am Ende sehr ähnlich sehen dürfte.


Anmelden zum Antworten