problem ze zrozumieniem regex_search

0

Witam
Próbuję się nauczyć regexa i nie rozumiem jak działa regex_search. Tzn. wiem że zwraca true jak sekwencja jest substringiem, ale on tam ma jeszcze argument smatch it ego nie kumam jak
to może być użyteczne.

#include <stdio.h>
#include <regex>
#include <iostream>
#include <string>

int main()
{
    std::regex pattern("^(abc)+.xz");
    std::string text {"abc.xz"};
    std::smatch s;
    if(std::regex_search(text,s,pattern)) {
        std::cout << "found seq" << std::endl;
        for(auto x: s)
            std::cout << x << std::endl;
    }

    return 0;
}

Output spodziewałbym się że będzie abc.xz a jest:
abc.xz
abc

Jak dam powyżej

std::regex pattern("(abc)");
std::string text {"abc"};

to dwa razy otrzymuję jako output abc. Czemu nie raz?

3

std::string text {"abc.xz.abc.xz.abc"};
Zobacz co będzie z tym, sam sobie odpowiesz.

0

@_13th_Dragon: To powinno mieć taką funkcjonalność, że ten poniżej algorytm powinien zwracać wektor słów z pominięciem white znaków:

#include <stdio.h>
#include <regex>
#include <iostream>
#include <string>
#include <vector>

std::vector<std::string> getWords(const std::string& text)
{
    std::vector<std::string> output;
    std::regex pattern("[^\\s*]*");
    std::smatch s;
    if(regex_search(text,s,pattern))
        for(const auto& x : s)
            output.push_back(x);
    
    return output;
}

int main()
{
    std::vector<std::string> vec = getWords("Ala ma kota\ni psa");
    for(const auto& x: vec)
        std::cout << x << std::endl;

    return 0;
}

A zmienna s tylko przechowuje słowo "Ala". Coś totalnie spieprzyli w stlu w tej funkcji regex_search. Lepiej tego w ogóle nie używać do takich rzeczy jak wyżej bo to totalnie inaczej działa niż nazwa wskazuje.
Chyba że może ta funkcja wykonuje swoj algorytm dopóki nie uzna że jest już true i wtedy wychodzi i dlatego mamy tylko słowo Ala bez reszty.

3

Kliku kliku:

In order to examine all matches within the target sequence, std::regex_search may be called in a loop, restarting each time from m[0].second of the previous call. std::regex_iterator offers an easy interface to this iteration.

Do tego co chcesz zrobić w drugim poście służy regex_iterator
https://godbolt.org/z/jjTKTq3fY

std::vector<std::string> getWords(const std::string& text)
{
    std::vector<std::string> output;
    std::regex pattern("[^\\s]*");
    std::transform(
        std::sregex_iterator{begin(text), end(text), pattern},
        std::sregex_iterator{}, std::back_inserter(output),
        [](const auto& match) {return match.str();});
    return output;
}

A jak chcesz mogę zaraz wysmażyć Ci wersję na matchu...

EDIT: proszę https://godbolt.org/z/5r4encjY9


std::vector<std::string> getWords(const std::string& text)
{
    using std::regex_constants::match_not_null;
    std::vector<std::string> output;
    std::regex pattern("[^\\s]*");
    std::smatch s;
    while(regex_search(s.ready() ? s[0].second : begin(text), end(text), s, pattern, match_not_null)) {
        output.push_back(s.str());
    }
    return output;
}


0

To powinno mieć taką funkcjonalność, że ten poniżej algorytm powinien zwracać wektor słów z pominięciem white znaków:
...
Coś totalnie spieprzyli w stlu w tej funkcji regex_search.
...itd

aha
zamiast narzekać przeczytaj z uwagą i zrozumieniem C++ Wyrażenia regularne (C++11 / boost)
a tutaj masz jedno z możliwych rozwiązań swojego problemu

std::vector<std::string> getWords(const std::string& text)
{
    std::vector<std::string> output;
    string tekst = text;
    const regex pattern("(\\s)");
    tekst = regex_replace(tekst, pattern, " ");
    const regex spaces("([[:space:]]+)");
    tekst = regex_replace(tekst, spaces, " ");
    output.push_back(tekst);
    return output;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1