计算器到处都有,有啥好写的呢
我们在写程序时,对于长串计算,我们通常直接输入了,让计算机高级语言(例如 C++)给我们算就行了。但是,仔细想想这件事其实并不简单。
最初想做这件事的原因是:我在大学想写一个带 GUI 界面的计算器,就在这里被卡住了。
其实这是一个很有名的问题,大家有兴趣可以搜一下 逆波兰式
逆波兰式
逆波兰式即为后缀表达式,我们生活中算数表达式一般都是中序表达式。人类易于理解中序表达式,但计算机更容易处理后缀表达式。
直奔解决方案
我们的做法基本分
- 确定好符号集和它们的优先级
- 中序表达式转化成后缀表达式
- 根据后缀表达式得到最终结果
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
| #include<iostream> #include<string> #include<stack> #include<algorithm> using namespace std; const int INF=0x7fffffff; int pre(char a){ if(a=='='||a=='(') return 0; if(a=='+'||a=='-') return 1; if(a=='*'||a=='/') return 2; return -1; } string getsuffixexpression(string a){ stack<char> ope; ope.push('='); string ans; for(int i=0;i!=a.size();++i){ if(a[i]>='0'&&a[i]<='9'){ ans.push_back(a[i]); }else if(a[i]=='('){ ope.push('('); }else if(a[i]==')'){ while(!ope.empty()&&ope.top()!='('){ ans.push_back(ope.top()); ope.pop(); } ope.pop(); }else if(a[i]!='+'&&a[i]!='-'&&a[i]!='*'&&a[i]!='/'){ cout<<"error"<<endl; return ""; }else if(pre(a[i])>pre(ope.top())){ ope.push(a[i]); ans.push_back(' '); }else{ while(pre(a[i])<=pre(ope.top())){ ans.push_back(ope.top()); ope.pop(); } ope.push(a[i]); } } while(ope.top()!='='){ ans.push_back(ope.top()); ope.pop(); } return ans; } int getans(string a){ string b=getsuffixexpression(a); if(b.empty()) return INF; stack<int> s; for(int i=0;i!=b.size();++i){ if(b[i]==' ') continue; if(b[i]>='0'&&b[i]<='9'){ int t=0; while(i!=b.size()&&b[i]>='0'&&b[i]<='9'){ t=t*10+b[i++]-'0'; } --i; s.push(t); }else{ int x,y; if(!s.empty()){ y=s.top(); s.pop(); } if(!s.empty()){ x=s.top(); s.pop(); }else{ cout<<"error"<<endl; return INF; } switch(b[i]){ case '+': s.push(x+y); break; case '-': s.push(x-y); break; case '*': s.push(x*y); break; case '/': s.push(x/y); break; } } } int ans=s.top(); s.pop(); if(s.empty()) return ans; cout<<"error"<<endl; return INF; } int main(){ string a; while(cin>>a){ if(getans(a)!=INF){ cout<<getans(a)<<endl; } } return 0; }
|