Was gibt std::match_results::size zurück?

Lesezeit: 4 Minuten

Was gibt stdmatch resultssize zuruck
Morpheu5

Ich bin etwas verwirrt über den folgenden C++ 11-Code:

#include <iostream>
#include <string>
#include <regex>

int main()
{
    std::string haystack("abcdefabcghiabc");
    std::regex needle("abc");
    std::smatch matches;
    std::regex_search(haystack, matches, needle);
    std::cout << matches.size() << std::endl;
}

Ich würde erwarten, dass es ausgedruckt wird 3 aber stattdessen bekomme ich 1. Übersehe ich etwas?

  • Sie erhalten nur 1 Übereinstimmung pro Suche.

    – Wiktor Stribiżew

    24. September 2015 um 15:41 Uhr


Was gibt stdmatch resultssize zuruck
Wiktor Stribiżew

Du erhältst 1 da regex_search gibt nur 1 Übereinstimmung zurück, und size() gibt die Anzahl der Erfassungsgruppen + den gesamten Übereinstimmungswert zurück.

Dein matches ist…:

Gegenstand von a match_resultate Typ (z. B. cmatch oder smatch), der von dieser Funktion mit Informationen zu den Übereinstimmungsergebnissen und allen gefundenen Teilübereinstimmungen gefüllt wird.

Wenn [the regex search is] erfolgreich ist, ist es nicht leer und enthält eine Reihe von sub_match-Objekten: das erste sub_match -Element entspricht der gesamten Übereinstimmung, und wenn der Regex-Ausdruck zu vergleichende Unterausdrücke enthielt (dh durch Klammern getrennte Gruppen), werden ihre entsprechenden Unterübereinstimmungen als aufeinanderfolgende sub_match-Elemente im Objekt match_results gespeichert.

Hier ist ein Code, der mehrere Übereinstimmungen findet:

#include <string>
#include <iostream>
#include <regex>
using namespace std;
int main() {
  string str("abcdefabcghiabc");
  int i = 0;
  regex rgx1("abc");
  smatch smtch;
  while (regex_search(str, smtch, rgx1)) {
        std::cout << i << ": " << smtch[0] << std::endl;
        i += 1;
        str = smtch.suffix().str();
  }
  return 0;
}

Sehen IDEONE-Demo Rückkehr abc dreimal.

Da diese Methode die Eingabezeichenfolge zerstört, ist hier eine weitere Alternative basierend auf der std::sregex_iterator (std::wsregex_iterator sollte verwendet werden, wenn Ihr Thema ein ist std::wstring Objekt):

int main() {
    std::regex r("ab(c)");
    std::string s = "abcdefabcghiabc";
    for(std::sregex_iterator i = std::sregex_iterator(s.begin(), s.end(), r);
                             i != std::sregex_iterator();
                             ++i)
    {
        std::smatch m = *i;
        std::cout << "Match value: " << m.str() << " at Position " << m.position() << '\n';
        std::cout << "    Capture: " << m[1].str() << " at Position " << m.position(1) << '\n';
    }
    return 0;
}

Sehen IDEONE-DemoRückkehr

Match value: abc at Position 0
    Capture: c at Position 2
Match value: abc at Position 6
    Capture: c at Position 8
Match value: abc at Position 12
    Capture: c at Position 14

  • Hinweis: Das obige Beispiel wird schlagen str Machen Sie also eine Kopie, wenn Sie sie behalten müssen. Das Wichtige ist, zu erhalten smatch.suffix().str() die den Text zurückgibt nach dem das Spiel. Die while Schleife wiederholt die Übereinstimmung mit der verbleibenden Zeichenfolge, bis keine Übereinstimmungen mehr gefunden werden.

    – Herr Lama

    24. September 2015 um 15:48 Uhr

  • Ja, stimmt, um zu halten strverwenden Sie einfach seine Kopie.

    – Wiktor Stribiżew

    24. September 2015 um 15:50 Uhr

  • @Morpheu5, wenn noch etwas unklar ist, lass es mich bitte wissen.

    – Wiktor Stribiżew

    24. September 2015 um 21:20 Uhr

  • Ich habe die Antwort mit einer anderen aktualisiert std::sregex_iterator-basierte Methode zum Abrufen aller (Teil-)Übereinstimmungen mit ihren Positionen innerhalb der Eingabezeichenfolge.

    – Wiktor Stribiżew

    26. November 2015 um 15:21 Uhr

Was gibt stdmatch resultssize zuruck
Toby Speight

Was dir fehlt, ist das matches wird mit einem Eintrag für jede Erfassungsgruppe gefüllt (einschließlich der gesamten übereinstimmenden Teilzeichenfolge als 0. Erfassung).

Wenn du schreibst

std::regex needle("a(b)c");

dann bekommst du matches.size()==2mit matches[0]=="abc"und matches[1]=="b".

1646313608 871 Was gibt stdmatch resultssize zuruck
Arn Vogel

BEARBEITEN: Einige Leute haben diese Antwort abgelehnt. Das kann verschiedene Gründe haben, aber wenn es nicht auf die von mir kritisierte Antwort zutrifft (niemand hat einen Kommentar hinterlassen, um die Entscheidung zu erklären), sollten sie zur Kenntnis nehmen, dass W. Stribizew den Code zwei Monate geändert hat nach dem Ich habe dies geschrieben, und ich war mir dessen bis heute, dem 18.01.2021, nicht bewusst. Der Rest der Antwort ist unverändert, seit ich sie zum ersten Mal geschrieben habe.

Die Lösung von @stribizhev hat eine quadratische Worst-Case-Komplexität für vernünftige reguläre Ausdrücke. Bei verrückten (z. B. “y*”) endet es nicht. Bei einigen Anwendungen können diese Probleme auftreten DoS-Angriffe warten darauf, dass es passiert. Hier ist eine gefixte Version:

string str("abcdefabcghiabc");
int i = 0;
regex rgx1("abc");
smatch smtch;
auto beg = str.cbegin();
while (regex_search(beg, str.cend(), smtch, rgx1)) {
    std::cout << i << ": " << smtch[0] << std::endl;
    i += 1;
    if ( smtch.length(0) > 0 )
        std::advance(beg, smtch.length(0));
    else if ( beg != str.cend() )
        ++beg;
    else
        break;
}

Nach meiner persönlichen Vorliebe findet dies n+1 Übereinstimmungen einer leeren Regex in einem String der Länge n. Sie können die Schleife auch einfach nach einem leeren Match verlassen.

Wenn Sie die Leistung für eine Zeichenfolge mit Millionen von Übereinstimmungen vergleichen möchten, fügen Sie die folgenden Zeilen nach der Definition von hinzu str (und vergessen Sie nicht, Optimierungen einzuschalten), einmal für jede Version:

for (int j = 0; j < 20; ++j)
    str = str + str;

923790cookie-checkWas gibt std::match_results::size zurück?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy