上一个计算器有bug,还是用语法制导的方法计算表达式,这个没有bug,用的是LL(1)表达式文法,以=号结束

来源:互联网 发布:免费玻璃排版软件 编辑:程序博客网 时间:2024/06/05 00:21

pointer计数指针

pointer.h

#ifndef _pointer_h#define _pointer_htemplate<class T>  class pointer  {  public:      pointer():ptr(NULL),pCnt(new int(0)){}     pointer(T* src):ptr(src),pCnt(new int(1))      {      }      pointer(const pointer<T>& src):ptr(src.ptr),pCnt(src.pCnt)      {          ++(*pCnt);      }      pointer<T>& operator=(const pointer<T>& rhs)      {          if(ptr != rhs.ptr)          {              Release();              ptr = rhs.ptr;              pCnt = rhs.pCnt;              ++*pCnt;          }          return (*this);      }      T* operator->()      {          return ptr;      }      const T* operator->()const      {          return ptr;      }      T& operator*()      {          return (*ptr);      }      const T& operator*()const      {          return (*ptr);      }      ~pointer()      {          Release();      }  public:      T* ptr;      int *pCnt;      void Release()      {          if(--*pCnt == 0)          {              delete ptr;              delete pCnt;          }      }  };  #endif 

表达式节点有两种,符号节点和数字节点

express_node.h

#ifndef _express_node_h#define _express_node_h #include<iostream>using std::cout; class node{public:    node(){}    virtual float getNum(){return -1;}     virtual char getChar(){return '#';}     virtual ~node(){        //cout<<"~node\n";        //system("pause");    } };    class char_node:public node{    char sym;public:    char_node(char c):sym(c){}    void setChar(char c){sym=c;}    virtual char getChar(){return sym;}    virtual ~char_node(){        //cout<<"~char_node\n";        //system("pause");    }};    class num_node:public node{    float num;public:    num_node(float n):num(n){}    void setNum(float n){num=n;}    virtual float getNum(){return num;}    virtual ~num_node(){        //cout<<"~num_node\n";        //system("pause");    }};  #endif 

主函数

main.cpp

#include<vector>#include<memory> #include<stack> #include<iostream> #include"express_node.h"#include"pointer.h" using namespace std;void E();void Ts();void T();void Ps();void P(); void error(){    cout<<"语法错误\n"<<endl;system("pause");exit(1); } bool isNum(pointer<node> a){    return dynamic_cast<num_node*>(&(*a))!=NULL;}  bool isChar(pointer<node> a){    return dynamic_cast<char_node*>(&(*a))!=NULL; } void print1(node* a){    if(dynamic_cast<char_node*>(a)!=NULL){        cout<<dynamic_cast<char_node*>(a)->getChar()<<endl;    }        else{        cout<<dynamic_cast<num_node*>(a)->getNum()<<endl;    }    }  void print2(node& a){    if(dynamic_cast<char_node*>(&a)!=NULL){        cout<<dynamic_cast<char_node*>(&a)->getChar()<<endl;    }        else{        cout<<dynamic_cast<num_node*>(&a)->getNum()<<endl;    }    }   void print4(pointer<node>& a){    if(dynamic_cast<char_node*>(&(*a))!=NULL){        cout<<dynamic_cast<char_node*>(&(*a))->getChar()<<endl;    }        else{        cout<<dynamic_cast<num_node*>(&(*a))->getNum()<<endl;    }    }    vector<pointer<node> > v;vector<pointer<node> >::iterator current;stack<float> s; void GenCode(char c){    //cout<<"生成中间代码\n";     float p1=s.top();s.pop();//cout<<"弹出"<<p1<<endl;     float p2=s.top();s.pop();//cout<<"弹出"<<p2<<endl;     switch(c){        case '+':            s.push(p2+p1);            //cout<<"相加 ";             //cout<<"压入"<<p1+p2<<endl;             break;        case '-':            s.push(p2-p1);            //cout<<"相减 ";            //cout<<"压入"<<p2-p1<<endl;              break;        case '*':            s.push(p2*p1);             //cout<<"相乘 ";            //cout<<"压入"<<p1*p2<<endl;             break;        case '/':            s.push(p2/p1);             //cout<<"相除 ";            //cout<<"压入"<<p2/p1<<endl;             break;     } } void match(char c){    //cout<<"match(char)\n";     //system("pause");     if(isChar(*current)){        if((*current)->getChar()==c){            //cout<<"匹配"<<c<<endl;            current++;            return;        }         else{            //cout<<((*current)->getChar())<<"不匹配"<<endl;            error();        }     }     else{        error();     } } void E(){    //cout<<"E()\n";     if(isChar(*current)){        //system("pause");cout<<"当前值为字符\n";         if((*current)->getChar()=='('){            //cout<<"当前值为字符'('\n";             T();Ts();        }        else{error();}     }     else{        if(isNum(*current)){            //system("pause");cout<<"当前值为数字\n";            T();Ts();        }        else{            error();         }     }     //cout<<"退出E()\n";     } void Ts(){    //cout<<"Ts()\n";     if(isChar(*current)){        //system("pause");cout<<"当前值为字符\n";        if((*current)->getChar()=='#' || (*current)->getChar()==')'){            //cout<<"当前值为字符#或)\n";        }         else{            if((*current)->getChar()=='+'){match('+');T();GenCode('+');Ts();}            else{                if((*current)->getChar()=='-'){                    match('-');T();GenCode('-');Ts();                 }                 else{                    error();                 }             }         }     }     else{        error();     }     //cout<<"退出Ts()\n"; } void T(){    //cout<<"T()\n";     if(isChar(*current)){        //system("pause");cout<<"当前值为字符\n";         if((*current)->getChar()=='('){P();Ps();}        else{error();}     }    else{        if(isNum(*current)){            //system("pause");cout<<"当前值为数字\n";            P();Ps();        }        else{error();}     }     //cout<<"退出T()\n"; } void Ps(){    //cout<<"Ps()\n";     if(isChar(*current)){        //system("pause");cout<<"当前值为字符\n";         if((*current)->getChar()=='+' || (*current)->getChar()=='-' || (*current)->getChar()=='#' || (*current)->getChar()==')'){            //cout<<"当前值为字符+或-或#或)\n";         }        else{            if((*current)->getChar()=='*'){match('*');P();GenCode('*');Ps();}            else{                if((*current)->getChar()=='/'){match('/');P();GenCode('/');Ps();}                 else{error();}             }         }     }     else{error();}     //cout<<"退出Ps()\n"; } void P(){    //cout<<"P()\n";     if(isNum(*current)){        //system("pause");cout<<"当前值为数字\n";         s.push((*current)->getNum());        //cout<<"压入"<<((*current)->getNum())<<endl;         current++;     }     else{        if(isChar(*current)){            //system("pause");cout<<"当前值为字符\n";             if((*current)->getChar()=='('){match('(');E();match(')');}            else{error();}         }      }     //cout<<"退出P()\n"; } int main(){    //while(1){     //while(!s.empty()){s.pop();}     //while(v.size()!=0){v.clear();}         string str;    cin>>str;//输入字符串,以#号结束     //如  (1+3)*(2-4/1)#     //如    (-0.3)*(2+2)#         if(str.at(0)=='+' || str.at(0)=='-'){str="0"+str;}        int pos=0;    while((pos=str.find('+',pos))!=string::npos && str.at(pos-1)!=')'){        if(!isdigit(str.at(pos-1))){            str.insert(pos,"0");pos+=1;        }        pos++;     }     pos=0;    while((pos=str.find('-',pos))!=string::npos && str.at(pos-1)!=')'){        if(!isdigit(str.at(pos-1))){str.insert(pos,"0");pos+=1;}        pos++;     }         //cout<<"processed :"<<str<<endl;        const char* iter=str.c_str();         iter=str.c_str();        while(*iter!='\0'){        if(*iter=='+' || *iter=='-' || *iter=='*' || *iter=='/' || *iter=='=' || *iter=='(' || *iter==')'){            if(*iter=='='){v.push_back(pointer<node>(new char_node('#')));}             else{                v.push_back(pointer<node>(new char_node(*iter)));            }             iter++;         }        else{            float f=atof(iter);            v.push_back(pointer<node>(new num_node(f)));            while((*iter>='0' && *iter<='9') || *iter=='.'){iter++;}         }     }         //cout<<"total parts : "<<v.size()<<endl;         //for_each(v.begin(),v.end(),print4);         current=v.begin();          E();     match('#');        if(!s.empty()){cout<<s.top()<<endl;}         //char c;     //cout<<"继续?y/n\n";cin>>c;if(c=='n')break;     //}         system("pause");}    
用的是表达式文法

E -> T Ts

Ts -> null

Ts -> +T Ts

Ts -> -T Ts

T -> P Ps

Ps -> null

Ps -> * P Ps

Ps -> / P Ps

P -> C

P -> (E)


程序中输入如

(9-2)/2=

(-3)/(4-2)=

....

如果有语法错误,会终止





原创粉丝点击