Regex — границы слов не работают

Подводя итог: Как я могу запретить моему шаблону регулярных выражений ошибочно принимать сегменты строк как имя переменной из целого слова? Это замена букв, которые являются частью большего слова, хотя я использую границы слов \b,

Что я пытаюсь сделать: Я работаю над калькулятором. У него есть список переменных, и перед передачей выражения в парсер я вызываю свою функцию ParseVars() сделать regex_search используя шаблон для сопоставления переменных. Как только в нем есть все токены, соответствующие моему шаблону переменных, я проверяю, действительно ли эта строка находится в списке имен переменных, и если да, я заменяю строку значением переменной. Кроме того, каждый раз, когда в парсере производятся вычисления, я определяю константу с именем ans1, ans2, и так далее.

Проблема в: Допустим, у меня есть определенная переменная с именем aи его значение 6, (Кстати, я отслеживаю их в map<string,double> Vars; Когда я делаю ParseVars("ans1") результирующая строка "ans1", Также с ParseVar(), строка ans1+ans2+9 остается такой же. Строка 9+a становится 9+6, Итак, пока мое регулярное выражение работает, как ожидалось.

НО, если я сделаю ParseVars("ans1+a")полученная строка "6ns1+6", Меня смущает, почему границы слова в моем регулярном выражении терпят неудачу, только если я использую переменную, «a» всегда можно найти в «ans1», но он заменяется только в том случае, если «a» находится где-то еще в строке ,

Что я имею: Вот мой шаблон регулярных выражений: \b([a-z][a-z0-9_]*)\b Разве это не должно соответствовать только целым словам? Граница слова работает хорошо, пока «а» не находится в другом месте строки. Может это мой ParseVars() функция, вот код:

map<string,double> Vars;

// Variables must be a whole word, start with a letter, and
// optionally have other letters, numbers, and underscores.
sregex VarPattern = sregex::compile("\\b([a-z][a-z0-9_]*)\\b");

string Calculator::ParseVars(string expr) {
if (Vars.empty()) return expr;

string newExpr = StrToLower(expr);
const sregex_iterator End;

// Loop through all possible variable matches
for (sregex_iterator i(expr.begin(), expr.end(), VarPattern); i != End; ++i) {
string name = (*i)[0];

// If it is a variable
if (Vars.find(name) != Vars.end()) {
int rPos = 0;

// Replace all occurrences of it
while ((rPos = newExpr.find(name, rPos)) != string::npos) {
newExpr.replace(
rPos, name.length(),
lexical_cast<string,double>(Vars[name])
);
}
}
}

return newExpr;
}

С a быть равным 6как я могу предотвратить ans1+a от становления 6ns1+6 вместо желаемого ans1+6?

1

Решение

Ну, я нашел решение. Я помещаю свой ответ здесь для любого, кто столкнулся с подобной проблемой.

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

map<string,double> Vars;

// Variables must be a whole word, start with a letter, and
// optionally have other letters, numbers, and underscores.
sregex VarPattern = sregex::compile("\\b([a-z][a-z0-9_]*)\\b");

string Calculator::ParseVars(string expr) {
if (Vars.empty()) return expr;
string newExpr = StrToLower(expr);
const sregex_iterator End;

// Loop through all possible variable matches
for (sregex_iterator i(expr.begin(), expr.end(), VarPattern); i != End; ++i) {
string name = (*i)[0];

// If it is a variable
if (Vars.find(name) != Vars.end()) {
sregex rgxName = sregex::compile("\\b" + name + "\\b");

// Replace all occurrences of it
newExpr = xpressive::regex_replace(
newExpr, rgxName,
lexical_cast<string,double>(Vars[name])
);
}
}

return newExpr;
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]