#include "stdafx.h" #include #include #include #include #include #include #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& 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>& mathExp, string exp) { xmls::ReplaceAll(exp, " ", ""); std::vector list1; SplitString(exp, list1, "and"); for (auto s : list1) { if (s.find("or") != std::string::npos) { std::vector list2; SplitString(s, list2, "or"); for (auto s1 : list2) { std:: pair p1; p1.first = s1; p1.second = s1; mathExp.push_back(p1); } } else { std::pair 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) // get the priority of the expression { if (c == '(') return 4; if (c == '!') return 3; if (c == '&') return 2; // the same as * if (c == '|') return 1; // the same as +,the lowest priority else return 0; } bool f2(char c) //the logical expression number conversion { if (c == 'F') { return false; // F ,the same as 0 } else { return true; // V,the same as 1 } } string MidToPost(const char* c) //get the postfix expression from the infix expression { stack s; //remove the space in the string string q = ""; int n = strlen(c); for (unsigned int i = 0; i < n; i++) { if (c[i] != ' ') // remove the space { //if meet an operand,add into the queue directly,use a queue to keep the postfix expression if (c[i] == 'F' || c[i] == 'V') { q += c[i]; } else if (c[i] == '!' && !s.empty() && s.top() == '!') { s.pop(); // if meet a '!' and the top of stack is also '!', pop it out } else if (!s.size()) { s.push(c[i]); // if the stack is empty,the operator is pushed into the stack } else if (c[i] == ')') { //if it is a right parenthesis, pop all the operators before the corresponding left parenthesis and add them to the queue while (s.top() != '(') { q += s.top(); s.pop(); } s.pop(); // pop the left parenthesis continue; } else if (f(s.top()) == 4 || (f(c[i]) > f(s.top()))) { s.push(c[i]); //if the top of stack is a left parenthesis or the current operator has a higher priority than the top of stack, push it into the stack } else if (f(s.top()) != 4 && f(c[i]) <= f(s.top())) { q += s.top(); s.pop(); // if the current operator has a lower or equal priority than the top of stack, pop the top of stack and add it to the queue while (!s.empty() && f(s.top()) != 4 && f(c[i]) <= f(s.top())) { q += s.top(); // pop all the operators in the stack that have a higher or equal priority than the current operator and add them to the queue s.pop(); } s.push(c[i]); //push the current operator into the stack } } } while (!s.empty()) { q += s.top(); //at last,pop all the operators in the stack and add them to the queue s.pop(); } return q; } char GetValuePost(string q) { // calculate the postfix expression bool r = true; char x, y, ans; ans = 'F'; stack 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> 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 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 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 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 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 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; } } }