C++ Regex infinite loop

Viewed 307

I'm writing a c++ program that regex's to find the cells mentioned in a give excel range string

e.g.

$C$5

$CC$4

$C$5:$F$89

because of the need to either match only once (i.e only one cell is being mentioned in the string) or twice (i.e. for when two cells are mentioned in the string; its a range) I have designed my program as thus:

    //get the cell being mentioned
    std::regex regx("\\$(\\w+)\\$(\\d+)"); 
    std::smatch match;
    //match[0] = whole match (only useful for debug) 
    //match[1] = first cell col letter ; match[2] = first cell row numb
    //match[3] = second cell col letter; match[4] = second cell row numb
    /*vectors for putting columns and rows values extracted in the while loop into*/
    std::vector<std::string> vecCol;
    std::vector<std::string> vecRow;

    //put all substring matches into a vector - This loop runs infinitely
    while (std::regex_search(inString.begin(),inString.end(), match, regx)) {
        std::cout << match[0] << "\n";
        //add them to the vecs
        vecCol.push_back(match[1].str());
        vecRow.push_back(match[2].str());
    }

the while loop causes an issue I don't quite understand; it gets trapped in an infinite loop and continues to add in the same substring match (e.g. C4) each time round infinitely. this happens even if there is only one cell mentioned in the string that is passed in

Please can anyone explain what I'm getting wrong with this C++ regex?

1 Answers

Inside your while loop, you do not change the inString, nor are you using an iterator that would move the regex index, so you constantly get one and the same match, and there is no break condition inside the loop.

Use

while (std::regex_search(inString, match, regx)) {
        std::cout << match[0] << "\n";
        vecCol.push_back(match[1].str());
        vecRow.push_back(match[2].str());
        inString = match.suffix().str();

See the C++ demo. Output: $C$5 and $F$89.

Note it will change inString. If you do not want it, use the sregex_iterator:

for(std::sregex_iterator i = std::sregex_iterator(inString.begin(), inString.end(), regx);
                         i != std::sregex_iterator();
                         ++i)
{
    std::smatch match = *i;
    std::cout << "Whole match: " << match.str() << ", Group 1: " << match.str(1) << ", and Group 2: " << match.str(2) << '\n';
    //add them to the vecs
    vecCol.push_back(match.str(1));
    vecRow.push_back(match.str(2));
}

See the C++ demo, output:

Whole match: $C$5, Group 1: C, and Group 2: 5
Whole match: $F$89, Group 1: F, and Group 2: 89
Related