使用正则表达式拆分数学表达式

Posted

技术标签:

【中文标题】使用正则表达式拆分数学表达式【英文标题】:Split a mathematical expression using regex 【发布时间】:2021-01-05 22:05:02 【问题描述】:

我想使用正则表达式将以下数学表达式-1+33+4.4+sin(3)-2-x^2 拆分为标记。我使用以下站点来测试我的正则表达式link,这说明没有错。当我在我的 C++ 中实现正则表达式时,抛出以下错误 Invalid special open parenthesis 我寻找解决方案,我找到了以下 *** 站点 link 但它并没有帮助我解决我的问题。 我的正则表达式代码是(?<=[-+*\/^()])|(?=[-+*\/^()])。在 C++ 代码中我不使用\

另一个问题是我不知道如何判断减号是一元运算符还是二元运算符,如果减号是一元运算符我想看起来像这样-1

我希望令牌看起来像这样:-1,+,33,+4.4,+,sin,(,3,),-,2,-,x,^,2

一元减号可以在字符串中的任何位置。

如果我不使用^,它仍然是错误的。

代码:

std::vector<std::string> split(const std::string& s, std::string rgx_str) 
      std::vector<std::string> elems;
      std::regex rgx (rgx_str);
      std::sregex_token_iterator iter(s.begin(), s.end(), rgx);
      std::sregex_token_iterator end;
      while (iter != end)  
          elems.push_back(*iter);
          ++iter;
      
      return elems;

int main() 
    std::string str = "-1+33+4.4+sin(3)-2-x^2";
    std::string reg = "(?<=[-+*/()^])|(?=[-+*/()^])";
    std::vector<std::string> s = split(str,reg);
    for(auto& a : s)
        cout << a << endl;
    return 0;

【问题讨论】:

我们可以假设一元减号只能出现在字符串开头吗? 有几种正则表达式在使用中。如果不查找 C++ 的 std::regex 实现,则该语法可能与 std::regex 所期望的不匹配。最后,关于减号的话题,由于这个和其他原因,期望仅使用正则表达式来解析任意复杂的数学表达式根本不可行。真正的解析器使用基于正则表达式的词法分析器,它具有单独的语法解析阶段,通常使用 LALR(1) 解析器,并将- 视为一元运算符,并直接在数字常量操作数上实现它。 @WiktorStribiżew 没有一元减号可以在任何地方 ^ 符号可能是问题所在吗?那不是代表字符串结尾的保留字符吗? @J.Lengel 如果我不使用 ^ 它仍然是错误的 【参考方案1】:

C++ 默认使用modified ECMAScript regular expression grammar 作为其std::regex。它支持前瞻 (?=)(?!),但不支持后瞻。因此,(?&lt;=) 不是有效的 std::regex 语法。

C++23中有a proposal添加这个,但是目前没有实现。

【讨论】:

以上是关于使用正则表达式拆分数学表达式的主要内容,如果未能解决你的问题,请参考以下文章

使用正则表达式拆分简单的 JSON 结构

如何使用正则表达式拆分字符串而不消耗拆分器部分?

使用正则表达式拆分字符串值

通过正则表达式拆分字符串[重复]

使用正则表达式将字符串拆分为句子

如何使用 JavaScript 正则表达式拆分此文本?