zoukankan      html  css  js  c++  java
  • 表达式求解

    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))) =  ?,增加更多的算法。

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

  • 相关阅读:
    Web大前端面试题-Day12
    Web大前端面试题-Day11
    每天刷Web面试题(前10天汇总)
    Web大前端面试题-Day10
    Web大前端面试题-Day9
    Web大前端面试题-Day8
    Web大前端面试题-Day5
    Web大前端面试题-Day7
    Web大前端面试题-Day6
    php获取时间是星期几
  • 原文地址:https://www.cnblogs.com/kobe-vanessa/p/5222132.html
Copyright © 2011-2022 走看看