7-20 表达式转换 (25 分)
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。日常使用的算术表达式是采用中缀表示法,即二元运算符位于两个运算数中间。请设计程序将中缀表达式转换为后缀表达式。
输入格式:
输入在一行中给出不含空格的中缀表达式,可包含+
、-
、*
、\
以及左右括号()
,表达式不超过20个字符。
输出格式:
在一行中输出转换后的后缀表达式,要求不同对象(运算数、运算符号)之间以空格分隔,但结尾不得有多余空格。
输入样例:
2+3*(7-4)+8/4
输出样例:
2 3 7 4 - * + 8 4 / +
注意:表达式中有正负号,括号,多位数。
问题:将中缀表达式转化为后缀表达式:中缀表达式是一个字符串,其中有正负数,多位数和();
设计方案:遍历字符串。字符串中数字的相对位置不会改变,但是符号会入一个新栈,若栈为空,直接入栈,若不是判断此刻的符号和栈顶符号的优先级,若此刻的优先级比较低,则栈顶的符号可以跟在数字栈中最上面两个元素的后面,若此刻的优先级比较高,则加入到符号栈。如果遇到(,将他入栈且他后面紧邻的符号也要入栈,遇到)则将)前面的元素一个个弹出到数字的后面。如果字符串都遍历完了且字符栈不为空,则按从后向前的顺序将剩下的符号弹出到结果的最后。
对于正负号的判断:有加减号且加减号前面是非字符和非‘)’时不是加减法。
多位数:用流stringstream可以自动识别浮点数和整型数。但只能识别开头就是+-或整数的字符串,用substr解决这一问题,多位数和符号都用string来存储入栈。
代码
#include<iostream>
#include<stack>
#include<map>
#include<sstream>
#include<vector>
using namespace std;
map<char,int>mp;
int cmp(char a,char b)
{
if(a==')'&&b=='(')
return 0;
else if(mp[a]!=mp[b])
return mp[a]-mp[b];
else if(mp[a]==mp[b])
return -1;
}
char stringToChar(string s)
{
return s[0];
}
string charToString(char c)
{
string s;
s.push_back(c);
return s;
}
int main()
{
char a[21];
mp['-']=1;
mp['+']=1;
mp['(']=3;
mp[')']=0;
mp['*']=2;
mp['/']=2;
string s;
cin>>s;
int i;
stack<string>op,opd,res;
stringstream s1,s2;
s1.str(s);
for(i=0; i<s.size(); i++)
{
if((i-1>=0&&i+1<s.size()&&!isdigit(s[i-1])&&s[i-1]!=')'&&(s[i]=='-'||s[i]=='+')&&isdigit(s[i+1]))||isdigit(s[i])||(i==0&&(s[i]=='-'||s[i]=='+')))
{
double a;
string x;
s1.str(s.substr(i,s.size()-i));
s1>>a;
s2.str("");
s2<<a;
x=s2.str();
opd.push(x);
res.push(x);
i+=x.size()-1;
while(isdigit(s[i+1])||s[i+1]=='.')
i+=1;
}
else
{
if(!op.empty())
{
while(!op.empty()&&cmp(s[i], stringToChar(op.top()))<=-1&&stringToChar(op.top())!='(') //新的比栈顶优先级低
{
res.push(op.top());
op.pop();
}
if(!op.empty())
{
if(cmp(s[i],stringToChar(op.top()))==0)
{
op.pop();
}
else if(cmp(s[i],stringToChar(op.top()))>=1||stringToChar(op.top())=='(')
{
op.push(charToString(s[i]));
}
}
else
op.push(charToString(s[i]));
}
else
op.push(charToString(s[i]));
}
}
while(!op.empty())
{
res.push(op.top());
op.pop();
}
int k=0;
vector<string>v;
while(!res.empty())
{
v.push_back(res.top());
res.pop();
k++;
}
for(i=k-1; i>=0; i--)
{
if(i==k-1)
cout<<v[i];
else
cout<<" "<<v[i];
}
cout<<endl;
}