2

What is the best way if you want to read a input like this:

(1,13) { (22,446) (200,66) (77,103) } 
(779,22) {  } // this is also possible, but always (X,X) in the beginning

I would like to use regular expressions for doing it. But there is little info on usage of reqexp when parsing a string with more than only numbers. Currently im trying something similar with sscanf (from the c-library):

string data;
getline(in, data); // format: (X,X) { (Y,Y)* } 
stringstream ss(data);
string point, tmp;
ss >> point; // (X,X)
// (X,X) the reason for three is that they could be more than one digit.
sscanf(point.c_str(), "(%3d,%3d)", &midx, &midy); 

int x, y;
while(ss >> tmp) // { (Y,Y) ... (Y,Y) }
{
    if(tmp.size() == 5)
    {
        sscanf(tmp.c_str(), "(%3d,%3d)", &x, &y);
        cout << "X: " << x << " Y: " << y << endl;  
    }
}

The problem is that this does not work, as soon as there is more than one digit sscanf does not read the numbers. So is this the best way to go, or is there a better solution with regexp? I don´t want to use boost or something like that as this is part of a school assignment.

3
  • do you just want the numbers? is it ALWAYS going to have this format? Commented Jun 11, 2014 at 15:31
  • Well it could be something like: (X,X) { (Y,Y)* } meaning it could look like (X,X) { } as well Commented Jun 11, 2014 at 15:34
  • @vico I edited the question for clarification. Commented Jun 11, 2014 at 15:36

2 Answers 2

1

Maybe the following piece of code matches your requirements:

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

int main()
{
  std::smatch m;
  std::string str("(1,13) { (22,446) (200,66) (77,103) }");
  std::string regexstring = "(\\(\\s*\\d+\\s*,\\s*\\d+\\s*\\))\\s*(\\{)(\\s*\\(\\s*\\d+\\s*,\\s*\\d+\\s*\\)\\s*)*\\s*(\\})";
  if (std::regex_match(str, m, std::regex(regexstring))) {
    std::cout << "string literal matched" << std::endl;
    std::cout << "matches:" << std::endl;
    for (std::smatch::iterator it = m.begin(); it != m.end(); ++it) {
      std::cout << *it << std::endl;
    }
  }

  return 0;
}

Output:

enter image description here

Sign up to request clarification or add additional context in comments.

Comments

1

Assuming you're using C++11, you could use something like: std::regex pattern(r"\((\d+),(\d+)\)\s*\{(\s*\(\d+,\d+\))+\s*\}") (Disclaimer: This hasn't been tested), and then use it like so:

std::smatch match;
while (ss >> tmp) {
   if (std::regex_match(tmp, match, pattern)) {
      // match[0] contains the first number as a string
      // match[1] contains the second number as a string
      // match[2] contains the list of points
   }
}

1 Comment

Yes, raw strings are a lifesaver for regexen.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.