-1

Similar to Parse comma-separated ints/int-ranges in C++,
I want a regex to extract edges from a string: (1,2,1) (2,4,5) (1,4,3) (3,4,10) (3,6,2) (3,5,3) (6,7,6) (4,7,4) where (Node1 number, Node2 number, distance).

I currently am using: std::regex reg_edge("\(.*?\,.*?\,.*?\)"); which does not work (as in not a single match is found).

Since this can also be an XY-Problem, I will state what I want to do: I want the user to enter edges of the graph when creating the graph.

Please suggest a correct regex, or maybe, a better way altogether.
My current code:

void Graph::setEdges() {
    std::string edge_str;
    std::getline(std::cin, edge_str);
    std::istringstream iss(edge_str);
    edge_str.clear();
    while (iss >> edge_str) {
        std::regex reg_edge("\(.*?\,.*?\,.*?\,\)");
        auto reg_begin = std::sregex_iterator(edge_str.begin(), edge_str.end(), reg_edge);
        auto reg_end = std::sregex_iterator();
        for (std::sregex_iterator reg_it = reg_begin; reg_it != reg_end; reg_it++) {
            std::smatch it_match = *reg_it;

        }
    }
}
kesarling He-Him
  • 1,944
  • 3
  • 14
  • 39
  • You may use a simple `reg_edge(R"(\((\d+),(\d+),(\d+)\))")` and then get group values, `reg_it.str(1)`, `reg_it.str(2)` and `reg_it.str(3)`. Well, if you do not need that detailed output, use `reg_edge(R"(\(\d+(?:,\d+){2}\))")` – Wiktor Stribiżew Aug 24 '20 at 13:46
  • For such a simple parse, I'd write the straightforward parsing code. Check for an opening `(`, search to the next `,`, extract the substring. Etc. – Pete Becker Aug 24 '20 at 15:56

1 Answers1

1

You can use the regex \((\d+),(\d+),(\d+)\) with std::sregex_iterator. Note that you have to escape ( and ) to match against them literally. ALso, using a raw literal string makes it easier with regexes.

Then extract each matching group using operator[]. Group 0 is always the whole group, so you want groups 1, 2, and 3 in your case.

std::regex reg(R"(\((\d+),(\d+),(\d+)\))");
std::string str = "(1,2,1) (2,4,5) (1,4,3) (3,4,10) (3,6,2) (3,5,3) (6,7,6) (4,7,4)";
    
auto start = std::sregex_iterator(str.begin(), str.end(), reg);
auto end = std::sregex_iterator{};

for (std::sregex_iterator it = start; it != end; ++it)
{
     std::cout << "Node1 = " << (*it)[1] << ", Node2 = " << (*it)[2]
         << ", Distance = " << (*it)[3] << std::endl;         
}

Here's a demo.

jignatius
  • 6,304
  • 2
  • 15
  • 30