Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is returned in std::smatch and how are you supposed to use it?

Tags:

c++

regex

string "I am 5 years old"

regex "(?!am )\d"

if you go to http://regexr.com/ and apply regex to the string you'll get 5. I would like to get this result with std::regex, but I do not understand how to use match results and probably regex has to be changed as well.

std::regex expression("(?!am )\\d");
std::smatch match;
std::string what("I am 5 years old.");
if (regex_search(what, match, expression))
{
     //???
}
like image 644
Kimi Avatar asked Jun 14 '17 09:06

Kimi


People also ask

What is smatch in c++?

smatch | Regex (Regular Expressions) in C++ smatch is an instantiation of the match_results class template for matches on string objects.

What is regex CPP?

Regular Expression or regexes or regexp as they are commonly called are used to represent a particular pattern of string or text. Regexes are often used to denote a standard textual syntax of a string. => Visit Here To See The C++ Training Series For All.


1 Answers

The std::smatch is an instantiation of the match_results class template for matches on string objects (with string::const_iterator as its iterator type). The members of this class are those described for match_results, but using string::const_iterator as its BidirectionalIterator template parameter.

std::match_results supports a operator[]:

If n > 0 and n < size(), returns a reference to the std::sub_match representing the part of the target sequence that was matched by the nth captured marked subexpression).

If n == 0, returns a reference to the std::sub_match representing the part of the target sequence matched by the entire matched regular expression.

if n >= size(), returns a reference to a std::sub_match representing an unmatched sub-expression (an empty subrange of the target sequence).

In your case, regex_search finds the first match only and then match[0] holds the entire match text, match[1] would contain the text captured with the first capturing group (the fist parenthesized pattern part), etc. In this case though, your regex does not contain capturing groups.

Here, you need to use a capturing mechanism here since std::regex does not support a lookbehind. You used a lookahead that checks the text that immediately follows the current location, and the regex you have is not doing what you think it is.

So, use the following code:

#include <regex>
#include <string>
#include <iostream>
using namespace std;

int main() {
    std::regex expression(R"(am\s+(\d+))");
    std::smatch match;
    std::string what("I am 5 years old.");
    if (regex_search(what, match, expression))
    {
         cout << match.str(1) << endl;
    }
    return 0;
}

Here, the pattern is am\s+(\d+)". It is matching am, 1+ whitespaces, and then captures 1 or more digits with (\d+). Inside the code, match.str(1) allows access to the values that are captured with capturing groups. As there is only one (...) in the pattern, one capturing group, its ID is 1. So, str(1) returns the text captured into this group.

The raw string literal (R"(...)") allows using a single backslash for regex escapes (like \d, \s, etc.).

like image 178
Wiktor Stribiżew Avatar answered Sep 17 '22 20:09

Wiktor Stribiżew