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
getlinejede 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'beigetline()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.