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 }

 

posted @ 2017-04-01 14:16  彼岸Elan  阅读(723)  评论(0编辑  收藏  举报