思路与“中缀表达式转后缀表达式”相似
#include <iostream>
#include <cstring>
#include <stack>
#include <cmath>
using namespace std;
stack<double> num;
stack<char> oprt;
char s[1005];
int l = 0;
void in(){
char t[1005];
cin.getline(t, 1000);
int ll = strlen(t);
for(int i = 0; i < ll; ++i){
if(t[i] != ' '){
s[l++] = t[i];
}
}
}
double cal(double a, double b, char o){
if(o == '+') return a+b;
if(o == '-') return a-b;
if(o == '*') return a*b;
if(o == '/') return a/b;
else{
cerr << "error" << endl;
}
}
int main()
{
in();
int i = 0;
while(i < l){
if(isdigit(s[i]) || s[i] == '.'){
double b = 0;
while(i < l && isdigit(s[i])){
b *= 10;
b += s[i++] - '0';
}
if(s[i] == '.'){
++i;
int ct = 0;
while(i < l && isdigit(s[i])){
b += (s[i++]-'0') * pow(0.1, ++ct);
}
}
num.push(b);
}
else{
switch(s[i]){
case '+':
case '-':
while(!oprt.empty() && oprt.top() != '('){ // 如果用if,那么形如“1+2*3+”的式子就不能正常处理
double b = num.top(); num.pop();
double a = num.top(); num.pop();
num.push(cal(a,b,oprt.top())); oprt.pop();
}
oprt.push(s[i]);
break;
case '*':
case '/':
if(!oprt.empty() && (oprt.top() == '*' || oprt.top() == '/')){
double b = num.top(); num.pop();
double a = num.top(); num.pop();
num.push(cal(a,b,oprt.top())); oprt.pop();
}
oprt.push(s[i]);
break;
case '(':
oprt.push(s[i]);
break;
case ')':
while(!oprt.empty() && oprt.top() != '('){
double b = num.top(); num.pop();
double a = num.top(); num.pop();
num.push(cal(a,b,oprt.top())); oprt.pop();
}
oprt.pop(); // '('
break;
}
++i;
}
}
while(!oprt.empty()){
double b = num.top(); num.pop();
double a = num.top(); num.pop();
num.push(cal(a,b,oprt.top())); oprt.pop();
}
printf("%.2f\n", num.top());
system("pause");
return 0;
}
数月后另解,用运算符优先级确定运算顺序,更为本质:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <map>
using namespace std;
char s[605];
stack<int> num;
stack<char> oprt;
map<char, int> priority = {{'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'(', 0}, {')', 0}};
int cal(int a, int b, char op) {
// printf("calculating %d %c %d\n", a, op, b);
if (op == '+') return a+b;
if (op == '-') return a-b;
if (op == '*') return a*b;
if (b == 0)
cerr << "0 divisor" << endl;
if (op == '/') return a/b;
cerr << "bad op" << endl;
return 0;
}
void cal_and_push() {
int b = num.top(); num.pop();
int a = num.top(); num.pop();
char op = oprt.top(); oprt.pop();
int rst = cal(a, b, op);
num.push(rst);
}
int main()
{
int t; cin >> t; getchar();
while (t--) {
cin.getline(s, 605);
int i = 0;
int l = strlen(s);
while (i < l) {
if (isdigit(s[i])) {
int n = 0;
while (i < l && isdigit(s[i])) {
n *= 10;
n += s[i] - '0';
++i;
}
num.push(n);
}
else {
char c = s[i++];
if (c == '(') {
oprt.push(c);
}
else if (c == ')') {
while (!oprt.empty() && oprt.top() != '(')
cal_and_push();
oprt.pop(); // for '('
}
else {
while (!oprt.empty() && priority[oprt.top()] >= priority[c])
cal_and_push();
oprt.push(c);
}
}
}
while (!oprt.empty())
cal_and_push();
printf("%d\n", num.top());
num.pop();
}
return 0;
}
1646

被折叠的 条评论
为什么被折叠?



