逆波兰计算机的实现

逆波兰表达式计算器

首先,先来了解下什么是逆波兰表达式?逆波兰表达式又叫做后缀表达式,相当于二叉树中后根遍历。比如:计算(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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值