算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,例如2+3*(7-4)+8/4
的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4
。请设计程序计算前缀表达式的结果值。
输入格式:
输入在一行内给出不超过30个字符的前缀表达式,只包含+
、-
、*
、/
以及运算数,不同对象(运算数、运算符号)之间以空格分隔。
输出格式:
输出前缀表达式的运算结果,保留小数点后1位,或错误信息ERROR
。
输入样例:
+ + 2 * 3 - 7 4 / 8 4
输出样例:
13.0
解题思路:
解析前缀表达式并计算值的方法为:从右往左读取式子,如果遇到数字那么就入栈,如果遇到运算符,就从栈中弹出两个数字a和b,其中a为栈顶元素,计算完成后再压入栈中。
这道题需要注意的点是:
1. 结算结果需要保留一位小数,所以应该用double型记录结果
2. 数字有可能是小数
3. 当进行运算符运算的时候如果栈中没有两个元素则返回ERROR;当进行除法运算的时候如果b=0则返回ERROR
#include <stdio.h>
#include <stdlib.h>
#include <stack>
#include <iostream>
using namespace std;
#define MAXSIZE 1010
char exp[MAXSIZE];
int idx=0;
stack<double> num; //存数字的堆栈
int isDigit(char a){
if(a>='0' && a<='9'){
return 1;
} else {
return 0;
}
}
int main(){
char a;
while(~scanf("%c", &a)){
exp[idx++] = a;
}
for(int j=idx-1; j>=0; j--){
if(isDigit(exp[j])){ //解析数字这里有点难啊
double time=1;
double outcome = 0;
while(exp[j] != ' ' && j>=0){ //只要不等于空格就继续
if(exp[j]=='-'){
outcome = -outcome;
j--;
continue;
} else if(exp[j] == '+'){
j--;
continue;
} else if(isDigit(exp[j])){
outcome += (double)(time*(exp[j]-'0'));
time *= 10;
j--;
continue;
} else if(exp[j]=='.'){
outcome = outcome/time;
time = 1;
j--;
continue;
}
j--;
}
num.push(outcome);
j++;
} else if(exp[j]=='+' || exp[j]=='-' || exp[j]=='*' || exp[j]=='/'){ //遇到运算符需要先将两个运算数出栈
double a, b;
if(num.empty()){
printf("ERROR");
return 0;
}
a = num.top();
num.pop();
if(num.empty()){
printf("ERROR");
return 0;
}
b = num.top();
num.pop();
double outcome = 0;
switch(exp[j]){
case '+':
outcome = a+b;
break;
case '-':
outcome = a-b;
break;
case '*':
outcome = a*b;
break;
case '/':
if(b == 0){
printf("ERROR");
return 0;
}
outcome = a/b;
break;
default:
break;
}
num.push(outcome);
}
}
if(num.size()!=1){
printf("NULL");
} else {
printf("%.1lf", num.top());
}
return 0;
}