试着用c++写了一个计算器,支持加减乘除和括号。
我是分步完成的,先写了一个简单的不支持括号的,然后再改成支持括号版。
一. 仅支持加减乘除
用两个手写栈(不推荐stl的栈,因为栈不难写,stl感觉太慢),一个栈存储符号,一个栈存储已经读入的数(无符号)。
扫一遍表达式,把符号和数字按次序存进两个栈(注意,如果第一个数是正数,则第一个进栈的符号要是+号;如果是负数,则进栈一个-号,存储数的栈则存进正数)。存储符号的栈只需要存储+和-就行了,如果读到了*或号,就直接乘除给栈顶的数,这样可以保证乘除的优先级。
扫完了之后按顺序算一遍栈就行了。
#include <cstdio> #include <cstring> using namespace std; const int maxn=10000; int n; char ch[maxn+5]; int read_pos; //read()读入时最后一个字符的位置+1 inline int read(int s){ //返回以ch[s]为开头的数 int ans=0; for (;(ch[s]>='0'&&ch[s]<='9');s++) ans=ans*10+ch[s]-'0'; read_pos=s; return ans; } int solve(int l,int r){ //表达式l到r的值 int stack[2][maxn+5],len=0; //手写栈 if (ch[l]!='-') stack[0][++len]=1,stack[1][len]=read(l); else stack[0][++len]=-1,stack[1][len]=read(l+1); l=read_pos; int temp; while (l<=r){ if (ch[l]=='+') stack[0][++len]=1,stack[1][len]=read(l+1); else if (ch[l]=='-') stack[0][++len]=-1,stack[1][len]=read(l+1); else if (ch[l]=='*') temp=read(l+1),stack[1][len]*=temp; else temp=read(l+1),stack[1][len]/=temp; l=read_pos; } int result=0; for (int i=1;i<=len;i++) //处理掉栈中的数 result+=(stack[0][i]*stack[1][i]); return result; } int main(){ // freopen("test2.in","r",stdin); scanf("%s",ch); int tt=strlen(ch); printf("%d",solve(0,tt-1)); return 0; }
二. 支持括号
应该有很多种模拟方法,我是在预处理时存进每一对括号的位置,然后递归计算括号就行了(把括号当数来看)。
#include <cstdio> #include <cstring> using namespace std; const int maxn=10000; int n; char ch[maxn+5]; int to[maxn+5]; int que[maxn+5],size; int read_pos; int read(int s); int solve(int l,int r){ int stack[2][maxn+5],len=0; if (ch[l]!='-') stack[0][++len]=1,stack[1][len]=read(l); else stack[0][++len]=-1,stack[1][len]=read(l+1); l=read_pos; int temp; while (l<=r){ if (ch[l]=='+') stack[0][++len]=1,stack[1][len]=read(l+1); else if (ch[l]=='-') stack[0][++len]=-1,stack[1][len]=read(l+1); else if (ch[l]=='*') temp=read(l+1),stack[1][len]*=temp; else temp=read(l+1),stack[1][len]/=temp; l=read_pos; } int result=0; for (int i=1;i<=len;i++) result+=(stack[0][i]*stack[1][i]); return result; } int main(){ // freopen("test2.in","r",stdin); scanf("%s",ch); int tt=strlen(ch); for (int i=0;i<tt;i++) if (ch[i]=='(') que[++size]=i; else if (ch[i]==')') to[que[size]]=i,size-=1; printf("%d",solve(0,tt-1)); return 0; } inline int read(int s){ int ans=0,f=1; if (ch[s]=='('){ ans=solve(s+1,to[s]-1); read_pos=to[s]+1; return ans; } else if (ch[s]=='-') f=-1,s+=1; for (;(ch[s]>='0'&&ch[s]<='9');s++) ans=ans*10+ch[s]-'0'; read_pos=s; return ans*f; }