您的位置:首页 > 其它

逆波兰计算器(存疑)

2018-02-28 12:28 176 查看
摘自The C Programming Language

逆波兰表示法:①所有运算符都跟在操作数后面。
                       ②不需要圆括号,只要知道每个运算符需要几个操作数。
                       如:中缀表达式:(1 - 2) * (4 + 5) ; 逆波兰表达式:1 2 - 4 5 + *
计算器程序的实现:每个操作数都被一次压入到栈中;当一个运算符到达时,从栈中弹出相应数目的操作数(对二元运算符来说是两个操作数),把该运算符作用于弹出的操作数,并把运算结果再压入栈中。
如:上例中。首先把1和2压入到栈中,再用两者之差-1取代它们;然后,将4和5压入到栈中,再用两者之和9取代它们。最后,从栈中取出栈顶的-1和9,并把它们的积-9压入到栈顶。到达输入行的末尾时,把栈顶的值弹出来并打印。
#include <stdio.h>
#include <stdlib.h>  /* 为了使用atof函数 */

#define MAXOP 100 /* 操作数或运算符的最大长度 */
#define NUMBER '0' /* 标识找到一个数 */

int getop(char);
void push(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());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if(op2 != 0.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;
}注意:+与*满足交换律,因此,操作数弹出次序无关紧要。但是,-与/两个运算符的左右操作数必须加以区分,为了保证正确的次序,引进临时变量op2;
#define MAXVAL 100 /* 栈al的最大深度 */

int sp = 0; /* 下一个空闲栈的位置 */
double val[MAXVAL]; /* 值栈 */

/* push函数:把f压入到值栈中 */
void push(double f)
{
if(sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}

/* 弹出并返回栈顶的值 */
double pop(void)
{
if(sp > 0)
return val[--sp];
else{
printf("error: stack empty\n");
return 0.0;
}
}进栈和出栈的标准用法:*p++ = val;    val = *--p;

#include <ctype.h>

int getch(void);
void ungetch(int);

/* getop函数:获取下一个运算符或数值操作数 */
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[++i] = c = getch())
;
if(c == '.') /* 收集小数部分 */
while(isdigit[++i] = c = getch())
;
s[i] = '\0'; /* 最后一个存入digit数组中的元素不是数字,所以用'\0'取代最后一个元素 */
if(c != EOF)
ungetch(c);
return NUMBER;
}

程序中经常会出现这样的情况:程序不能确定它读入的输入是否足够,除非能超前多读入一些输入。
例如:读入一些字符合成一个数字时,在看到第一个非数字字符之前,已经读入的数的完整性是不能确定的。
由于程序要超前读入一个字符,这样就导致最后有一个字符不属于当前所要读入的数。
所以我们需要“反读”不需要的字符,即每当程序多读入一个字符时,就把它压回到输入中。
我们编写一对互相协作的函数来模拟 反取字符 操作。getch函数用于读入下一个待处理的字符,ungetch函数用于把字符放回到输入中。这样,以后在调用getch函数时,在读入新的输入前先返回ungetch函数放回的那个字符。
①ungetch函数把要压回的字符放到一个共享缓冲区(字符数组)中,当该缓冲区不空时,getch函数就从缓冲区读取字符;当缓冲区为空时,getch函数就直接从输入中读字符。
②用一个下标变量来记住缓冲区中当前字符的位置。
#define BUFSIZE 100

char buf[BUFSIZE];  /* 用于ungetch函数的缓冲区 */
int bufp = 0;       /* buf中下一个空闲位置*/

/* 取一个字符(可能是压回的字符) */
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: