C ++ регулярное выражение заменить на функцию обратного вызова - PullRequest
0 голосов
/ 26 октября 2019

У меня есть карта, в которой хранится привязка идентификатора к значению, входная строка может содержать несколько идентификаторов. Мне нужно заменить эти идентификаторы их соответствующими значениями. Например:

string = "I am in #1 city, it is now #2 time" // (#1 and #2 are ids here)
id_to_val_map = {1 => "New York", 2 => "summer"}

Требуемый вывод:

"I am in New York city, it is now summer time"

Есть ли способ получить функцию обратного вызова (которая принимает согласованную строку и возвращает строку, которая будет использоваться в качестве замены)std::regex_replace, кажется, не поддерживает это.

Альтернатива состоит в том, чтобы найти все совпадения, затем вычислить их значения замены и затем выполнить фактическую замену. Что не будет таким эффективным.

Ответы [ 2 ]

1 голос
/ 26 октября 2019

Доморощенный способ состоит в том, чтобы использовать цикл while с regex_search (), а затем
строить выходную строку по мере продвижения.

По сути, это то, что regex_replace () делает за один проход.

Нет необходимости выполнять отдельное регулярное выражение для каждого элемента карты, который имеет накладные расходы
переназначения для каждого элемента ( s = regex_replace () ), а также для покрытия того же
недвижимость с каждым пропуском.

Примерно это регулярное выражение

 (?s)
 ( .*? )                       # (1)
 (?:
      \#
      ( \d+ )                       # (2)
   |  $
 )

с этим кодом

typedef std::string::const_iterator SITR;
typedef std::smatch X_smatch;
#define REGEX_SEARCH std::regex_search

std::regex _Rx =  std::regex( "(?s)(.*?)(?:\\#(\\d+)|$)" );

SITR start = oldstr.begin();
SITR end   = oldstr.end();
X_smatch m;

std::string newstr = "";

while ( REGEX_SEARCH( start, end, m, _Rx ) )
{
    newstr.append( m[1].str() );

    if ( m[2].matched ) {
    {
        // append the map keys value here, do error checking etc..
        // std::string key = m[2].str();
        int ndx = std::atoi( m[2].str() );
        newstr.append( mymap[ ndx ] );
    }
    start = m[0].second;
}

// assign the old string with new string if need be
oldstr = newstr;
1 голос
/ 26 октября 2019

Вы можете сделать:

const std::map<int, std::string> m = {{1, "New York"}, {2, "summer"}};
std::string s = "I am in #1 city, it is now #2 time";

for (const auto& [id, value] : m) {
    s = std::regex_replace(s, std::regex("#" + std::to_string(id)), value);
}
std::cout << s << std::endl;

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...