123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- #include "stdafx.h"
- #include<iostream>
- #include<stack>
- #include<queue>
- #include<cstring>
- #include<vector>
- #include<map>
- #include "MathExpression.h"
- #include "XMLSerialization.h"
- #include "COTSUtilityDllFunExport.h"
- using namespace std;
- namespace expInterpreter {
- namespace {
- int CountStr(std::string T, std::string P)
- {
- int count = 0;
- int begin = 0;
- while ((begin = T.find(P, begin)) != string::npos)
- {
- count++;
- begin = begin + P.length();
- }
- return count;
- }
- void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c)
- {
- std::string::size_type pos1, pos2;
- pos2 = s.find(c);
- pos1 = 0;
- while (std::string::npos != pos2)
- {
- v.push_back(s.substr(pos1, pos2 - pos1));
- pos1 = pos2 + c.size();
- pos2 = s.find(c, pos1);
- }
- if (pos1 != s.length())
- v.push_back(s.substr(pos1));
- }
- void DevidExpToMathExp(std::vector<std::pair<string,string>>& mathExp, string exp)
- {
- xmls::ReplaceAll(exp, " ", "");
- std::vector<string> list1;
- SplitString(exp, list1, "and");
- for (auto s : list1)
- {
- if (s.find("or") != std::string::npos)
- {
- std::vector <string> list2;
- SplitString(s, list2, "or");
- for (auto s1 : list2)
- {
- std:: pair<string, string> p1;
- p1.first = s1;
- p1.second = s1;
- mathExp.push_back(p1);
- }
- }
- else
- {
- std::pair<string, string> p2;
- p2.first = s;
- p2.second = s;
- mathExp.push_back(p2);
- }
- }
- for (auto s2 = mathExp.begin(); s2 != mathExp.end(); s2++)
- {
- int startPos;
- int sMathLen;
- string sMath;
- int n1 = CountStr(s2->second, "(");
- int n2 = CountStr(s2->second, ")");
- if (n1 > n2)//contains unpaired "("
- {
- startPos = n1 - n2;
- sMathLen = s2->second.length() - startPos;
- sMath = s2->second.substr(startPos, sMathLen);
- s2->second = sMath;
- s2->first = sMath;
- }
- else if (n2 > n1)
- {
- startPos = n2 - n1;
- sMathLen = s2->second.length() - startPos;
- sMath = s2->second.substr(0, sMathLen);
- s2->second = sMath;
- s2->first = sMath;
- }
- }
- }
-
-
- int f(char c) // 求表达式的优先级
- {
- if (c == '(') return 4;
- if (c == '!') return 3;
- if (c == '&') return 2; // 相当于*
- if (c == '|') return 1; // 相当于+,优先级最低
- else
- return 0;
- }
- bool f2(char c) // 逻辑表达式数的转换
- {
- if (c == 'F')
- {
- return false; // F相当于0
- }
- else
- {
- return true; // V相当于1
- }
- }
- string MidToPost(const char* c) //求表达式对应的后缀表达式
- {
- stack<char> s; //字符串中去手动去空格
- string q = "";
- int n = strlen(c);
- for (unsigned int i = 0; i < n; i++)
- {
- if (c[i] != ' ') // 除去空格
- {
- // 如果遇到运算数,直接加入到队列中,用队列来放后缀表达式
- if (c[i] == 'F' || c[i] == 'V')
- {
- q += c[i];
- }
- else if (c[i] == '!' && !s.empty() && s.top() == '!')
- {
- s.pop(); // 如果遇到!而且栈顶也是!那么直接抵消出栈
- }
- else if (!s.size())
- {
- s.push(c[i]); // 如果栈为空,遇到运算符直接入栈
- }
- else if (c[i] == ')')
- { // 如果是右括号,则弹出对应左括号前的所有的运算符 ,加入到队列中
- while (s.top() != '(')
- {
- q += s.top();
- s.pop();
- }
- s.pop(); // 弹出左括号
- continue;
- }
- else if (f(s.top()) == 4 || (f(c[i]) > f(s.top())))
- {
- s.push(c[i]); // 如果栈顶是左括号,或者当前优先级高,都入栈
- }
- else if (f(s.top()) != 4 && f(c[i]) <= f(s.top()))
- {
- q += s.top();
- s.pop(); // 如果遇到运算符没有栈顶运算符级别高,出栈
- while (!s.empty() && f(s.top()) != 4 && f(c[i]) <= f(s.top()))
- {
- q += s.top(); // 从栈中弹出比当前优先级高的运算符
- s.pop();
- }
- s.push(c[i]); //将当前运算符加入到队列
- }
- }
- }
- while (!s.empty())
- {
- q += s.top(); // 最后将栈里面所有元素弹出加入到队列
- s.pop();
- }
- return q;
- }
- char GetValuePost(string q)
- { //后缀表达式求值
- bool r = true;
- char x, y, ans;
- ans = 'F';
- stack<char> s;
- int n = q.size();
- for (unsigned int i = 0; i < n; i++)
- {
- if (q[i] == 'V' || q[i] == 'F')
- {
- s.push(q[i]);
- }
- else
- {
- if (q[i] == '&')
- {
- x = s.top();
- s.pop();
- y = s.top();
- s.pop();
- bool v1, v2;
- v1 = f2(x);
- v2 = f2(y);
- r = (v1 && v2);
- if (r == true)
- s.push('V');
- else
- s.push('F');
- }
- else if (q[i] == '|')
- {
- x = s.top();
- s.pop();
- y = s.top();
- s.pop();
- r = (f2(x) || f2(y));
- if (r == true)
- s.push('V');
- else
- s.push('F');
- }
- else
- {
- x = s.top();
- s.pop();
- if (f2(x) == 1)
- s.push('F');
- else
- s.push('V');
- }
- }
- ans = s.top();
- }
- return ans;
- }
- /* void RemoveLeftAndRightBrace(std::string& s)
- {
-
- }*/
-
-
- }
- /*int main1()
- {*/
- //"(Si+Al+Na)>60 and O>15 and ASPECT>10 and D_MEAN<20"
- //"(20+21+22)>60 and 16>15 and (5>10 and 10<20)"
- //"(20+21+22)>60 and 16>15 and (5>10 or 10<20)"
- /* std::string hybrids = "20+(5+1)*25-500>60 and (21>15 and (5>10 or 10<20))";
- bool v = CalcuExp(hybrids);
- cout << v << endl;*/
- /*}*/
- bool CalcuExp(std::string hybrids)
- {
- //hybrids = "(51.839426 + 34.298664) > 90and34.298664 > 30and51.839426 > 40and0 < 1.5and0 < 1.5and8.452528 < 3and5.409383 < 2and0 < 2and0 < 2and0 < 2and51.839426 < 60and2.809600 < 1.6";
- //hybrids = "(26.856649 + 23.877375 + 0.000000) > 30 and (0.000000 + 26.856649) > 5 and 23.877375 > 5 and 19.041451 < 5 and 13.989637 < 10";
- //hybrids = "(0 < 1or0 > 50)and0.925024 >= 15and0.925024 <= 100and48.318507 >= 20and48.318507 <= 100and0 < 5";
- //hybrids = "(19.445164 + 0.950784) >= 80and0.950784 / 19.445164 >= 0.4and0.950784 / 19.445164 < 6.2and0 < 3and0 < 3and0.411897 < 3and0 < 3and0 < 5and0 < 10and0 < 5and0 < 5";
- xmls::ReplaceAll(hybrids, " ", "");
- expInterpreter::Expression mathExpIpr;
- std::vector<std::pair<string,string>> mathexp;
- DevidExpToMathExp(mathexp, hybrids);//first ,we devid the expression into math expressions such as "20+(5+1)*25-500>60" ,we use "and" and "or" to separate it.
-
- for (auto e : mathexp)
- {
- string rst;
- string s = e.second; //every string contains one logic compare sign,such as "<" or ">" etc.
- /*cout << e.second << endl;*/
- auto r = s.find("<");// we check which sign it contains.
- auto r1 = s.find(">");
- auto r2 = s.find("=");
- auto r3 = s.find(">=");
- auto r4 = s.find("<=");
-
- if (r3 != std::string::npos)// firstly,wind look out the ">=" then "<=" then ">" and "<" "=" .the sequence is very important.
- {
- double result;
- vector<string> strs;
- SplitString(s, strs, ">=");
- string s1 = "";
- s1 = strs[0] + "-(" + strs[1] + ")";
- mathExpIpr.SetExprStr(s1.c_str());
- float rst1 = mathExpIpr.GetResult(&result);
- if (result >= 0)
- {
- rst = "V";
- }
- else
- {
- rst = "F";
- }
- }
- else if (r4 != std::string::npos)
- {
- double result;
- vector<string> strs;
- SplitString(s, strs, "<=");
- string s1 = "";
- s1 = strs[0] + "-(" + strs[1] + ")";
- mathExpIpr.SetExprStr(s1.c_str());
- int rst1 = mathExpIpr.GetResult(&result);
- if (result <= 0)
- {
- rst = "V";
- }
- else
- {
- rst = "F";
- }
- }else if(r != std::string::npos)//contains "<"
- {
- double result;
- vector<string> strs;
- SplitString(s, strs, "<");
- string s1 = strs[0] + "-(" + strs[1] + ")";//convert this exp to a menus exp and calculate its value and then compare to 0.
- mathExpIpr.SetExprStr(s1.c_str());
- float rst1 = mathExpIpr.GetResult(&result);//calculate this expression
- if (result < 0)
- {
- rst = "V";
- }
- else
- {
- rst = "F";
- }
- }
- else if (r1 != std::string::npos)
- {
- double result;
- vector<string> strs;
- SplitString(s, strs, ">");
- string s1 = strs[0] + "-(" + strs[1] + ")";
- mathExpIpr.SetExprStr(s1.c_str());
- float rst1 = mathExpIpr.GetResult(&result);
- if (result > 0)
- {
- rst = "V";
- }
- else
- {
- rst = "F";
- }
- }
- else if (r2 != std::string::npos)
- {
- double result;
- vector<string> strs;
- SplitString(s, strs, "=");
- string s1 = strs[0] + "-(" + strs[1] + ")";
- mathExpIpr.SetExprStr(s1.c_str());
- float rst1 = mathExpIpr.GetResult(&result);
- if (result == 0)
- {
- rst = "V";
- }
- else
- {
- rst = "F";
- }
- }
- e.second = rst;
- xmls::ReplaceFirst(hybrids, e.first, e.second);
- }
- xmls::ReplaceAll(hybrids, "and", "&");
- xmls::ReplaceAll(hybrids, "or", "|");//get a pure logic expression.
-
- //LogTrace(__FILE__, __LINE__, hybrids.c_str());
- string post;
- char ans;
- post = MidToPost(hybrids.c_str());
- //cout << post << endl;
- ans = GetValuePost(post);
- if (ans == 'V')
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- }
|