逆波兰计算器就是用来计算逆波兰表达式的计算器。先谈一谈逆波兰表达式(RPN)吧,逆波兰表达式就是平常说的后缀表达式,即类似数字在前,符号在后的形式。例如:
a+b —> a,b,+
a+(b-c) —> a,b,c,-,+
a+(b-c)d —> a,b,c,-,d,,+
a+d*(b-c)—>a,d,b,c,-,*,+
a=1+3 —> a,1,3,+,=
正常的式子我们叫做中缀表达式,它方便人类的阅读计算,但计算机处理中序表达式(中缀表达式)非常复杂。计算机处理后缀表达式非常简便,因为计算机普遍采用的内存结构是栈式结构,遵循后入先出的原则。只需入栈和出栈两个操作就可以实现逆波兰表达式的计算。如果遇到数字就入栈,如果遇到符号就将栈顶的两个元素出栈并作相应的运算,之后将结果入栈,最终栈中剩下的那个数字就是最终结果。
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#define STACK_INIT_SIZE 20
#define STACK_DILA_SIZE 10
typedef double elemtype;
typedef struct
{
elemtype * base;
elemtype * top;
int stacksize;
}sqstack;
void initstack(sqstack*s)
{
s->base = (elemtype*)malloc(STACK_INIT_SIZE * sizeof(elemtype));
if (!s->base)
{
exit(0);
}
s->top = s->base;
s->stacksize = STACK_INIT_SIZE;
}
void push(sqstack*s, elemtype x)
{
if (s->top - s->base >= s->stacksize)
{
s->base = (elemtype*)realloc(s->base, (STACK_DILA_SIZE + STACK_INIT_SIZE) * sizeof(elemtype));
if (!s->base)
{
exit(0);
}
s->top = s->base + STACK_INIT_SIZE;
s->stacksize += STACK_DILA_SIZE;
}
*(s->top) = x;
s->top++;
}
void pop(sqstack*s, elemtype*x)
{
if (s->base == s->top)
{
return;
}
s->top--;
*x = *s->top;
}
int stacklen(sqstack*s)
{
return (s->top - s->base);
}
int main()
{
sqstack*s = (sqstack*)malloc(sizeof(sqstack));
initstack(s);
char c;
char str[10] = { '0' };//设置输入单个数字的缓冲区
int i = 0;
elemtype a, b, x;
scanf_s("%c", &c,sizeof(c));
while (c != '#')
{
while (isdigit(c)||c=='.')//过滤数字
{
str[i]=c;
i++;
scanf_s("%c", &c, sizeof(c));
if (c == ' ')
{
x = atof(str);//将字符型转为double型
push(s, x);
i = 0;
break;
}
}
switch (c)
{
case '+':
pop(s, &a);
pop(s, &b);
push(s, a + b);
break;
case '-':
pop(s, &a);
pop(s, &b);
push(s, b - a);
break;
case '*':
pop(s, &a);
pop(s, &b);
push(s, a*b);
break;
case '/':
pop(s, &a);
pop(s, &b);
push(s, b / a);
break;
}
scanf_s("%c", &c, sizeof(c));
}
pop(s, &x);
printf("%f", x);
return 0;
}
注:这个程序有一个弊端,因为计算时数据为double型,在进行除法运算时需要加上小数点,如10.0 5.0 / # 如果不加就会出错。