【C】逆波兰计算器程序

逆波兰表示法

在逆波兰表示法中,所有运算符都跟在操作数的后面。比如,下列中缀表达式:
(1-2)*(4+5)
采用逆波兰表示法表示为
1 2 - 4 5 + *

程序结构

while(下一个运算符或操作数不是文件结束指示符)
  if(是数)
    将该数压入到栈中
  else if(是运算符)
    弹出所需数目的操作数执行运算
    将结果压入到栈中
  else if(是换行符)
    弹出并打印栈顶的值
  else
    出错

子程序

字符缓冲 getch/ungetch

#define BUFSIZE 100
char buf[BUFSIZE];
int bufp=0;

getch

缓存区无字符,从外界读取字符 getchar()
缓存区有自付,从缓存区读取字符

int getch(void){
  return (bufp>0)?buf[--bufp]:getchar();
}

ungetch

将不属于当前输入的元素存入缓存区,以便后续利用

void ungetch(int c){
  if(bufp>=BUFSIZE)
    printf("error: too many charaters in buf\n");
  else
    buf[bufp++]=c; 
}

栈压入弹出

#define MAXVAL 100
int sp=0;
double val[MAXVAL];

pop

弹出并返回栈顶的值

double pop(void){
  if(sp>0)
    return val[--p];
  else{
    printf("error:stack empty\n");
    return 0.0;
  }
}

push

void push(int c){
  if(sp<MAXVAL)
    val[sp++]=c;
  else
    printf("error:stack full,can't push %g\n",f);
}

获取下一个运算符或操作数 getop

#include<ctype.h>
#define NUMBER '0'
int getch(void);
void ungetch(int);
int getop(s[]){
  while((s[0]=c=getch())==' '||c=='\t')
    ;
  s[1]='\0';
  if(!isdigit(c)&&c!='.')
    return c;
  i=0;
  if(isdigit(c))
    while(isdigit(s[++i]=c=getch()))
      ;
  if(c=='.')
    while(isdigit(s[++i]=c=getch()))
      ;
  s[i]='\0';
  if(c!=EOF)
    ungetch(c);
  return NUMBER;    
}

逆波兰计算器程序

#include<stdio.h>
#include<stdlib.h>/*为了使用atof()函数*/
#include<ctype.h> /*为了使用isdigit()函数*/

#define MAXOP 100 /*操作数或运算符的最大长度*/
#define NUMBER '0'/*标识找到一个数*/
#define MAXVAL 100/*栈val的最大深度*/
#define BUFSIZE 100/*缓存区*/


double val[MAXVAL];/*操作数寄存的栈*/
int sp = 0;        /*下一个空闲栈的位置*/
char buf[BUFSIZE]; /*字符的缓存区*/
int bufp = 0;      /*下一个缓冲的位置*/


int getch(void);   /*读(缓冲区/外界)字符*/
void ungetch(int); /*将非数字字符压入缓冲区*/
int getop(char s[]);/*下一字符串类别*/

void push(double);  /*将转化后的double压入栈*/
double pop(void);   /*弹出返回栈顶*/

int main() {
	int type;
	double op2;
	char s[MAXOP];

	while ((type = getop(s)) != EOF) {
		switch (type) {
		case NUMBER:
			push(atof(s));
			break;
		case '+':
			push(pop() + pop());
			break;
		case '*':
			push(pop() * pop());
		case'-':
			op2 = pop();
			push(pop() - op2);
			break;
		case'/':
			op2 = pop();
			push(pop() / op2);
		case'\n':
			printf("\t%.8g\n", pop());
			break;
		default:
			printf("error:unkonwn command %s\n", s);
			break;
		}
	}
	return 0;
}

int getch(void) {
	return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c) {
	if (bufp >= BUFSIZE)
		printf("ungetch: too many characters\n");
	else
		buf[bufp++] = c;
}

double pop(void) {
	if (sp > 0)
		return val[--sp];
	else {
		printf("error:stack empty\n");
		return 0.0;
	}
}

void push(double f) {
	if (sp < MAXVAL)
		val[sp++] = f;
	else
		printf("error:stack full, can't push %g\n", f);

}

int getop(char s[]) {
	int i, c;
	while ((s[0] = c = getch()) == ' ' || c == '\t')
		;
	s[1] = '\0';
	if (!isdigit(c) && c != '.')
		return c;
	i = 0;
	if (isdigit(c))
		while (isdigit(s[++i] = c = getch()))
			;
	if (c == '.')
		while (isdigit(s[++i] = c = getch()))
			;
	s[i] = '\n';
	if (c != EOF)
		ungetch(c);
	return NUMBER;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值