#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) // 求表达式的优先级 { 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 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 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; } } }