这个题就是给一个中缀表达式(普通算式)有+-*/和^(乘方)五种运算,而且有负数。
思路:先把中缀表达式转化为后缀表达式,然后根据后缀表达式,利用栈求值。(首先要知道后缀表达式求法和用法)
把中缀转化为后缀时,如果是数字就直接写,如果有左括号就把左括号加入栈,如果遇到运算符也加入栈,遇到了右括号时,把左右括号之间的运算符全部pop,并加入后缀表达式,然后一定要把左括号pop,因为左括号运算优先级低,不pop会影响后面的运算符出栈。还有就是得判断很多栈为空得情况,不然要segmentfaul。因为有负数,我把负数看作是减正数,没有数值和它相减,就用0和它相减。
后缀表达式求值就很简单了,遇到数字就入栈,遇到运算符就出栈,如果栈只有一个元素,就赋值为0(因为有负数)。
#pragma warning(disable:4996)
#include<climits>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<string>
using namespace std;
typedef long long ll;
char s[100005];//原来的字符串
char f[100005];//后最表达式
int prio(char t)//优先级
{
if(t==')'||t=='(')return -1;
else if(t=='+'||t=='-')return 0;
else if(t=='*'||t=='/')return 1;
else if(t=='^')return 2;
}
int calc(int i)//计算数字的值
{
int sum=0;
while(f[i]>='0'&&f[i]<='9')
{
sum=sum*10+f[i]-'0';
i++;
}
return sum;
}
int pow(int x,int y)//快速幂求乘方
{
int base=x,ans=1;
while(y)
{
if(y&1)ans=ans*base;
base=base*base;
y/=2;
}
return ans;
}
bool isope(char x)//判断是不是运算符
{
if(x=='+'||x=='-')return 1;
else if(x=='*'||x=='/')return 1;
else if(x=='^')return 1;
return 0;
}
void post()//计算后缀表达式,最难的地方
{
int L=strlen(s);
int i,j=0;
stack<char>st;
for(i=0;i<L;i++)
{
if(s[i]>='0'&&s[i]<='9')//如果是数字就直接填上去
{
f[j++]=s[i];
}
else if(s[i]=='(')//左括号压入栈中
{
st.push(s[i]);
}
else if(s[i]==')')//右括号
{
//一定要判断非空
while(!st.empty()&&st.top()!='(')
{
f[j++]=st.top();
st.pop();
}
if(!st.empty())st.pop();//弹出左括号!!
}
else if(isope(s[i]))//如果是运算符
{
f[j++]=' ';//把数字和数字之间分开
//pop掉优先级高的
while(!st.empty()&&prio(st.top())>=prio(s[i]))
{
f[j++]=st.top();
st.pop();
}
st.push(s[i]);//入栈
}
}
while(!st.empty())
{
f[j++]=st.top();
st.pop();
}//把剩下的出栈
f[j]=0;
}
int getans()//计算后缀表达式
{
int ans=0,i=0,temp,j,len,t1,t2;
len=strlen(f);
stack<int>t;
while(i<len)
{
//cout<<f[i]<<" ! "<<i<<endl;
if(f[i]>='0'&&f[i]<='9')
{
temp=calc(i);
t.push(temp);
while(f[i+1]>='0'&&f[i+1]<='9')i++;
//因为while循环最后会i++,所以判断i+1
}
else if(isope(f[i]))//遇到运算符
{
t1=t.top();t.pop();
if(t.empty())t2=0;//因为可能有负数。
else
{
t2=t.top();t.pop();
}
if(f[i]=='+')
{
ans=t1+t2;
}
else if(f[i]=='-')
{
ans=t2-t1;
}
else if(f[i]=='*')
{
ans=t1*t2;
}
else if(f[i]=='/')
{
ans=t2/t1;
}
else if(f[i]=='^')
{
ans=pow(t2,t1);
}
t.push(ans);
}
i++;
}
return t.top();
}
int main()
{
int ans;
scanf("%s",s);//输入
post();//求后缀表达式
//cout<<f<<endl;
ans=getans();//根据后缀表达式求值
printf("%d\n",ans);
return 0;
}