21.000+2/4=((1+2)*5+1)/4=
1.504.00
#define TRUE 1 #define FALSE 0 #define STACK_INIT_SIZE 10002 #include "iostream" #include "cstdlib" #include "cstdio" #include "cstring" using namespace std; typedef int Status; //Status 相当于 int typedef struct Stack1 //运算符栈 { char * base; char * top; }SqStack1; typedef struct Stack2 //数字栈 { double * base; double * top; }SqStack2; //运算符栈操作 void InitStack1(SqStack1 &S) //创建一个空栈 { S.base = (char *)malloc(sizeof(char) * STACK_INIT_SIZE); S.top = S.base; } Status Stack1Empty(SqStack1 S)//判断是否为空 { if(S.top == S.base) return TRUE; else return FALSE; } void Push1(SqStack1 &S,char e )//插入元素e为新的栈顶元素 { * S.top++ = e; } void Pop1(SqStack1 &S,char &e)//出栈 { e = * --S.top ; } char GetTop1(SqStack1 S) { return *(S.top-1); } void TraverseStack1(SqStack1 S)//输出当前顺序表 { char * p = S.base; cout<<"运算栈中的元素为:"; while( p != S.top ) { cout<<*p<<" "; p++; } cout<<endl; } //数字栈操作 void InitStack2(SqStack2 &S) //创建一个空栈 { S.base = (double *)malloc(sizeof(double) * STACK_INIT_SIZE); S.top = S.base; } void Push2(SqStack2 &S,double e )//插入元素e为新的栈顶元素 { * S.top++ = e; } void Pop2(SqStack2 &S,double &e)//出栈 { e = * --S.top ; } double GetTop2(SqStack2 S) { return *(S.top-1); } void TraverseStack2(SqStack2 S)//输出当前顺序表 { double * p = S.base; cout<<"数字栈栈中的元素为:"; while( p != S.top ) { cout<<*p<<" "; p++; } cout<<endl; } //运算操作 Status In(char ch)//判断ch是否为运算符 { if(ch == '+' || ch == '('|| ch == '-' || ch == '*' || ch == '/' || ch == ')' || ch == '=') return TRUE; else return FALSE; } char Precede(char a, char b) // 计算运算符优先级 { char r; switch(b) { case '+' : //此处由于加减几乎优先级一样,故放在一起 case '-' : if (a=='(' || a=='=') r = '<'; else r = '>'; break; case '*' : //此处由于乘除优先级一样,故放在一起 case '/' : if (a=='*' || a=='/' || a==')') r = '>'; else r = '<'; break; case '(' : r = '<'; break; case ')' : if (a=='(') r = '='; else r = '>'; break; case'=': if (a=='=') r = '='; else r = '>'; break; } return r; } double Operate(double a,char theta, double b) { switch (theta) { case '+': return a + b;break; case '-': return a - b;break; case '*': return a * b;break; case '/': return a / b;break; default : return FALSE; } } double EvaluateExpression(char str[]) { char *p = str; SqStack1 OPTR; SqStack2 OPND;//设OPTR和OPND分别为运算符栈和运算数栈 InitStack1(OPTR); InitStack2(OPND); Push1(OPTR,'='); char x,theta,c; double a,b,k,t,m; c = *p; while( !Stack1Empty(OPTR)) { if(!In(c) ) { for(k = 0; !In(c) && c!='.'&&c!='='; c = * ++p) k = 10*k + c-'0'; t = 0 ; if(c=='.') { c = * ++p; for(t = 0,m = 0.1 ; !In(c) ; c = * ++p) { t += m * (c-'0'); m *= 0.1; } } Push2(OPND,k+t); } else switch(Precede(GetTop1(OPTR),c)) { case '<': Push1(OPTR,c); c = * ++p; break; case '=': Pop1(OPTR,x); c = * ++p; break; case '>': Pop1(OPTR,theta); Pop2(OPND,b); Pop2(OPND,a); Push2(OPND,Operate(a,theta,b)); break; } } return GetTop2(OPND); } int main() { int n; scanf("%d",&n); while(n--) { char str[1002]; scanf("%s",str); printf("%.2lf\n",EvaluateExpression(str)); } return 0; }
2
1.000+2/4=
((1+2)*5+1)/4=
1.000 2 4 / + =
1 2 + 5 * 1 + 4 / =
转换过程需要用到栈,具体过程如下:
1)如果遇到操作数,我们就直接将其输出。
2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。也就是说这种操作," + "的优先级最低," ( "优先级最高。
5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
规则很多,还是用实例比较容易说清楚整个过程。以上面的转换为例,输入为a + b * c + (d * e + f)*g,处理过程如下:
1)首先读到a,直接输出。
2)读到“+”,将其放入到栈中。
3)读到b,直接输出。
此时栈和输出的情况如下:
4)读到“*”,因为栈顶元素"+"优先级比" * " 低,所以将" * "直接压入栈中。
5)读到c,直接输出。
此时栈和输出情况如下:
6)读到" + ",因为栈顶元素" * "的优先级比它高,所以弹出" * "并输出, 同理,栈中下一个元素" + "优先级与读到的操作符" + "一样,所以也要弹出并输出。然后再将读到的" + "压入栈中。
此时栈和输出情况如下:
7)下一个读到的为"(",它优先级最高,所以直接放入到栈中。
8)读到d,将其直接输出。
此时栈和输出情况如下:
9)读到" * ",由于只有遇到" ) "的时候左括号"("才会弹出,所以" * "直接压入栈中。
10)读到e,直接输出。
此时栈和输出情况如下:
11)读到" + ",弹出" * "并输出,然后将"+"压入栈中。
12)读到f,直接输出。
此时栈和输出情况:
13)接下来读到“)”,则直接将栈中元素弹出并输出直到遇到"("为止。这里右括号前只有一个操作符"+"被弹出并输出。
14)读到" * ",压入栈中。读到g,直接输出。
15)此时输入数据已经读到末尾,栈中还有两个操作符“*”和" + ",直接弹出并输出。
至此整个转换过程完成。程序实现代码后续再补充了。
1)先按照运算符的优先级对中缀表达式加括号,变成( ( a+(b*c) ) + ( ((d*e)+f) *g ) )
2)将运算符移到括号的后面,变成((a(bc)*)+(((de)*f)+g)*)+
3)去掉括号,得到abc*+de*f+g*+
计算就好说了,根据后缀表达式,遇到运算符则弹出两个操作数,计算后压栈,最后栈顶元素为计算结果
#define TRUE 1 #define FALSE 0 #define STACK_INIT_SIZE 10002 #include "iostream" #include "cstdlib" #include "cstdio" #include "cstring" using namespace std; typedef int Status; //Status 相当于 int typedef struct Stack1 //运算符栈 { char * base; char * top; }SqStack1; //运算符栈操作 void InitStack1(SqStack1 &S) //创建一个空栈 { S.base = (char *)malloc(sizeof(char) * STACK_INIT_SIZE); S.top = S.base; } Status Stack1Empty(SqStack1 S)//判断是否为空 { if(S.top == S.base) return TRUE; else return FALSE; } void Push1(SqStack1 &S,char e )//插入元素e为新的栈顶元素 { * S.top++ = e; } void Pop1(SqStack1 &S,char &e)//出栈 { e = * --S.top ; } char GetTop1(SqStack1 S) { return *(S.top-1); } void TraverseStack1(SqStack1 S)//输出当前顺序表 { char * p = S.base; cout<<"运算栈中的元素为:"; while( p != S.top ) { cout<<*p<<" "; p++; } cout<<endl; } Status In(char ch)//判断ch是否为运算符 { if(ch == '+' || ch == '('|| ch == '-' || ch == '*' || ch == '/' || ch == ')' || ch == '=') return TRUE; else return FALSE; } void In_to_Ne(char s[1002], char p[1002],int &l) { char c,ch; Stack1 S; InitStack1(S); int i,k, len; k = 0; len = strlen(s); for(i = 0; i< len ; ++i) { c =s[i]; // printf("c = %c\n",c); if( !In(c) ) { while(!In(c) ){ p[k++] = c; c = s[++i]; } p[k++] = ' '; }//操作数 if( Stack1Empty(S) ) Push1(S,c); else if( c == '(' ) Push1(S,c); else if(c == ')' ) { while( GetTop1(S)!= '(') { Pop1(S,ch);p[k++] = ch; p[k++] =' '; } Pop1(S,ch); //将(出栈 } //将栈顶元素弹出并放到p else if( (c == '+' || c=='-' )&&(GetTop1(S)=='(' ) ) Push1(S,c); else if( (c == '+' || c=='-' )&&(GetTop1(S) =='+' ||GetTop1(S)=='-'||GetTop1(S)=='*' ||GetTop1(S)=='/' ) ) { Pop1(S,ch); p[k++] = ch; p[k++] =' '; i = i-1; } //将栈顶元素弹出并放到p else if( (c == '*' || c=='/' )&&(GetTop1(S) =='+' ||GetTop1(S)=='-'|| GetTop1(S)=='(' ) ) Push1(S,c); else if( (c == '*' || c=='/' )&&(GetTop1(S) =='*' ||GetTop1(S)=='/') ) { Pop1(S,ch); p[k++] = ch; p[k++] =' '; i = i-1; } //将栈顶元素弹出并放到p // TraverseStack1(S); } while(!Stack1Empty(S) ) { Pop1(S,ch); p[k++] = ch; p[k++] =' '; } l = k; return ; } /* 2 1.000+2/4= ((1+2)*5+1)/4= */ int main() { char s[1002], p[1002]; int n,i,len; scanf("%d",&n); while(n--) { scanf("%s",s); In_to_Ne( s, p,len); for(i =0; i<len; ++i) printf("%c",p[i]); printf("=\n"); } return 0; }
聪明的你帮助C小加解决了中缀表达式到后缀表达式的转换(详情请参考“郁闷的C小加(一)”),C小加很高兴。但C小加是个爱思考的人,他又想通过这种方法计算一个表达式的值。即先把表达式转换为后缀表达式,再求值。这时又要考虑操作数是小数和多位数的情况。
21+2=(19+21)*3-4/5=
12+=3.001921+3*45/-=119.20
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <iomanip> #include <stack> using namespace std; int In(char e) { if(e=='(' || e==')' || e=='+' || e=='-' || e=='*' || e=='/') return 1; else return 0; } int cmp(char c) { switch(c) { case '+': case '-': return 1; case '*': case '/': return 2; default : return 0; } } double calculate(char op,double k1,double k2) { double k; switch (op) { case '+': k = k1+k2; break; case '-': k = k1-k2; break; case '*': k = k1*k2; break; case '/': k = k1/k2; break; } return k; } /* 20 (2.6)-(1.666)= 1+2= (19+21)*3-4/5= */ void change(char str[]) { int t,i,k,m; char e,buf[1002],op,s[1002]; double kk,k1,k2; stack <char> S1; stack <double> S2; k=0; S1.push('='); for(i=0;i<strlen(str)-1;++i) //最后一位是 = { if( In(str[i]) ) { switch(str[i]) { case '(': S1.push(str[i]); break; case ')': //遇到右括号, while(S1.top()!='(')//弹出栈元素输出 直到 (, { s[k++]=S1.top(); k1 = S2.top(); S2.pop(); k2 = S2.top(); S2.pop(); S2.push(calculate(S1.top(),k2,k1)); S1.pop(); } if(S1.top()=='(')//弹出(不输出 { S1.pop(); } break; default : while(cmp(str[i])<=cmp(S1.top())) { s[k++]=S1.top(); k1 = S2.top(); S2.pop(); k2 = S2.top(); S2.pop(); S2.push(calculate(S1.top(),k2,k1)); S1.pop(); } S1.push(str[i]); break; }//switch }//if else{ sscanf(str+i,"%[^=()+*/-]",buf); //操作数 for(m=0;m<strlen(buf);m++) s[k++]=buf[m]; //printf("%s",buf); i += strlen(buf)-1; kk = atof(buf); //printf("k = %lf\n",k); S2.push(kk); } }//for while(!S1.empty()) { if(S1.top()!='(' && S1.top()!='=') { s[k++]=S1.top(); k1 = S2.top(); S2.pop(); k2 = S2.top(); S2.pop(); S2.push(calculate(S1.top(),k2,k1)); } S1.pop(); } for(i=0;i<k;i++) printf("%c",s[i]); printf("=\n"); printf("%.2lf\n",S2.top()); } int main() { int t,i; char e,str[1002],buf[1002],op; double k,k1,k2; scanf("%d",&t); getchar(); while(t--) { gets(str); //puts(str); change(str); if(t>0) printf("\n"); } return 0; }
* + 11.0 12.0 + 24.0 35.0
1357.000000
#include <stack> #include <math.h> #include <iostream> #include <string.h> #include <stdio.h> #include <stdlib.h> using namespace std; void fan(char s[]) { char buf[10001]; int i,j=0; for(i=strlen(s)-1;i>=0;i--) buf[j++]=s[i]; buf[j]='\0'; for(i=0;i<strlen(s);i++) s[i]=buf[i]; } stack <double> s1; bool In(char c) { if(c=='-' || c=='+' || c=='*' || c=='/') return true; return false; } double calc(double k2,double k1, char op) { switch( op ) { case '+': return k2+k1; case '-': return k2-k1; case '*': return k2*k1; case '/': return k2/k1; } } double solve(char s[]) { char buf[10001],op; double k1,k2; int i,num_shu=0; // printf("%s\n",s); for(i=strlen(s)-1;i>=0;i--) { // printf("c=%c\n",s[i]); if(s[i]==' ') continue; if(In( s[i]) ){ k1=s1.top(); s1.pop(); k2=s1.top(); s1.pop(); // printf("k1=%f k2=%f,calc=%f\n",k1,k2,calc(k2,k1,op)); s1.push(calc(k1,k2,s[i])); } //caozuofu else //caozuoshu { int j=0; memset(buf,0,sizeof(buf)); while(s[i]!=' ') {buf[j]=s[i]; j++;i--;} //strrev(buf); fan(buf); // printf("buf=%s\n",buf); k1 = atof(buf); // i+= strlen(buf)-1; // printf("shu=%lf\n",k1); s1.push(k1); // cin>>i; } } // while(!s2.empty()) // { // k1=s1.top(); s1.pop(); // k2=s1.top(); s1.pop(); // op = s2.top(); s2.pop(); // // printf("k1=%f k2=%f,calc=%f\n",k1,k2,calc(k2,k1,op)); // s1.push(calc(k2,k1,op)); // num_shu = 1; // } return s1.top(); } // * + 11.0 12.0 + 24.0 35.0 int main() { char s[10001]; gets(s); printf("%f\n",solve(s)); return 0; }
#include <iostream> #include <stdlib.h> #include <string> #include <cstdio> using namespace std; double recur() { char s1[10]; scanf("%s",s1); switch(s1[0]) { case '+': return recur()+recur(); case '-': return recur()-recur(); case '*': return recur()*recur(); case '/': return recur()/recur(); default : return atof(s1); } return 0; } int main() { //freopen("in.txt","r",stdin); double res=0; res=recur(); printf("%lf\n",res); return 0; }