1

I am trying to use the Regex library tools to extract double and integer parameters from a text file. Here is a minimal code that captures the 'std::regex_error' message I've been getting:

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

int main ()
{
  std::string My_String = "delta = -002.050";
  std::smatch Match;
  std::regex Base("/^[0-9]+(\\.[0-9]+)?$"); 

  std::regex_match(My_String,Match,Base);

  std::ssub_match Sub_Match = Match[1];
  std::string Sub_String = Sub_Match.str();
  std::cout << Sub_String << std::endl;

  return 0;
}

I am not much familiar with the Regex library, and couldn't find anything immediately useful. Any idea what causes this error message? To compile my code, I use g++ with -std=c++11 enabled. However, I am sure that the problem is not caused by my g++ compiler as suggested in the answers given to this earlier question (I tried several g++ compilers here).

I expect to get "-002.050" from the string "delta = -002.050", but I get:

terminate called after throwing an instance of 'std::regex_error' what(): regex_error Abort

Community
  • 1
  • 1
S.G.
  • 357
  • 2
  • 15
  • what is the problem exactly, what is the output your expecting and what are you getting? – Samer Nov 04 '14 at 15:37

3 Answers3

3

Assuming you have gcc4.9 (older versions do not ship with a libstdc++ version that supports <regex>), then you can get the desired result by changing your regex to

std::regex Base("[0-9]+(\\.[0-9]+)?");

This will capture the fractional part of the floating point number in the input, along with the decimal point.

There are a couple of problems with your original regex. I think the leading / is an error. And then you're trying match the entire string by enclosing the regular expression in ^...$, which is clearly not what you want.

Finally, since you only want to match part of the input string, and not the entire thing, you need to use regex_search instead of regex_match.

std::regex Base(R"([0-9]+(\.[0-9]+)?)"); // use raw string literals to avoid
                                         // having to escape backslashes

if(std::regex_search(My_String,Match,Base)) {
  std::ssub_match Sub_Match = Match[1];
  std::string Sub_String = Sub_Match.str();
  std::cout << Sub_String << std::endl;
}

Live demo


I expect to get "-002.050" from the string "delta = -002.050"

To do that, modify the regex in the example above to

std::regex Base(R"(([+-]{0,1}[0-9]+\.[0-9]+))");

The above will match a single, optional, leading + or - sign.

Praetorian
  • 106,671
  • 19
  • 240
  • 328
0

The leading forward slash doesn't look right. Also, it looks like you are trying to match an entire line, due to the leading ^ and trailing $, but I'm not really sure that is what you want. Also, your expression isn't matching the negative sign.

Try this:

std::regex Base("-?[0-9]+(\\.[0-9]+)?$");
Matt Jacobi
  • 864
  • 7
  • 17
0

I think you are getting an error because what within the smatch object
is not valid.

To avoid this you have to check for a match.

Beyond that a general regex is

 #  "(?<![-.\\d])(?=[-.\\d]*\\d)(-?\\d*)(\\.\\d*)?(?![-.\\d])"

 (?<! [-.\d] )       # Lookbehind, not these chars in behind
                     # This won't match like  -'-3.44'
                     # Remove if not needed

 (?= [-.\d]* \d )    # Lookahead, subject has to contain a digit

                     # Here, all the parts of a valid number are
                     # in front, now just define an arbitrary form 
                     # to pick them out.
                     # Note - the form is all optional, let the engine
                     # choose what to match.
                     # -----------------  

 ( -? \d* )          # (1), Required group before decimal, can be empty
 ( \. \d* )?         # (2), Optional group, can be null
                     #      change to (\.\d*) if decimal required

 (?! [-.\d] )        # Lookahead, not these chars in front
                     # This won't match like  '3.44'.66
                     # Remove if not needed

Sample output:

 **  Grp 0 -  ( pos 9 , len 8 ) 
-002.050  
 **  Grp 1 -  ( pos 9 , len 4 ) 
-002  
 **  Grp 2 -  ( pos 13 , len 4 ) 
.050  

-----------------

 **  Grp 0 -  ( pos 28 , len 3 ) 
.65  
 **  Grp 1 -  ( pos 28 , len 0 )  EMPTY 
 **  Grp 2 -  ( pos 28 , len 3 ) 
.65  

-----------------

 **  Grp 0 -  ( pos 33 , len 4 ) 
1.00  
 **  Grp 1 -  ( pos 33 , len 1 ) 
1  
 **  Grp 2 -  ( pos 34 , len 3 ) 
.00  

-----------------

 **  Grp 0 -  ( pos 39 , len 4 ) 
9999  
 **  Grp 1 -  ( pos 39 , len 4 ) 
9999  
 **  Grp 2 -  NULL 

-----------------

 **  Grp 0 -  ( pos 104 , len 4 ) 
-99.  
 **  Grp 1 -  ( pos 104 , len 3 ) 
-99  
 **  Grp 2 -  ( pos 107 , len 1 ) 
.