目录
我个人认为表达式处理的核心思路和难点就在于,中缀表达式转换成后缀表达式,符号优先级和输入的处理。
中缀表达式转换成后缀表达式
for(;k<i;k++)
{
if(c[k]>='0'&&c[k]<='9')
change(c,&k,i,S1);
else
{
switch(c[k])
{
case '(':
push(S2,c[k]);
break;
case ')':
if(S2->date[S2->top]=='(')
pop(S2,&d);
else
like(S1,S2);
break;
case '+':
case '-':
if(likestackempty(S2)||S2->date[S2->top]=='(')
;
else
{
while(S2->date[S2->top]=='*'||S2->date[S2->top]=='/'||S2->date[S2->top]==')'||S2->date[S2->top]=='-'||S2->date[S2->top]=='+')
like(S1,S2);
}
push(S2,c[k]);
break;
case '*':
case '/':
if(S2->date[S2->top]!=')'&&S2->date[S2->top]!='*'&&S2->date[S2->top]!='/')
;
else
{
while(S2->date[S2->top]==')'||S2->date[S2->top]=='*'||S2->date[S2->top]=='/')
like(S1,S2);
}
push(S2,c[k]);
break;
}
}
}
转换的过程中要满足:符号优先级比操作符栈顶符号高的就进行入栈操作,低的就将数字栈弹栈两次,操作符栈弹出一次。 之后要注意假设a是数字栈栈顶,b是数字栈次栈顶,则要将b op a 的结果压入数字栈。
下图是上述操作的代码
void like(likestack1 *S1,likestack2 *S2)
{
double b,a;
char e;
pop(S1,&a);
pop(S1,&b);
pop(S2,&e);
switch(e)
{
case '*':
push(S1,b*a);
break;
case '/':
push(S1,b/a);
break;
case '+':
push(S1,b+a);
break;
case '-':
push(S1,b-a);
break;
}
}
输入的处理
输入时要注意多位数字和小数的处理,一种思路是用string类去处理,一种是用字符数组自己写个处理函数,这边是第二种(qaq)。
void change (char c[],int *k,int i,likestack1 *S1)
{
int a;
double b=0;
a=*k;
if(c[a+1]=='.')
{
b=c[a]-48;
a=a+2;
while(a<i)
{
b+=(c[a]-48)*pow(10,*k-a+1);
a++;
if(c[a]>'9'||c[a]<'0')
break;
}
push(S1,b);
*k=a-1;
}
else if(c[a+1]>='0'&&c[a+1]<='9')
{
a++;
while(c[a+1]<='9'&&c[a+1]>='0')
{
a++;
}
for(;*k<=a;*k=*k+1)//??
{
b+=(c[*k]-48)*pow(10,a-*k);
}
push(S1,b);
*k=*k-1;
}
else
push(S1,c[a]-48);
}
具体思路就这样了。。。。。。第一次写博客,初心想的是,一方面可以当作复习资料,另一方面也可以让其他人参考参考。写的不好的地方请多担待,下次见(下附完整代码)。
#include <iostream>
#define MAXSIZE 100
#include <cstring>
#include <cmath>
#include <iomanip>
using namespace std;
struct likestack1
{
int top;
double date[MAXSIZE];
};
struct likestack2
{
int top;
char date[MAXSIZE];
};
template <class T1,class T2>
bool push(T1 *S,T2 e)
{
if(S->top==MAXSIZE-1)
return false;
S->top++;
S->date[S->top]=e;
return true ;
}
template <class T1,class T2>
bool pop(T1 *S,T2 *e)
{
if(S->top==-1)
return false;
*e=S->date[S->top];
S->top--;
return true;
}
template <class T1,class T2>
bool gettop(T1 *S,T2 *e)
{
if(S->top==-1)
return false;
*e=S->date[S->top];
return true;
}
template <class T>
bool likestackempty(T *S)
{
if(S->top==-1)
return true;
else
return false;
}
void like(likestack1 *S1,likestack2 *S2)
{
double b,a;
char e;
pop(S1,&a);
pop(S1,&b);
pop(S2,&e);
switch(e)
{
case '*':
push(S1,b*a);
break;
case '/':
push(S1,b/a);
break;
case '+':
push(S1,b+a);
break;
case '-':
push(S1,b-a);
break;
}
}
void change (char c[],int *k,int i,likestack1 *S1)
{
int a;
double b=0;
a=*k;
if(c[a+1]=='.')
{
b=c[a]-48;
a=a+2;
while(a<i)
{
b+=(c[a]-48)*pow(10,*k-a+1);
a++;
if(c[a]>'9'||c[a]<'0')
break;
}
push(S1,b);
*k=a-1;
}
else if(c[a+1]>='0'&&c[a+1]<='9')
{
a++;
while(c[a+1]<='9'&&c[a+1]>='0')
{
a++;
}
for(;*k<=a;*k=*k+1)//??
{
b+=(c[*k]-48)*pow(10,a-*k);
}
push(S1,b);
*k=*k-1;
}
else
push(S1,c[a]-48);
}
int main()
{
char c[100],d;
int i=0,k=0;
likestack1 *S1=new likestack1;
likestack2 *S2=new likestack2;
S1->top=-1;
S2->top=-1;
cin>>c;
i=strlen(c)-1;
for(;k<i;k++)
{
if(c[k]>='0'&&c[k]<='9')
change(c,&k,i,S1);
else
{
switch(c[k])
{
case '(':
push(S2,c[k]);
break;
case ')':
if(S2->date[S2->top]=='(')
pop(S2,&d);
else
like(S1,S2);
break;
case '+':
case '-':
if(likestackempty(S2)||S2->date[S2->top]=='(')
;
else
{
while(S2->date[S2->top]=='*'||S2->date[S2->top]=='/'||S2->date[S2->top]==')'||S2->date[S2->top]=='-'||S2->date[S2->top]=='+')
like(S1,S2);
}
push(S2,c[k]);
break;
case '*':
case '/':
if(S2->date[S2->top]!=')'&&S2->date[S2->top]!='*'&&S2->date[S2->top]!='/')
;
else
{
while(S2->date[S2->top]==')'||S2->date[S2->top]=='*'||S2->date[S2->top]=='/')
like(S1,S2);
}
push(S2,c[k]);
break;
}
}
}
while(1)
{
if(S2->top==-1)
break;
like(S1,S2);
}
cout<<fixed<<setprecision(2)<<S1->date[S1->top];
return 0;
}