首先,先来了解下什么是逆波兰表达式?逆波兰表达式又叫做后缀表达式,相当于二叉树中后根遍历。比如:计算(1-2)*(4+5)= -9,写成逆波兰表达式为1 2 - 4 5 + *。我们需要用一个栈来保存终端读入的字符(以空格为分界,输入EOF(ctrl + d)结束输入),当遇到数字时就入栈保存,当遇到运算符时,就连续取出两个栈顶的数字并进行运算,然后把运算结果压入栈中,再次从终端读入字符。当终端结束一个表达式的输入时(回车),程序会把当前标记的栈顶的值输出出来,作为表达式的结果。
下面,就让我们来实现逆波兰计算器,代码如下:
/* calc.h */
#ifndef _CALC_H
#define _CALC_H
#ifdef __cplusplus
extern "C"
{
#endif
#define NUMBER '0'
extern void push(double);
extern double pop(void);
extern int getop(char []);
extern int getch(void);
extern void ungetch(int);
}
#endif
/* main.cpp */
#include
#include
#include "calc.h"
#ifdef __cplusplus
extern "C"{
#define MAXTOP 100
/***** author: 王志平
****** date: 2015-9-6
****** name: main()函数
****** 功能:实现逆波兰计算器
比如: 123.5 + 4.7
逆波兰表达式为: 123.45 4.7 +
输入此表达式就可以得到结果:128.15
稍微复杂一点的:1 2 - 4 5 + *
结果为-9
******************************/
int main(void)
{
int type;
double op2;
char s[MAXTOP];
while ((type = getop(s)) != EOF)//输入按ctrl + c结束输入
{
switch (type)
{
case NUMBER:
push(atof(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0)
{
push( pop() / op2);
}
else
{
printf("error: zero divisor\n");
}
break;
case '\n':
printf("\t%.8g\n",pop());//打印栈顶的值,即结果
break;
default:
printf("error: unknown command %s\n",s);
break;
}
}
return 0;
}
#endif
}
/* gettop.cpp */
#include
#include
#include "calc.h"
#ifdef __cplusplus
extern "C"
{
/***** author: 王志平
****** date: 2015-9-6
****** name: int getop(char s[])
****** 功能:取下一个运算符或者数值运算分量
比如逆波兰输入:1 2 - 4 5 + *
每个输入要以空格隔开,不能123.45+ 4.7会出错
******************************/
int getop(char s[])
{
int i,c;
//跳过空格和制表符
c = getch();
s[0] = c;
while (s[0] == ' ' || c == '\t')
{
c = getch();
s[0] = c;
}
s[1] = '\0';//空格分割的一类输入终止,比如1 2 +,三个字符以空格分割,处理单字符,在后面加上结束标志
if (!isdigit(c) && c != '.')//不是数字
{
return c;
}
i = 0;
if(isdigit(c))//搜集整数部分
{
c = getch();
++i;
s[i] = c;
while (isdigit(s[i]))
{
c = getch();
++i;
s[i] = c;
}
}
if (c == '.')//搜集小数部分
{
c = getch();
++i;
s[i] = c;
while (isdigit(s[i]))
{
c = getch();
++i;
s[i] = c;
}
}
s[i] = '\0';//数字搜集完毕
if (c != EOF)//提前读了一个字符,回退回去,比如: 123.45空格,此时把+回退
{
ungetch(c);
}
return NUMBER;
}
#endif
}
/* getch.cpp */
#include
#ifdef __cplusplus
extern "C"
{
#define BUFSIZE 100
static char buf[BUFSIZE];//输入缓冲区,getchar()从终端读取字符
static int bufp = 0;
/***** author: 王志平
****** date: 2015-9-6
****** name: int getch(void)
****** 功能:取一个字符(可能是退回的字符)
******************************/
int getch(void)
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
/***** author: 王志平
****** date: 2015-9-6
****** name: void ungetch(int c)
****** 功能:把字符退回到输入中
******************************/
void ungetch(int c)
{
if (bufp >= BUFSIZE)
{
printf("ungetch: too many characters\n");
}
else
{
buf[bufp++] = c;
}
}
#endif
}
/* stack.cpp */
#include
#ifdef __cplusplus
extern "C"
{
#define MAXVAL 100
static int sp = 0;
static double val[MAXVAL]; //存储栈,栈顶元素即为最终结果
/***** author: 王志平
****** date: 2015-9-6
****** name: void push(double f)
****** 功能:把元素f下推到栈中
******************************/
void push(double f)
{
if(sp < MAXVAL)
{
val[sp++] = f;
}
else
{
printf("error: stack full,can't push %g\n",f);
}
}
/***** author: 王志平
****** date: 2015-9-6
****** name: double pop (void)
****** 功能:弹出并返回栈顶的值
******************************/
double pop(void)
{
if (sp > 0)
{
return val[--sp];
}
else
{
printf("error: stack empty.\n");
return 0.0;
}
}
}
#endif
逆波兰表达式计算器

964

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



