std::regex



  • Hallo da,
    ich bastele gerade an diesem nichtsonnigen Mittag an regexen herum, komme aber noch nicht so ganz auf den Trichter.

    Ich habe folgende regex:

    const std::wregex pattern( L"\\s*(\\d{1,2})\\s*(;\\s*(\\d{1,2})\\s*)*" );
    

    die Strings wie "43;2;4; 4 ; 1" matchen soll, und ich glaube das tut sie auch. Was ich mich nun frage ist, ob es irgendwie eine Möglichkeit gibt, die hintere Wiederholung ohne gleichzeitige umschließende Capture-Gruppe durchzuführen, also ob es eine Klammer gibt, die nicht gleich captured. Mich interessieren hinterher ja schlicht die Zahlen.

    Viele Grüße,
    Deci



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (auch C++0x und C++11) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • bei einer EBNF werden gleiche Teile in einer allgemeinen Regel zusammengefaßt, die man dann an verschiedenen Stellen aufruft. bei einem regulären Ausdruck geht das nicht, deshalb hat man da immer diese Wiederholungen drinne. man kann sich den Gesamtausdruck (als String) aber mit Präprozessor oder std::string aus Teilstrings zusammensetzen



  • Huch?



  • Also es ist natürlich auch nervig, sich dort wiederholen zu müssen, da hast Du natürlich Recht, aber mit meiner Frage wollte ich auf etwas anderes abzielen.
    Wenn ich das besagte Muster per regex_match auf den String "1;2" anwende, bekomme ich als Resultat "1;2", "1", ";2" und "2". Ich würde das Muster gern so hinbekommen, dass ich die Resultate "1" und "2" erhalte.



  • ich meinte ungefähr so:

    #define MYSUBEXPR "\\s*(\\d{1,2})\\s*"
      const std::regex pattern(MYSUBEXPR "(;" MYSUBEXPR ")*");
    


  • dd, du bis ganz am falschen thema. kann er klammen zum Binden benutzen, ohne daß die im Ergebnis Strings erzeugen?



  • Das geht mit einer Non-Capturing Group: "(?:expr)".



  • Ich habe es durch die Channel9-Präsentation von STL und dann über non capturing groups gefunden. (?: ist die Einleitung einer non capturing group!

    Edit: Danke Michael E., ich kam leider zu spät!



  • Okay, das funktioniert zwar vom matching-Standpunkt aus, aber so kann ich nicht die Zahlen aus einem String mit beliebiger anzahl von auftretenden Gruppen rausparsen. Am Ende steht halt für jede Gruppe genau ein Ergebnis da und das ist natürlich das letzte: "1;2;3" => "1" und "3". Kann ich das erfolgreiche Auftreten/Parsen einer Gruppe irgendwie dazu veranlassen, mich mit dem Ergebnis zu benachrichtigen, sodass ich selber eine Liste anfertigen kann?

    Edit: Ich könnte natürlich mit "\\s*;\\s*" tokenizen und die Tokens hinterher nochmal durch eine andere regex laufen lassen, aber es muss doch einen Dreizeiler geben für das, was ich vorhabe O.O

    Edit #2:

    So sieht das jetzt aus, wobei ich den Eindruck bekomme, dass ich gleich mit 2 Kanonen auf einen Spatzen schieße...

    const std::wregex tokenpattern( L"[^;]" );
    const std::wregex numberpattern( L"\\s*(\\d{1,2})\\s*" );
    std::match_results<std::wstring::const_iterator> result;
    std::regex_token_iterator<std::wstring::const_iterator> end;
    std::regex_token_iterator<std::wstring::const_iterator> it( selection.begin(), selection.end(), tokenpattern );
    
    for( unsigned int i=0; it != end; ++it, ++i ) {
    	std::wstring str = it->str();
    	std::regex_match( str, result, numberpattern );
            // ...
    }
    


  • Langsam wird's mir unklar.

    Was soll bei "2;3;5;7;11;13;17;19" herauskommen?
    Und sind die Formatbeschränkungen (abgesehen von whitespaces nur, daß mindestens eine Zahl in der Liste ist, jede Zahl eine oder zwei Ziffern hat und zwischen zei Zahlen stets ein Semikolon stehen muss?



  • Ja genau Volkard! (Siehe den Edit meines vorigen Posts, wie ich das jetzt hingefummelt habe)

    "2", "3", "5", "7", "11", "13", "17", "19" hätte ich gerne. Ich brauche keine komplette Liste, mir würde auch reichen, die in dieser Reihenfolge aufgezählt zu bekommen.



  • ich hatte bisher mit QRegExp gearbeitet, die verhalten sich etwas anders. mit std::regex kann man das etwa so machen:

    #include <string>
    #include <iostream>
    #include <regex>
    
    int main ()
      {
      std::regex Pattern("(\\d+);");
      std::smatch Match;
      std::string Data = "12;34;56;78;90;";
      std::string::const_iterator Begin = Data.begin();
      std::string::const_iterator End = Data.end();
    
      while (std::regex_search(Begin, End, Match, Pattern,
             std::regex_constants::match_continuous))
        {
        Begin = Match[0].second;
        std::cout << Match[1] << std::endl;
        }
      }
    

Anmelden zum Antworten