[C++] String nach bestimmten Muster durchsuchen

dabu

Well-known member
ID: 11566
L
20 April 2006
7.229
407
Ich bräuchte mal wieder Hilfe :mrgreen:.

Und zwar suche ich nach einer Möglichkeit einen String untersuchen zu lassen, ob darin ein bestimmtes Muster vorkommt.

Die Teile sehen so aus:
1.1.1 Kapitel 1
1.1.2 Überschrift 2
1.2.1 nächste Überschrift eben

Dazwischen kommen dann aber natürlich auch Zeilen vor, wo es keine Nummer gibt. Ich bräuchte aber genau alle Zeilen, wo diese Nummer vorhanden ist. Wie kann ich die Zeile jetzt mit C++ auf Enthalt dieser Ziffern durchsuchen? Ich kenne zwar strstr(), wo ich nach einem vorgegebenen Teil suchen kann - aber kann ich da zum Beispiel auch Regular Expressions verwenden und wenn ja, wie?
 
Also ich habe sehr wenig Ahnung von c++, aber Googlen nach c++ regular expressions wird dir sicherlich weiterhelfen.
 
Was für Strings nutzt Du?
char* oder std::string oder die CString-Klasse von Microsoft?

Mir wäre nicht bekannt, daß es Funktionen für sowas gäbe. Sowas wäre aber auch leicht zu programmieren.
 
Die Teile sehen so aus:
1.1.1 Kapitel 1
1.1.2 Überschrift 2
1.2.1 nächste Überschrift eben
Die Nummern sind immer dreiteilig? Im Normalfall würde ich eher
1. Haupt-Überschrift1
1.1 Unter-Überschrift1
1.2 Unter-Überschrift2
1.2.1 Unter-Unter-Überschrift
1.3
2.
etc.

erwarten...
Was die Auswertung per Regenechse sicherlich nicht leichter macht.
Nur die dreiteiligen ginge ja vermutlich mit dem regulären Ausdruck "^\d+\.\d+\.\d+" (drei mal eine oder mehrere Ziffern getrennt mit einem Punkt und das Ganze am Zeilenanfang), wenn die Nummern aber auch ein- oder zweiteilig sein können, wird das deutlich komplizierter...
 
Was die Auswertung per Regenechse sicherlich nicht leichter macht.
Nur die dreiteiligen ginge ja vermutlich mit dem regulären Ausdruck "^\d+\.\d+\.\d+" (drei mal eine oder mehrere Ziffern getrennt mit einem Punkt und das Ganze am Zeilenanfang), wenn die Nummern aber auch ein- oder zweiteilig sein können, wird das deutlich komplizierter...

"^\d+(?:\.\d+)*\.? " :ugly: ?
 
"^\d+(?:\.\d+)*\.? " :ugly: ?
Hmmm, "^\d+(\.\d+)*\." hätte ich jetzt verstanden, aber was sagen mir die Fragezeichen und der Doppelpunkt? Davon abgesehen, kenne ich das eigentlich so, dass hinter der letzten Ziffer kein Punkt mehr kommt, wenn es nicht eine Haupt-Überschrift ist (also 1. aber 1.2 und nicht 1.2.). Das müsste dann in den Ausdruck ja auch noch irgendwie sinnvoll rein...
 
Jungs, im Titel steht C++. Wenn ihr solche Regulären Ausdrücke postet, dann doch bitte auch, wie ihr die auf einen C++-String anwenden wollt, ja? :roll:
 
Jungs, im Titel steht C++. Wenn ihr solche Regulären Ausdrücke postet, dann doch bitte auch, wie ihr die auf einen C++-String anwenden wollt, ja? :roll:
Da ich von C++ keinen Plan habe dachte ich, dass ich wenigstens bei den regulären Ausdrücken meinen Senf dazu geben kann. :mrgreen:

Hmmm, "^\d+(\.\d+)*\." hätte ich jetzt verstanden, aber was sagen mir die Fragezeichen und der Doppelpunkt? Davon abgesehen, kenne ich das eigentlich so, dass hinter der letzten Ziffer kein Punkt mehr kommt, wenn es nicht eine Haupt-Überschrift ist (also 1. aber 1.2 und nicht 1.2.). Das müsste dann in den Ausdruck ja auch noch irgendwie sinnvoll rein...
Der letzte Punkt ist optional (daher das Fragezeichen)... das heißt zum Beispiel würde da "3." matchen, weil der die zweite, dritte, ... Zifferngruppe (Zahl) nicht mehr nimmt [das sind die in der runden Klammern]. Das Fragezeichen und der Doppelpunkt kommen bei mir daher, dass diese Gruppierung nicht extra gezählt/erfasst werden müssen (keine Ahnung wie man das richtig formuliert). Kann man dann ggf. sonst auch weglassen, klar... vielleicht besser so. Weiß ja auch nicht, ob der regEx funzt... also bei Perl/PHP sollte er tun. :D
 
Jungs, im Titel steht C++. Wenn ihr solche Regulären Ausdrücke postet, dann doch bitte auch, wie ihr die auf einen C++-String anwenden wollt, ja? :roll:
Stimmt, da steht C++ - Nachdem C++ aber nicht gleich C++ ist, und dabu nicht verraten hat, was für ein C++ er denn verwendet, kann man die konkrete Lösung eh nicht so einfach hinblättern. Deine Frage nach der Art des verwendeten Strings ist ja schon mal ein Schritt in die Richtung, dies zu klären. Nachdem wir auf diese Frage aber noch keine Antwort haben, können wir jetzt auch noch nicht sagen, wie wir die RegExp dann anwenden - zumindest aber schon mal den korrekten Ausdruck zu finden, kann aber doch nicht schaden, oder?

Der letzte Punkt ist optional (daher das Fragezeichen)...
Dann würde aber eine "3" oder eine "3.2." auch Treffer liefern, was wir ja nicht wollen...
 
Was std::string und CString hergeben, hab ich keinen Plan. Ich würde den Fußweg vorschlagen:
PHP:
char* string; // da is dein Text drin
char* ptr = string;
int modus = 0;

while(*ptr)
{
  if(*ptr >= '0' && *ptr <= '9') // wenn Ziffer
  {
    if(modus == 0) // Anfang
      modus = 1; // erste Zahl
    else if(modus == 1) // immer noch erste Zahl
      ; // ok
    /* ... */
  }
  else if(*ptr == '.') // wenn Punkt
  {
    if(modus == 1)
      modus = 2; jetzt zweite Zahl
    /* ... */
  }
  else // irgendwas falsches
  {
    if(modus == 1) // wir erwarten Ziffer oder Punkt
      goto_naechste_zeile();
    /* ... */
  }

  ptr++;
}
edit:
So begegnet einem die theoInf wieder. Ich hasse Automaten :-? :mrgreen:
 
Dann würde aber eine "3" oder eine "3.2." auch Treffer liefern, was wir ja nicht wollen...

Weiß ich nicht, ob wir das nicht wollen. :mrgreen: Könnte ja sein. Aber da lässt sich auch noch ein regEx basteln.. dann halt mit einem oder.. sprich entweder nur eine Zahl und Punkt oder das andere Schema Zahl (Punkt Zahl)*. Kann sich dann denke ich "jeder" selber rumbasteln.
 
Die Nummern sind immer dreiteilig?
Nicht immer... stimmt, das habe ich oben in dem Beispiel jetzt nicht ganz so gut rübergebracht. Es können natürlich auch nur 1 oder 2 Stellen sein.

Was für Strings nutzt Du?
char* oder std::string oder die CString-Klasse von Microsoft?

Ich nutze die std::string. Wobei es auch kein Problem wäre den string in einen char* oder CString umzuwandeln.

@theHacker: Danke, das werde ich mir morgen früh gleich mal genauer anschauen :).
 
Und was für ein C++ verwendest du nun? Im .NET-Framework gibt es z.B. eine RegExp-Klasse, wenn du also VC++.NET verwendet solltest, könntest du diese einsetzen...

Der Fußweg von tH klappt natürlich in diesem Fall auch, da es sich ja doch noch um ein recht einfaches Muster handelt (das insbesondere auch am Zeilenanfang liegt, sonst wäre es zu Fuß nochmal etwas haariger).
 
Und was für ein C++ verwendest du nun? Im .NET-Framework gibt es z.B. eine RegExp-Klasse, wenn du also VC++.NET verwendet solltest, könntest du diese einsetzen...

Ich nutze VC++.NET :). Aber ich hab jetzt bereits den Fußweg von theHacker genommen. Ich werde mir das aber trotzdem noch anschauen und evtl. umbauen, falls dies kürzer und schöner sein sollte...
 
Es geht zwar um etwas anderes, aber ich will wegen der Kleinigkeit jetzt keinen neuen Thread starten.

Ich denke die Frage ist recht einfach, aber dennoch brauche ich Hilfe:
Und zwar müsste ich einen Dialog mit Übergabeparameter haben. Ich weiß, dass ich einen neuen Dialog mit DoModal() starten kann, aber gibt es auch eine Möglichkeit da ein Parameter zu übergeben?

Ich könnte zwar meinen Parameter irgendwo ablegen und dann im neuen Dialog wieder holen, aber ich denke da gibt es bestimmt eine bessere Lösung für. Hat da jemand vielleicht eine Idee?

P.S.: Sorry für Doppelposting. Aber wie gesagt will ich keinen extra Thread machen :biggrin:.
 
Du überschreibst einfach die Methode doModal() und rufst innerhalb Deiner Methode mit Dialog::doModal() die Methode der Basisklasse Dialog auf.