FrozenHeart
FrozenHeart

Reputation: 20756

Infinite loop when using regex_search with std::string

Why does the following code result in an infinite loop?

#include <boost/regex.hpp>

#include <iostream>
#include <string>

int main()
{
  const std::string formula = "LAST_BID_EURUSD$ LAST_ASK_USDJPY$";

  boost::smatch matches;
  boost::regex expr("(LAST_(?:BID|ASK)_.+?\\$)");
  while (boost::regex_search(formula, matches, expr))
  {
    std::cout << std::string(matches[1].first, matches[1].second) << std::endl;
  }
}

If I pass iterators to begin and end of formula instead of the formula itself and update the start one accordingly, all works as expected:

#include <boost/regex.hpp>

#include <iostream>
#include <string>

int main()
{
  const std::string formula = "LAST_BID_EURUSD$ LAST_ASK_USDJPY$";

  auto start = formula.begin();
  auto end = formula.end();

  boost::smatch matches;
  boost::regex expr("(LAST_(?:BID|ASK)_.+?\\$)");
  while (boost::regex_search(start, end, matches, expr))
  {
    std::cout << std::string(matches[1].first, matches[1].second) << std::endl;
    start = matches[0].second;
  }
}

Output

LAST_BID_EURUSD$
LAST_ASK_USDJPY$

The same goes for C++11 regex.

How is it supposed to be used with std::string objects?

Upvotes: 0

Views: 798

Answers (2)

Marshall Clow
Marshall Clow

Reputation: 16680

In the first snippet, you're making the same call over and over again.

boost::regex_search(formula, matches, expr)

It's really not surprising that this call gives the same results (i.e, succeeds) each time you call it.

In the second snippet, you are updating the start iterator each time through the loop, so the "string" that you're searching keeps getting smaller, until, eventually, the search fails, and the loop terminates.

boost::regex_search(start, end, matches, expr)

Upvotes: 3

Mayukh Sarkar
Mayukh Sarkar

Reputation: 2625

Requires: Type BidirectionalIterator meets the requirements of a Bidirectional Iterator (24.1.4).

This is the line written in boost documentation page. You need to provide Iterators not the object itself.

Boost Documentation

In c++11 documentation

Parameters

first, last - a range identifying the target character sequence

Means it needs iterators to define the range.

C++11 Documentation Page

For your convenience, here is snippet given in the documentation page

#include <string>
#include <map>
#include <boost/regex.hpp>

// purpose: 
// takes the contents of a file in the form of a string 
// and searches for all the C++ class definitions, storing 
// their locations in a map of strings/int's 
typedef std::map<std::string, int, std::less<std::string> > map_type;

boost::regex expression(
   "^(template[[:space:]]*<[^;:{]+>[[:space:]]*)?"
   "(class|struct)[[:space:]]*"
   "(\\<\\w+\\>([[:blank:]]*\\([^)]*\\))?"
   "[[:space:]]*)*(\\<\\w*\\>)[[:space:]]*"
   "(<[^;:{]+>[[:space:]]*)?(\\{|:[^;\\{()]*\\{)");

void IndexClasses(map_type& m, const std::string& file)
{
   std::string::const_iterator start, end;
   start = file.begin();
   end = file.end();
      boost::match_results<std::string::const_iterator> what;
   boost::match_flag_type flags = boost::match_default;
   while(regex_search(start, end, what, expression, flags))
   {
      // what[0] contains the whole string 
      // what[5] contains the class name. 
      // what[6] contains the template specialisation if any. 
      // add class name and position to map: 
      m[std::string(what[5].first, what[5].second)
            + std::string(what[6].first, what[6].second)]
         = what[5].first - file.begin();
      // update search position: 
      start = what[0].second;
      // update flags: 
      flags |= boost::match_prev_avail;
      flags |= boost::match_not_bob;
   }
}

Look at 2nd and 3rd line of the IndexClasses function

Because you are not providing any Iterators, I think, you are running into some kind of infinite loop.

Upvotes: -1

Related Questions