表达式求解

 

 

0.功能:

计算一个多层次表达式

例如:

(((((6)+(5)+(4))-(3))*(2))/(1)) = ?

 ((((1)or(0))xor(2))and(not(-1)))= ?

1.原理:

参考正则表达式解析,存储结构,和xml树形结构文件解析的思路,创建树形算式结构。

2.流程:

第一步:解析表达式

<1>.遇到'('创建一个节点。

<2>.遇到')'返回上一层。

<3>.遇到其他情况填值。

第二步:创建结构

结构图

 

3.应用

求解出一个复杂计算条件计算值,表达式的结果可以是数字量或者模拟量,可以抽象到复杂条件判断上面。

 

4.代码

 symbol.h

  1 #ifndef SYMBOL_H
  2 #define SYMBOL_H
  3 
  4 /*
  5 symbol
  6 各种运算符号的算法实现。做所有“正确”数据的计算。
  7 */
  8 
  9 
 10 #include <list>
 11 #include <string>
 12 
 13 using namespace std;
 14 
 15 
 16 class ValSymbol
 17 {
 18 public:
 19     ValSymbol(){}
 20     virtual ~ValSymbol(){}
 21     string SymbolContent() {return "val";}
 22     double Operation(list<double>& values);
 23 };
 24 
 25 class AddSymbol
 26 {
 27 public:
 28     AddSymbol(){
 29     
 30     }
 31     virtual ~AddSymbol(){}
 32     string SymbolContent(){return "+";}
 33     double Operation(list<double>& values);
 34 };
 35 
 36 class SubSymbol
 37 {
 38 public:
 39     SubSymbol(){}
 40     virtual ~SubSymbol(){}
 41     string SymbolContent() {return "-";}
 42     double Operation(list<double>& values);
 43 };
 44 
 45 class MulSymbol
 46 {
 47 public:
 48     MulSymbol(){}
 49     virtual ~MulSymbol(){}
 50     string SymbolContent() {return "*";}
 51     double Operation(list<double>& values);
 52 };
 53 
 54 class DivSymbol
 55 {
 56 public:
 57     DivSymbol(){}
 58     virtual ~DivSymbol(){}
 59     string SymbolContent() {return "/";}
 60     double Operation(list<double>& values);
 61 };
 62 
 63 class AndSymbol
 64 {
 65 public:
 66     AndSymbol(){}
 67     virtual ~AndSymbol(){}
 68     string SymbolContent() {return "and";}
 69     double Operation(list<double>& values);
 70 };
 71 
 72 class OrSymbol
 73 {
 74 public:
 75     OrSymbol(){}
 76     virtual ~OrSymbol(){}
 77     string SymbolContent() {return "or";}
 78     double Operation(list<double>& values);
 79 };
 80 
 81 class NotSymbol
 82 {
 83 public:
 84     NotSymbol(){}
 85     virtual ~NotSymbol(){}
 86     string SymbolContent() {return "not";}
 87     double Operation(list<double>& values);
 88 };
 89 
 90 class XorSymbol
 91 {
 92 public:
 93     XorSymbol(){}
 94     virtual ~XorSymbol(){}
 95     string SymbolContent() {return "xor";}
 96     double Operation(list<double>& values);
 97 };
 98 
 99 
100 
101 
102 
103 
104 #endif

symbol.cpp

  1 #include "symbol.h"
  2 
  3 
  4 double ValSymbol::Operation(list<double>& values)
  5 {
  6     return 0;
  7 }
  8 
  9 double AddSymbol::Operation(list<double> &values)
 10 {
 11     list<double>::iterator _beg = values.begin();
 12     list<double>::iterator _end = values.end();
 13     double value_1st = (*_beg);
 14     _beg++;
 15 
 16     while (_beg != _end) {
 17         double value = (*_beg);
 18         value_1st = value_1st + value;
 19         _beg++;
 20     }
 21 
 22     return value_1st;
 23 }
 24 
 25 double SubSymbol::Operation(list<double> &values)
 26 {
 27     list<double>::iterator _beg = values.begin();
 28     list<double>::iterator _end = values.end();
 29     double value_1st = (*_beg);
 30     _beg++;
 31 
 32     while (_beg != _end) {
 33         double value = (*_beg);
 34         value_1st = value_1st - value;
 35         _beg++;
 36     }
 37 
 38     return value_1st;
 39 }
 40 
 41 double MulSymbol::Operation(list<double> &values)
 42 {
 43     list<double>::iterator _beg = values.begin();
 44     list<double>::iterator _end = values.end();
 45     double value_1st = (*_beg);
 46     _beg++;
 47 
 48     while (_beg != _end) {
 49         double value = (*_beg);
 50         value_1st = value_1st * value;
 51         _beg++;
 52     }
 53 
 54     return value_1st;
 55 }
 56 
 57 double DivSymbol::Operation(list<double> &values)
 58 {
 59     list<double>::iterator _beg = values.begin();
 60     list<double>::iterator _end = values.end();
 61     double value_1st = (*_beg);
 62     _beg++;
 63 
 64     while (_beg != _end) {
 65         double value = (*_beg);
 66         value_1st = value_1st / value;
 67         _beg++;
 68     }
 69 
 70     return value_1st;
 71 }
 72 
 73 double AndSymbol::Operation(list<double> &values)
 74 {
 75     list<double>::iterator _beg = values.begin();
 76     list<double>::iterator _end = values.end();
 77     double re_value = 1;
 78 
 79     while (_beg != _end) {
 80         re_value = (*_beg);
 81         if(re_value <= 0) {
 82             return 0;
 83         }
 84     }
 85 
 86     return 1;
 87 }
 88 
 89 double OrSymbol::Operation(list<double> &values)
 90 {
 91     list<double>::iterator _beg = values.begin();
 92     list<double>::iterator _end = values.end();
 93     double re_value = 0;
 94 
 95     while (_beg != _end) {
 96         re_value = (*_beg);
 97         if(re_value >= 0) {
 98             return 1;
 99         }
100     }
101 
102     return re_value;
103 }
104 
105 double NotSymbol::Operation(list<double> &values)
106 {
107     list<double>::iterator _beg = values.begin();
108     double value_1st = (*_beg);
109 
110     if (value_1st >0) {
111         return 1;
112     } else {
113         return 0;
114     }
115 }
116 
117 double XorSymbol::Operation(list<double> &values)
118 {
119     list<double>::iterator _beg = values.begin();
120     list<double>::iterator _end = values.end();
121     double re_value = 1;
122 
123     while (_beg != _end) {
124         re_value = (*_beg);
125         if(re_value >= 0) {
126             return 0;
127         }
128     }
129 
130     return re_value;
131 }

data.h

 1 #ifndef DATA_H
 2 #define DATA_H
 3 
 4 /*
 5 data
 6 数据的类型,可以是一般值,也可以是符号,都抽象成数据。
 7 这里应用到策略模式 
 8 支持扩展:id取值,数据只保存id。
 9 
10 这里使用泛型编程,是将数据,与操作数据的算法,既绑定又分开,
11 刚开始只为了练习泛型编程,后来感觉这么写不错。
12 */
13 
14 
15 #include <list>
16 #include <string>
17 
18 using namespace std;
19 
20 class IData
21 {
22 public:
23     IData(){}
24     virtual ~IData(){}
25     virtual void SetValue(string str) = 0;
26     virtual string GetValue() = 0;
27     virtual double Result(list<double>& value) = 0;
28 };
29 
30 template<class TypeSymbol>
31 class Data : public IData
32 {
33 public:
34     Data() {
35         m_strvalue = "";
36         m_pSymbol = new TypeSymbol;
37     }
38     virtual ~Data() {
39     
40     }
41     void SetValue(string str) {
42         m_strvalue = str;
43     }
44     string GetValue() {
45         return m_strvalue;
46     }
47 
48     double Result(list<double>& values) {
49     
50         return m_pSymbol->Operation(values);
51     }
52 
53 private:
54     string m_strvalue;
55     TypeSymbol* m_pSymbol;
56 
57 };
58 
59 #endif

data.cpp

 1 #include "data.h" 

node.h

 1 #ifndef NODE_H
 2 #define NODE_H
 3 
 4 /*
 5 node
 6 保存表达式的结构。
 7 
 8 支持扩展:添加错误值节点排除,有选择性的计算结果。
 9 */
10 
11 #include <iostream>
12 #include <list>
13 #include <string>
14 
15 using namespace std;
16 
17 class IData;
18 
19 class Node
20 {
21 public:
22     Node();
23     virtual ~Node();
24 
25     void SetParent(Node* pnode);
26     Node* GetParent();
27 
28     void AppendChild(Node* pnode);
29     list<Node*>::iterator ChildrenBeg();
30     list<Node*>::iterator ChildrenEnd();
31     bool HasChildren();
32 
33     void SetData(string str);
34     string Content();
35 
36     double Result();
37 
38 private:
39     Node* m_pparent;
40     list<Node*> m_children;
41     IData* m_pData;
42 };
43 
44 
45 #endif

node.cpp

  1 #include "node.h"
  2 #include "data.h"
  3 #include "symbol.h"
  4 #include <sstream>
  5 
  6 template <class Type>
  7 Type stringToNum(const string& str)
  8 {
  9     istringstream iss(str);
 10     Type num;
 11     iss >> num;
 12     return num;
 13 }
 14 
 15 Node::Node()
 16 {
 17     m_pparent = NULL;
 18     m_children.clear();
 19     m_pData = NULL;
 20 }
 21 
 22 Node::~Node()
 23 {
 24 }
 25 
 26 void Node::SetParent(Node* pnode)
 27 {
 28     m_pparent = pnode;
 29 }
 30 
 31 Node* Node::GetParent()
 32 {
 33     return m_pparent;
 34 }
 35 
 36 void Node::AppendChild(Node *pnode)
 37 {
 38     m_children.push_back(pnode);
 39 }
 40 
 41 list<Node*>::iterator Node::ChildrenBeg()
 42 {
 43     return m_children.begin();
 44 }
 45 
 46 list<Node*>::iterator Node::ChildrenEnd()
 47 {
 48     return m_children.end();
 49 }
 50 
 51 bool Node::HasChildren()
 52 {
 53     if (m_children.empty()) {
 54         return false;
 55     }else {
 56         return true;
 57     }
 58 }
 59 
 60 void Node::SetData(string str)
 61 {
 62     if (str == "+") {
 63         m_pData = new Data<AddSymbol>;
 64 
 65     } else if(str == "-") {
 66         m_pData = new Data<SubSymbol>;
 67     
 68     } else if(str == "*") {
 69         m_pData = new Data<MulSymbol>;
 70     
 71     } else if(str == "/") {
 72         m_pData = new Data<DivSymbol>;
 73     
 74     } else if (str == "and") {
 75         m_pData = new Data<AndSymbol>;
 76 
 77     } else if( str == "or") {
 78         m_pData = new Data<OrSymbol>;
 79 
 80     } else if (str == "not") {
 81         m_pData = new Data<NotSymbol>;
 82 
 83     } else if (str == "xor") {
 84         m_pData = new Data<XorSymbol>;
 85 
 86     } else {
 87         m_pData = new Data<ValSymbol>;
 88         m_pData->SetValue(str);
 89     }
 90 }
 91 
 92 string Node::Content()
 93 {
 94     return "";
 95 }
 96 
 97 double Node::Result()
 98 {
 99     if ( HasChildren()) {
100         list<Node*>::iterator _beg = ChildrenBeg();
101         list<Node*>::iterator _end = ChildrenEnd();
102         list<double> values;
103         while (_beg != _end) {
104             Node* pnode = (*_beg);
105             values.push_back(pnode->Result());
106             _beg++;
107         }
108         return m_pData->Result(values);
109 
110     }else {
111         return  stringToNum<double>(m_pData->GetValue());
112     }
113 }

expresionAnalysis.h

 1 #ifndef EXPRESION_ANALYSIS_H
 2 #define EXPRESION_ANALYSIS_H
 3 
 4 /*
 5 expresionAnalysis
 6 解析表达式到数据结构中。
 7 
 8 支持扩展:将解析与结构管理类功能放到一起,可以将两个功能分开做。
 9 遇到复杂多干扰的表达式,做一个“前处理类”,得到一个规范的表达式,
10 如支持空格(去掉空格),支持前运算符max((1),(2))。
11 */
12 
13 #include <iostream>
14 #include <string>
15 
16 using namespace std;
17 
18 class Node;
19 
20 class ExpresionAnalysis
21 {
22 public:
23     ExpresionAnalysis(string strExpresion);
24     virtual ~ExpresionAnalysis();
25 
26     void Analysis();
27     void SetRoot(Node* pnode);
28     void AddChild(Node* pnode);
29     void SetParentCurNode();
30     void ValueCurNode(string str);
31     void Print(Node* pnode= NULL);
32     double Result();
33 
34 private:
35     string m_strExpresion;
36     Node* m_pCur;
37     Node* m_pRoot;
38 };
39 
40 
41 #endif 

 

expresionAnalysis.cpp 

 1 #include "expresionAnalysis.h"
 2 #include "node.h"
 3 
 4 
 5 ExpresionAnalysis::ExpresionAnalysis(string strExpresion)
 6 {
 7     m_strExpresion = strExpresion;
 8     m_pCur = NULL;
 9     m_pRoot = NULL;
10 }
11 
12 ExpresionAnalysis::~ExpresionAnalysis()
13 {
14     if (m_pRoot) {
15         delete m_pRoot;
16         m_pRoot = NULL;
17     }
18 }
19 
20 void ExpresionAnalysis::Analysis()
21 {
22     int ilen = m_strExpresion.length();
23     int i = 0;
24     while ( i < ilen ) {
25         char c = m_strExpresion.at(i);
26         if (c == '(') {
27             if (!m_pRoot) {
28                 SetRoot(new Node());
29             } else {
30                 AddChild(new Node());
31             }
32             i++;
33         } else if (c == ')') {
34             SetParentCurNode();    
35             i++;
36         } else {
37             int j = 0;
38             string strvalue = "";
39             while (true) {
40                 char cc = m_strExpresion.at(i+j);
41                 if (cc == '(' || cc == ')') {
42                     break;
43                 }            
44                 strvalue = strvalue + cc;
45                 j++;
46             }
47             ValueCurNode(strvalue);
48             i = i + j;
49         }
50     }
51 }
52 
53 void ExpresionAnalysis::SetRoot(Node *pnode)
54 {
55     if (!m_pRoot) {
56         m_pRoot = pnode;
57     }
58     m_pCur = m_pRoot;
59 }
60 
61 void ExpresionAnalysis::AddChild(Node *pnode)
62 {
63     m_pCur->AppendChild(pnode);
64     pnode->SetParent(m_pCur);
65     m_pCur = pnode;
66 }
67 
68 void ExpresionAnalysis::SetParentCurNode()
69 {
70     m_pCur = m_pCur->GetParent();
71 }
72 
73 void ExpresionAnalysis::ValueCurNode(string str)
74 {
75     cout << str <<endl;
76     m_pCur->SetData(str);
77 }
78 
79 void ExpresionAnalysis::Print(Node *pnode)
80 {
81     /*打印结构*/
82 }
83 
84 double ExpresionAnalysis::Result()
85 {
86     return m_pRoot->Result();
87 }

main.cpp

 1 #include "expresionAnalysis.h"
 2 
 3 /*
 4 在实际表达式计算中,情况会很多,可在代码结构上添加功能
 5 
 6 <1>.单目运算,多目运算
 7 <2>.前,中,后运算
 8 <3>.id取值运算
 9 <4>.错误值排除运算
10 <5>.等等
11 */
12 
13 using namespace std;
14 
15 int main()
16 {
17     string strExpresion1 = "(((((6)+(5)+(4))-(3))*(2))/(1))";
18     string strExpresion2 = "((((1)or(0))xor(2))and(not(-1)))";
19 
20     ExpresionAnalysis ea(strExpresion2);
21     ea.Analysis();
22     cout << "= " << ea.Result();
23 
24     return 0;
25 }

 

5.扩展

<1> ([1]((((6)+(5)+(4))-(3))*(2))/(1)) = ?,加入错误分析,如果错误舍弃局部结构。

<2> (((((@192.168.0.1)+(5)+(4))-(3))*(2))/(1)) = ? ,丰富一般取值的途径。

<3> (max((1) , (2))) =  ?,增加更多的算法。

这些需求都可以在源代码基础上方便扩展。

posted on 2016-02-26 23:52  SharpD  阅读(417)  评论(0)    收藏  举报