C++ Mehrere Wörter aus einem String lesen

Crysko

Cadet 3rd Year
Registriert
Feb. 2011
Beiträge
33
Hallo,

ich arbeite gerade an einem "intelligenten Chatprogramm", wo man mit seinem Computer chatten kann. Dazu muss ich mehrere Wörter aus den Benutzereingaben abfragen können, damit dieser darauf entsprechend reagieren kann.

Meine Suche nach 1 Wort klappt prima. Allerdings weiß ich nicht genau, wie ich nach mehreren Wörtern gleichzeitig suchen kann. Hier mal mein Code für das Suchen eines Wortes:

Code:
string Eingabe;

cin >> Eingabe;

//Suche nach dem Wort "Hallo" in Variable "Eingabe"
if (static_cast<int>(Eingabe.find("Hallo", 0)) != -1)   //gibt bei false -1 aus
{
   cout << "Wort gefunden!" << endl;
}
else
{
   cout << "Wort nicht gefunden!" << endl;
}

Das klappt super. Jetzt habe ich mal das hier für zwei Worte versucht:

Code:
string Eingabe;

cin >> Eingabe;

//Suche nach dem Wort "Hallo" UND "Welt" in Variable "Eingabe"
if ((static_cast<int>(Eingabe.find("Hallo", 0)) != -1)
    && (static_cast<int>(Eingabe.find("Welt", 0)) != -1))
{
   cout << "Wörter gefunden!" << endl;
}
else
{
   cout << "Wörter nicht gefunden!" << endl;
}

Dieser Code klappt aber so nicht. Er gibt keine Ausgabe. Weder true, noch false. Auch kommt keine Fehlermeldung oder sowas. Er schreibt einfach nichts. Woran kann das liegen? Habt ihr andere Vorschläge, wie man das lösen kann?

Vielen Dank!
 
Wie, weder die Anweisungen im if-Zweig noch die im else-Zweig werden ausgeführt?? Verstehe ich nicht. Im Übrigen frage ich mich, warum den Rückgabewert von std::string::find immer so eigenartig in einen int umwandelst. Die find()-Methode gibt std::string::npos zurück, wenn sie nix findet ... das ist eine vordefinierte Konstante, die du so direkt in deinem Code verwenden kannst (und solltest).
 
ok. habe das abgeändert. allerdings funktioniert der code nach wie vor nicht.

Das Programm scheint nicht die &&-Verknüpfung zu berücksichtigen, da er ja die Suche nach einem Wort einwandfrei ausführt und daher verstehe ich das auch nicht :confused_alt:
 
Und bleibst du bei deiner Aussage, daß weder der Code im if-Zweig, noch der Code im else-Zweig ausgeführt wird? Denn das wäre eigentlich technisch unmöglich. Führ das Programm mal im Debugger aus und setze im if-Zweig und im else-Zweig jeweils einen Breakpoint.
 
ok sorry, hatte da wohl einen Fehler. Der Else-Zweig wird ausgeführt, also dass er die Wörter nicht findet. Aber logisch ist das trotzdem nicht, da es eigentlich true zurückgeben soll, da ja beide Wörter eingegeben wurden.

Den Wert -1 gibt es bei "false" zurück und ich frage ja ab, ob der Wert NICHT -1, also true ist. Wenn ich aber "Hallo Welt" eingebe, liefert er trotzdem den Else-Teil zurück.
 
Weder das eine noch das andere Programm haben so oder ähnlich jemals funktioniert. Der Grund:
Eine Abfrage gegen Fehlercode mit einer positiven Ausgabe verknüpfen ist schon ein Kracher.

Find() liefert die Position in der durchsuchten Zeichenkette oder Länge der durchsuchten Zeichenkette (ist dann also am Ende angelangt ohne Erfolg).

&& wird erst erfüllt, wenn die Rückgaben von A und B gleich sind, was bei unterschiedlicher Position im Text unwahrscheinlich ist.
Wird A nicht erfüllt, wird B gar nicht erst geprüft.
!= -1 ist aber immer der Fall, selbst wenn nach "Popel" in "Hallo Welt" gesucht wird.

Gehe in dich und überdenke die if-Anweisungen nochmal.
 
Ich würde dir empfehlen die ganze Vorgehensweise zu überdenken. Dein Ansatz wird nämlich nicht skalieren. Sprich nach je mehr Wörtern du suchst, umso längert wird es dauern.
Zudem ist dein Code im Moment nicht dynamisch.

Ich würde die Eingabe in einzelne Wörter (Tokens) zerlegen und dann jedes der Wörter in einer Hash-Tabelle nachsehen.
In der Hash-Tabelle sollte dann eine Aktion bzgl. dem Wort verknüpft sein.

Die Hash-Tabelle kann dann ja beliebig erweitert werden.

So viel von meiner Seite.
 
Plaste schrieb:
Find() liefert die Position in der durchsuchten Zeichenkette oder Länge der durchsuchten Zeichenkette (ist dann also am Ende angelangt ohne Erfolg).

Nee, nicht wirklich. find() liefert entweder den Index, an der erste Treffer gefunden wurde, oder std::string::npos, wenn kein Treffer gefunden wurde. npos ist eine Konstante vom Typ std::size_t, die wenn man sie nach int castet, -1 ergibt. Von daher könnte sein Code theoretisch schon funktionien, oder.

@Crysko: Bedenkst du auch, daß find() case-sensitive ist? "Hallo Welt" ist also nicht das selbe wie "hallo welt".
 
Dein Problem ist, dass du mit
Code:
std::cin >> Eingabe;
nur das erste Wort einliest.
 
Danke für eure Antworten!

Habe es jetzt geschafft, die Variable "Eingabe" (die ja ein String ist) in ihre einzelnen Wörter zu zerlegen (Tokens). Dazu habe ich einen kleinen Tokenizer im Internet gefunden, der das recht einfach machen kann.

Jetzt werde ich versuchen, diese einzelnen Tokens via Schleife in einen Vektor bzw. eine Liste zu speichern, damit ich diese einzeln abrufen kann. Aber das Problem ist dabei, dass ich ja nie weiß, was der Benutzer genau eingibt und wie viele Wörter in seiner Eingabe vorkommen. Daher kann ich ja nicht einfach sagen: Liste.at(2) - wo man normalerweise den dritten Listeneintrag anspricht, wenn in der Benutzereingabe nur 2 Wörter vorkommen.

Da muss ich noch schauen, wie ich das mache. Bin halt nicht so der C++-Experte. Aber Ideen und Vorschläge sind immer willkommen :)
 
Kannst du nicht die Anzahl der Elemente in der Liste abfragen?
 
Ja das schon. Könnte dann mit einer for-Schleife die Anzahl der Listeneinträge durchgehen und bei jedem Schleifendurchgang nach den Wörtern suchen, die zu suchen sind und dann evtl. zwei bool-Variablen (bei zwei zu suchenden Wörtern) auf true setzen, sobald sie gefunden wurden. Damit geht's dann mit der Reaktion des Computers weiter.

Mal sehen, ob ich diese Theorie praktisch so hinbekomme ;)
Ergänzung ()

Das hat geklappt!
Ich weiß nicht, ob der Code gut oder dynamisch ist, aber so klappt es jedenfalls ;)

Code:
//Vektor für die einzugebenden Wörter erstellen
vector<string> EingabeWoerter;
vector<string>::iterator i;

//bool-Variablen für die Weiterverarbeitung, ob die Wörter gefunden wurden
bool Wort1Gefunden = false;
bool Wort2Gefunden = false;

...
/*
hier kommt der Tokenizer zum Einsatz, der die Eingabe in die Wörter
aufteilt und in den Vektor "EingabeWoerter" schiebt
*/
...

//Die Liste der Wörter durchgehen und nach zwei bestimmten Wörtern suchen
for (i = EingabeWoerter.begin(); i < EingabeWoerter.end(); i++)
{
   if ((*i).find("Hallo", 0) != -1)
   {
      Wort1Gefunden = true;
   }

   if ((*i).find("Welt", 0) != -1)
   {
      Wort2Gefunden = true;
   }
}

//Die bool-Variablen abfragen und darauf reagieren
if (Wort1Gefunden && Wort2Gefunden)
{
   cout << "Beide Wörter gefunden!" << endl;
}
else
{
   cout << "Nicht alle Wörter gefunden!" << endl;
}

So funktioniert es aber einwandfrei. Vielen Dank für eure Hilfe!!! :)
 
Dynamischer wäre es, wenn du das ganze in eine Funktion umschreibst, die eine Liste der gesuchten Wörter und den Eingabestring annimmt. Der Rückgabewert ist die Anzahl der gefundenen Wörter.
 
Zurück
Oben