/** * 功能:表达式求值 * 时间: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; } /********************************************************************************/ //操作符转换成真正的operator int 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,不限制位数。
【ThinkingInC++】1、三写表达式求值,布布扣,bubuko.com
原文地址:http://blog.csdn.net/cutter_point/article/details/38418127