逆波兰计算机的实现

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

余额充值