Подводя итог: как я могу предотвратить то, что мой шаблон регулярного выражения ошибочно принимает сегменты строк за имя переменной из целого слова? Он заменяет буквы, которые являются частью большего слова, хотя я использую границы слов \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
?
\b
соответствует между буквенно-цифровым символом ([A-Za-z0-9_]
) и либо не-alnum символом, либо началом/концом строки. Таким образом, в строкеans1+a
\b
совпадают в следующих позициях, отмеченных|
:|ans1|+|a|
. - person Tim Pietzcker   schedule 03.10.2012string.replace()
не знает границ слов. Поэтому он пошел дальше и заменилa
вans1
на6
, хотяans1
никогда не совпадало. - person Brandon Miller   schedule 03.10.2012