简单四则运算之逆波兰式解法
前提:数字为单个0~9,只有四则运算符,不含括号优先级(数字和优先级均可拓展)
易错点
1. 字符串读取
不含空格:整行读取
开辟char数组,以字符串形式 %s 读取,以空白符为分割;
含有空格:单个字符逐个读取
开辟char字符, %c 读取;
【注意 %c 的读取不会跳过空格等空白符,对于以空格为间隔的输入,可在 %c 前面加空格处理。即 "(空格)%c" 】
2. 数字与运算符混合处理
单个字符判断是否为十进制数字(0~9): isdigit() 函数 (头文件<ctype.h>)
数字字符char转int计算:- ‘0’
int数字转字符char输出:+ ‘0’
precede函数检查优先级:注意优先级相等情况的考虑!
操作数读取时注意先后顺序,被除(减)数和除(减)数不要弄反了!!
知识考点归纳
一般的表达式计算采用的是中缀(操作数在操作符两边紧挨着),逆波兰式则采用的是后缀(操作符紧挨在两个操作数后面)。
注意从左到右依次运算这一默认优先级。
表达式读取核心逻辑:
- 创建rpn主栈存储逆波兰式,oprs临时栈存储运算符;
- 先读取起始的三个字符,数字入rpn,运算符入oprs;
- 此后必为一个运算符,一个数字交替出现。所以,新读取运算符先与top(oprs)比较,后者优先级大于等于前者均出栈入rpn,新运算符一直与oprs栈顶元素比较,直到运算符优先级比栈顶高或者栈空为止。
- 读取完全部输入后不要忘记检查oprs是否为空,不为空则全部出栈依次入栈rpn。
- 因为是栈结构,所以最后输出前一定要进行反转。
- 逆波兰式的的读取计算较简单一些:读取数字一直入临时栈(存储操作数),直到读取运算符,弹出栈顶的两个元素进行运算(注意两个数的顺序),结果再入栈,继续读取,直到最后剩一个数字即为最终运算结果。(注意数字和字符的转化)
代码(C,包括简单的栈实现)
//简单四则远算(不含括号,两级运算优先级)逆波兰式解法 #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define ERROR 0 #define OK 1 typedef struct Stack { char *data; int top_index, max_size; } Stack; void init(Stack *s, int size) { s->data = (char *)malloc(sizeof(char) * size); s->max_size = size; s->top_index = -1; return; } int push(Stack *s, int data) { if (s->top_index >= s->max_size - 1) { return ERROR; } s->top_index++; s->data[s->top_index] = data; return OK; } int top(Stack *s) { return s->data[s->top_index]; } int pop(Stack *s) { if (s->top_index < 0) { return ERROR; } s->top_index--; return OK; } int empty(Stack *s) { if (s->top_index < 0) { return 1; } else { return 0; } } void clear(Stack *s) { free(s->data); free(s); return; } int precede(char c1, char c2) { int score1, score2; if(c1 == '+' || c1 == '-') { score1 = 0; } else { score1 = 1; } if(c2 == '+' || c2 == '-') { score2 = 0; } else { score2 = 1; } return score1 >= score2; } Stack *reverse(Stack *s) { Stack *tmp = (Stack *)malloc(sizeof(Stack)); init(tmp, 20); while (!empty(s)) { push(tmp, top(s)); pop(s); } clear(s); return tmp; } void output(Stack *s) { for (int i = s->top_index; i > 0; --i) { printf("%c", s->data[i]); } printf("%c ", s->data[0]); return; } void calculate(Stack *s, char op) { int a = top(s) - '0'; pop(s); int b = top(s) - '0'; pop(s); switch (op) { case '+' : push(s, (b + a) +'0'); break; case '-' : push(s, (b - a) + '0'); break; case '*' : push(s, (b * a) + '0'); break; case '/' : push(s, (b / a) + '0'); break; } } int calc(Stack *s) { Stack *tmp = (Stack *)malloc(sizeof(Stack)); init(tmp, 20); char data; while (!empty(s)) { data = top(s); pop(s); if (isdigit(data)) { push(tmp, data); } else { calculate(tmp, data); } } return top(tmp) - '0'; } int main() { Stack *rpn = (Stack *)malloc(sizeof(Stack)); init(rpn, 20); Stack *oprs = (Stack *)malloc(sizeof(Stack)); init(oprs, 20); char *tmp = (char *)malloc(sizeof(char) * 20); scanf("%s", tmp); int i = 0; push(rpn, tmp[i++]); push(oprs, tmp[i++]); push(rpn, tmp[i++]); while (tmp[i] != '