• C++正则表达式例子


    给了策划配置公式的地方,需要将策划配置的公式文本转化为可执行的脚本代码:
    比如:self->mHp*2+target->2mMp*GetHit()+ self_mon->4mDan/1000 ==> self:lf_mHp(0)*2+dst:lf_mMp(2)*GetHit()+ src:lf_mDan(4)/1000

    意思就是
    1 指针变量凡是含有self的都变为src,target的都替换为dst
    2 调用的属性前面的系数要提取出来
    3 属性可能是多种多样的,所以提取方法不能写死。

    当时时间紧急,对正则表达式也不熟,按照字符串分割的方法实现了。

    代码如下:

      1 void TestFormula(std::string& for_text)
      2 {
      3     using std::string;
      4     using std::vector;
      5     string::size_type pos = 0;
      6     string searchStr = "->";
      7     string replaceStr = "#";
      8 
      9     if (for_text.find(searchStr) == string::npos)
     10     {
     11         return;
     12     }
     13 
     14     while ( (pos = for_text.find(searchStr, pos)) != string::npos)
     15     {
     16         if ((for_text.size() >= pos + 2 && for_text[pos + 2] == 'm') || (for_text.size() >= pos + 3 && for_text[pos + 3] == 'm' && for_text[pos + 2] >= '0' && for_text[pos + 2] <= '9'))
     17         {
     18             for_text.replace(pos, searchStr.size(), replaceStr);
     19         }
     20         pos++;
     21     }
     22         
     23     vector<string> lVector;
     24     vector<string> rVector;
     25     int lastSplitIdx = 0;
     26     string lastText("");
     27     for (string::size_type i = 0; i < for_text.size(); i++)
     28     {
     29         if (for_text[i] == '+' || for_text[i] == '-' || for_text[i] == '*' || for_text[i] == '/'
     30             || for_text[i] == '#' || for_text[i] == '(' || for_text[i] == ')' || for_text[i] == ',')
     31         {
     32             if (for_text[i] == '#')
     33             {
     34                 lastText = for_text.substr(lastSplitIdx, i - lastSplitIdx);
     35             }
     36             else 
     37             {
     38                 if (lastText.size() > 0)
     39                 {
     40                     lVector.push_back(lastText);
     41                     rVector.push_back(for_text.substr(lastSplitIdx, i - lastSplitIdx));
     42                 }
     43                 lastText = "";
     44             }
     45             lastSplitIdx = i + 1;
     46         }
     47     }
     48     if (lastSplitIdx != for_text.size())
     49     {
     50         if (lastText.size() > 0)
     51         {
     52             lVector.push_back(lastText);
     53             rVector.push_back(for_text.substr(lastSplitIdx, lastText.size() - lastSplitIdx));
     54         }
     55     }
     56 
     57     if (lVector.size() == 0 || rVector.size() == 0 || lVector.size() != rVector.size())
     58     {
     59         return;
     60     }
     61 
     62     pos = 0;
     63     int parseIdx = 0;
     64     while ( ( pos = for_text.find(replaceStr, pos)) != string::npos)
     65     {
     66         string leftStr = lVector.at(parseIdx);
     67         string rightStr = rVector.at(parseIdx);
     68         string oldStr = leftStr + replaceStr + rightStr;
     69         string category = rightStr.substr(0, 1);
     70         string ower = leftStr;
     71         if (category == "0" || category == "1" || category == "2" || category == "3" || category == "4")
     72         {
     73             rightStr = rightStr.substr(1, rightStr.size());
     74         }
     75         else
     76         {
     77             category = "0";
     78         }
     79         if (leftStr.find("self", 0) != string::npos)
     80         {
     81             ower = "src";
     82         }
     83         else if (leftStr.find("target", 0) != string::npos)
     84         {
     85             ower = "dst";
     86         }
     87         string newStr = ower + ":lf_" + rightStr + "(" + category + ")";
     88         for_text.replace(pos - leftStr.size(), oldStr.size(), newStr);
     89         parseIdx++;
     90         pos++;
     91     }
     92 }
     93 int main()
     94 {
     95     std::string text("self->mHp*2+target->2mMp*GetHit()+self_mon->4mDan/1000");
     96     std::cout << text.c_str() << std::endl;
     97     TestFormula(text);
     98     std::cout<<text.c_str()<<std::endl;
     99 
    100     return 0;
    101 }    

    运行结果:

    颇费周折有木有~~~,还有很多临界状态需要检查,一不留神可能就踩到坑里了。

    索性,看了看正则表达式,发现非常好用。代码少很多,结果一模一样。

     1 void TestFormulaRegex(std::string& for_text)
     2 {
     3     using std::string;
     4     std::regex pat("([A-Za-z_]+)->([0-4]*)(m[A-Za-z]+)");
     5     string::const_iterator startPos = for_text.begin();
     6     string::const_iterator endPos = for_text.end();
     7     std::smatch mat;
     8     while (std::regex_search(startPos, endPos, mat, pat))
     9     {
    10         string object(mat[1].first, mat[1].second);
    11         string category(mat[2].first, mat[2].second);
    12         string attrName(mat[3].first, mat[3].second);
    13         if (category.compare("") == 0)
    14         {
    15             category = "0";
    16         }
    17         if (object.find("self", 0) != string::npos)
    18         {
    19             object = "src";
    20         }
    21         else if (object.find("target", 0) != string::npos)
    22         {
    23             object = "dst";
    24         }
    25         string replaceStr(object + ":lf_" + attrName + "(" + category + ")");
    26         for_text.replace(mat[0].first, mat[0].second, replaceStr);
    27         startPos = for_text.begin();
    28         endPos = for_text.end();
    29     }
    30 }
  • 相关阅读:
    1 说在前面的一些话,给想学习编程的人
    springboot使用api操作HBase之shell
    HBase的安装及使用
    spring boot 多数据源加载原理
    架构师之路
    Libra和中国央行数字货币(DCEP)的对比
    微博feed系统的推(push)模式和拉(pull)模式和时间分区拉模式架构探讨
    海底光缆知识科普
    jmeter安装配置教程及使用
    CountDownLatch 部分加载和同时并发业务。
  • 原文地址:https://www.cnblogs.com/lan0725/p/6655803.html
Copyright © 2020-2023  润新知