【ThinkingInC++】1、三写表达式求值

来源:互联网 发布:万果五笔输入法mac版 编辑:程序博客网 时间:2024/04/28 17:29
/*** 功能:表达式求值* 时间:2014年8月3日08:27:42* 作者:cutter_point*/#include<iostream>#include<cstdlib>#include<sstream>#include<string>using namespace std;/********************************************************************************/string OP="+-*/()#";//构建两个栈,一个数字栈一个字符栈/********************************************************************************///数字栈的数据结构typedef struct iStack{    int i;  //要用来计算的数字    iStack* next;   //指向下一个节点}*pIStack;//字符栈的数据结构typedef struct cStack{    char c; //操作符号    cStack* next;   //指向下一个节点}*pCStack;/********************************************************************************///定义两个全局栈变量,并初始化为空pIStack headIntSt=nullptr, tailIntSt=nullptr; //数字栈pCStack headCharSt=nullptr, tailCharSt=nullptr; //字符栈/********************************************************************************///栈的初始化,就是一个空的头节点initialise:初始化void initialiseIStack()    //数字栈初始化{    //创建一个空的头结点    pIStack p=new iStack;   //创建节点    p->next=nullptr;    headIntSt=p;  //设置为头结点(空的)    tailIntSt=p;    //吧尾节点指向追后一个}void initialiseCStack()     //字符栈的初始化{    //创建一个空的头结点    pCStack p=new cStack;   //创建节点    p->next=nullptr;    headCharSt=p;  //接入头结点    tailCharSt=p;    //吧尾节点指向追后一个}/********************************************************************************///栈的弹出并吧栈的弹出元素删除一个int popInt()       //给一个指针就是头指针,数字栈的删除{    pIStack p1;      //这两个指向最后一个的前一个,即倒数第二    p1=headIntSt;    //遍历找到倒数两个    while(p1->next != tailIntSt)   //只要p1->next不指向尾节点    {        p1=p1->next;    //指向下一个节点    }    //取得尾节点的值准备返回    int i=tailIntSt->i;    //吧尾节点delete掉    delete tailIntSt;    //重置尾节点    tailIntSt=p1;   //新的尾节点    return i;}char popChar()       //给一个指针就是头指针,字符栈的删除{    pCStack p1;      //这两个指向最后一个的前一个,即倒数第二    p1=headCharSt;    //遍历找到倒数两个    while(p1->next != tailCharSt)   //只要p1->next不指向尾节点    {        p1=p1->next;    //指向下一个节点    }    //取得尾节点的值准备返回    char c=tailCharSt->c;    //吧尾节点delete掉    delete tailCharSt;    //重置尾节点    tailCharSt=p1;   //新的尾节点    return c;}/********************************************************************************///栈的压入,增加一个节点void pushInt(int e)      //数字栈的压入{    //创建一个节点    pIStack p=new iStack;   //创建节点    p->i=e;    p->next=nullptr;    //接入到尾节点后面    tailIntSt->next=p;    //重置尾节点    tailIntSt=p;}void pushChar(char e)      //字符栈的压入{    //创建一个节点    pCStack p=new cStack;   //创建节点    p->c=e;    p->next=nullptr;    //接入到尾节点后面    tailCharSt->next=p;    //重置尾节点    tailCharSt=p;}/********************************************************************************///返回优先级符号,对两个字符比较/*  +  -  *  /  (  )  #  这里代表c2+ >  >  <  <  <  >  >- >  >  <  <  <  <  <* >  >  >  >  <  >  >/ >  >  >  >  <  >  >( <  <  <  <  <  =  ×) >  >  >  >  >  >  ># <  <  <  <  <  <  =这个代表c1之间格式是c1 符号 c2*/char isFirst(char c1, char c2){    char res;   //返回优先级比较结果    switch(c1)    {    case '+': case '-': //当第一个字符是这两个的时候        switch(c2)  //和后面的字符比较        {        case '+': case '-': case ')': case '#':            //当第二个字符是这些的时候,c1的优先级比他们大            res='>';            break;        case '*': case '/': case '(':            //当第二个字符是这些的时候,c1的优先级比他们小            res='<';            break;        }        break;    case '*': case '/':        switch(c2)  //和后面的字符比较        {        case '(':            //当第二个字符是这些的时候,c1的优先级比他们小            res='<';            break;        default:            res='>';            break;        }        break;    case '(':        switch(c2)  //和后面的字符比较        {        case ')':            //当第二个字符是这些的时候,c1的优先级比他们大            res='=';            break;        case '*': case '/': case '(': case '+': case '-': case '#':            //当第二个字符是这些的时候,c1的优先级比他们小            res='<';            break;        }        break;    case ')':        res='>';        break;    case '#':        switch(c2)        {        case '#':            res='=';            break;        default:            res='<';            break;        }        break;    }    return res;}/********************************************************************************///是否是运算符验证bool isOperator(char c){    bool b=false;//    string::size_type pos=0;    for(auto it=OP.begin() ; it != OP.end() ; ++it) //一个个匹配    {        if(c == *it)    //只要出现匹配立马跳出循环        {            b=true;            break;        }    }    return b;}/********************************************************************************///操作符转换成真正的operatorint doOperator(int a, char o, int b){    int res;    switch(o)    {    case '+':        res=a+b;        break;    case '-':        res=a-b;        break;    case '*':        res=a*b;        break;    case '/':        res=a/b;        break;    }    return res;}/********************************************************************************///表达式求值算法,求出表达式结果/*found=str.find_first_of("aeiou");while (found!=string::npos){    str[found]='*';    found=str.find_first_of("aeiou",found+1);}*/int result(string s)    //吧表达式字符串导入{    //首先清空栈,初始化    initialiseIStack();    initialiseCStack();    pushChar('#');  //给栈底添加#元素    while(s != "" || tailCharSt->c == '#')    {        //吧s分割成2快,第一个数字快和后面字符快        int found=s.find_first_of(OP);        string si=s.substr(0, found);   //第一个数字,不包括第found那个字符        //吧数字入栈        if(si != "")  //如果数字不为空,就是取到数字了而不是字符        {            int sitoi;  //si转化成的int类型            stringstream stream(si);    //使用sstream头文件流来转化            stream>>sitoi;      //转化为int            //cout<<sitoi<<" sdfs "<<2*sitoi<<"  sadasdadasd"<<endl;            /*            void str2int(int &int_temp,const string &string_temp)            {                stringstream stream(string_temp);                stream>>int_temp;            }            */            pushInt(sitoi); //吧数字压入到数字栈        }        //处理字符压入栈还是出来运算        //取出运算符        char sc=s[found];       //string支持这种方式访问        s=s.substr(found+1, s.length());        //cout<<sc<<" ddddd "<<s<<endl;        //判断是不是操作符        if(isOperator(sc))        {            //是操作符那么入栈            //入栈之前和站内原有的字符比较            char bijiao=isFirst(tailCharSt->c, sc);            if(bijiao == '<')                //c1小于c2优先级,直接入栈                pushChar(sc);            else if(bijiao == '=')                popChar();  //括号匹配,直接把括号去掉            else if(bijiao == '>')            {                //c1的优先级比较大,那么进行c1的运算符操作                int b=popInt(); //出后面那个数字                int a=popInt(); //出前面那个数字                char o=popChar();   //前面那个优先级搞的字符进行操作                //进行字符操作                int c=doOperator(a, o, b);                //吧数字放回去                pushInt(c);                //吧优先级低的字符压入栈                //pushChar(sc);                //这里不能把符号加入,因为进行了运算,符号要等在数值后面添加                //我们得吧sc加回到string中                s=sc+s; //这一步很重要要点!!2014年8月5日10:52:59                //cout<<"ok?"<<endl;            }//else if(bijiao == '>')        }//if(isOperator(sc))    }//while(s != "" || tailCharSt->c == '#')    //返回数字栈的栈顶元素,就是结果    return tailIntSt->i;}/********************************************************************************/int main(){    string test;    cin>>test;    cout<<result(test)<<endl;    system("pause");    return 0;}//初步完成时间2014年8月3日17:14:11/********************************************************************************/


测试表达式:

(10-9)*24+128/4#


结果:

56


PS:这次的表达式求值比上两次有有点改进,就是不是仅仅停留在0~9数字之间的表达式求值了,而是比较大的数了,比如128比如10比如24,不限制位数。



1 0