02-线性结构3. 求前缀表达式的值(25)
时间限制
400 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
算术表达式有前缀表示法、中缀表示法和后缀表示法等形式。前缀表达式指二元运算符位于两个运算数之前,比如2+3*(7-4)+8/4的前缀表达式是:+ + 2 * 3 - 7 4 / 8 4。请设计程序计算前缀表达式的结果值。
输入格式说明:
输入在一行内给出不超过30个字符的前缀表达式,仅仅包括+、-、*、\以及运算数,不同对象(运算数、运算符号)之间以空格分隔。
输出格式说明:
输出前缀表达式的运算结果。精确到小数点后1位。或错误信息“ERROR”。
例子输入与输出:
序号 | 输入 | 输出 |
1 | + + 2 * 3 - 7 4 / 8 4 | 13.0 |
2 | / -25 + * - 2 3 4 / 8 4 | 12.5 |
3 | / 5 + * - 2 3 4 / 8 2 | ERROR |
4 | +10.23 | 10.2 |
#include <stdio.h>
#include <string.h>
#include <ctype.h>
double parseNum(char *s, int head, int rear) { //分析字符串。返回相应数值
double ret = 0;
double flag = 1; //标记数值正负号
if (s[head] == '+' || s[head] == '-') { //推断正负号
if (s[head] == '-')
flag = -1;
++head;
}
while (head <= rear && s[head] != '.') { //处理小数点之前部分。即整数部分
ret = 10 * ret + (s[head] - '0');
++head;
}
if (s[head] == '.') { //假设有小数部分,计算小数部分
++head;
double weight = 0.1;
while (head <= rear) {
ret += (double)(s[head] - '0') * weight;
weight *= 0.1;
++head;
}
}
return flag * ret;
}
int main() {
char s[30];
gets(s);
double numStack[15]; //用于储存操作数的栈
int numSize = 0; //栈元素个数
int rear = strlen(s) - 1;
//从输入字符串尾部開始遍历。遇到操作数将其压入栈中;遇到操作符。弹出栈顶两个元素运算,运算结果入栈
for (int head = rear; rear >= 0; --head) {
if (head == -1 || s[head] == ' ') { //两个空格之间为一个处理单元;第一个处理单元前没有空格。head = -1推断
//假设是个操作符,从操作数栈中弹出两个数进行运算,运算结果入栈
if (rear - head == 1 && (s[rear] == '+' || s[rear] == '-' || s[rear] == '*' || s[rear] == '/')) {
double num1 = numStack[--numSize];
double num2 = numStack[--numSize];
switch (s[rear]) {
case '+':
numStack[numSize++] = num1 + num2;
break;
case '-':
numStack[numSize++] = num1 - num2;
break;
case '*':
numStack[numSize++] = num1 * num2;
break;
case '/':
numStack[numSize++] = num1 / num2;
if (num2 < 1e-5 && num2 > -1e-5) { //被除数是0时输出错误信息,终止程序
printf("ERROR\n");
return 0;
}
break;
}
}
else { //假设是操作数,分析数值后入栈
numStack[numSize++] = parseNum(s, head + 1, rear);
}
rear = head - 1;
}
}
printf("%.1f\n", numStack[0]);
return 0;
}
题目链接:http://www.patest.cn/contests/mooc-ds/02-%E7%BA%BF%E6%80%A7%E7%BB%93%E6%9E%843