逆波兰算术表达式 C语言

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了逆波兰算术表达式 C语言相关的知识,希望对你有一定的参考价值。

35 逆波兰算术表达式(选作)
成绩: 5 / 折扣: 0.8
传统的算术表达式是由操作数(又叫运算对象或运算量)和运算符以及改变运算次序的圆括号连接而成的式子。 其运算规则如下:

(1) 先计算括号内,后计算括号外;
(2) 在无括号或同层括号内,先进行乘除运算,后进行加减运算,即乘除运算的优先级高于加减运算的优先级;
(3) 同一优先级运算,从左向右依次进行。

在这种表达式的计算过程中,既要考虑括号的作用,又要考虑运算符的优先级,还要考虑运算符出现的先后次序。

波兰科学家卢卡谢维奇(Lukasiewicz)提出了算术表达式的另一种表示,即后缀表示,又称逆波兰式,其定义是把运算符放在两个运算对象的后面。在后缀表达式中,不存在括号,也不存在优先级的差别,计算过程完全按照运算符出现的先后次序进行,整个计算过程仅需一遍扫描便可完成。

例如:
3/5+6的逆波兰表达式为3 5 / 6 +
2*(3+4)的逆波兰表达式为2 3 4 + *

输入:
一个只包含加、减、乘、除和数字的逆波兰表达式

输出:
该表达式的值

//利用栈去处理算术方法,利用后缀表达式去处理,只涉及到“+”“-”“*”“/”“()”

#define MAXSIZE 1000
struct
char data[MAXSIZE];
int top;
op;
struct
float data[MAXSIZE];
int top;
st;
//后缀表达式的建立,关键在于圆括弧和加减乘除的处理问题
void trans(exp,postexp)
char exp[MAXSIZE],postexp[MAXSIZE];


char ch;
int i=0,j=0;
op.top=-1;
ch=exp[i];
i++;

while(ch!='\0')

switch(ch)

case '(':
op.top++;
op.data[op.top]=ch;
break;
case ')':
while(op.data[op.top]!='(')
postexp[j]=op.data[op.top];
j++;
op.top--;

op.top--; //将“(”弹栈
break;
//在这里由于我们是按照从左到右的顺序去计算 因此新得出来的“+”“-”的优先级小于原来在栈里面的优先级
//“*”“/”也是一样的
case '+':
case '-':
while(op.top!=-1&&op.data[op.top]!='(')
postexp[j]=op.data[op.top];
j++;
op.top--;

op.top++;
op.data[op.top]=ch;
break;
case '*':
case '/':
while(op.top!=-1 && op.data[op.top]!='(' && (op.data[op.top]=='*'||op.data[op.top]=='/'))
postexp[j]=op.data[op.top];
j++;
op.top--;

op.top++;
op.data[op.top]=ch;
//break;
case ' ':
break;
default:
while(ch>='0'&&ch<='9')
postexp[j]=ch;
j++;
ch=exp[i];
i++;

i--;
postexp[j]='#';
j++;

ch=exp[i];
i++;

while(op.top!=-1)
postexp[j]=op.data[op.top];
j++;
op.top--;

postexp[j]='\0';


//对表达式进行计算
float compvalue(postexp)
char postexp[MAXSIZE];

char ch;
int k=0;
float d;
st.top=-1;
ch=postexp[k];
k++;
while(ch!='\0')
switch(ch)
case '+':
st.data[st.top-1]=st.data[st.top-1]+st.data[st.top];
st.top--;
break;
case '-':
st.data[st.top-1]=st.data[st.top-1]-st.data[st.top];
st.top--;
break;
case '/':
if(st.data[st.top!=0])
st.data[st.top-1]=st.data[st.top-1]/st.data[st.top];
st.top--;

else
printf("除数不能为零!@\n");

break;
case '*':
st.data[st.top-1]=st.data[st.top-1]*st.data[st.top];
st.top--;
break;
default:
d=0;
while(ch>='0'&&ch<='9')
d=d*10+ch-'0';
ch=postexp[k];
k++;

st.top++;
st.data[st.top]=d;

ch=postexp[k];
k++;

return st.data[st.top];



int main()
char expo[MAXSIZE],postexpo[MAXSIZE];
int i=0;
//char postexpo[1000];
for(i=0;i<1000;i++)
postexpo[i]='\0';

printf("请输入你要计算的表达式:\n");
scanf("%s",&expo);
trans(expo,postexpo);
printf("你输入的表达式的结果-----:%f",compvalue(postexpo));
return 0;

个人写的程序
参考技术A 我用c语言写的wintc下运行正确
希望对你有帮助
#include<stdio.h>
#include<string.h>
int
nibolan(char
s[])

int
i=0,a,b;
char
*p;
p=s
;
while(*p!='\0')
if(*p=='+')*p=((*(p-2)-48)+(*(p-1)-48))+48;
if(*p=='-')*p=((*(p-2)-48)-(*(p-1)-48))+48;
if(*p=='*')*p=((*(p-2)-48)*(*(p-1)-48))+48;
if(*p=='/')*p=((*(p-2)-48)/(*(p-1)-48))+48;
p++;

p--;
return
(*p)-48;

main()

int
r;
char
a[100];
gets(a);
r=nibolan(a);
printf("%d",r);
getch();
参考技术B #include <stdio.h>
#include <stdlib.h>
typedef struct stack
char c[100];
int top;
int size;
stack;
typedef struct level
char ch;
int l;
level;
void initStack(stack *s)

s->top=-1;
s->size=100;


void pushStack(stack *s,char ch)

s->top++;
if(s->top>=s->size)
printf("已满");
else
s->c[s->top]=ch;

char popStack(stack *s)

char ch;
if(s->top==-1)
printf("已空");
else
ch=s->c[s->top--];
return ch;


int main(int argc, char *argv[])

struct level lev[4];
struct stack s;
lev[0].ch='+';
lev[0].l=1;
lev[1].ch='-';
lev[1].l=1;
lev[2].ch='*';
lev[2].l=2;
lev[3].ch='/';
lev[3].l=2;
initStack(&s);
int i=0,j=0;
char a[100],newa[100];
scanf("%s",a);
while(a[i]!='#')

if(a[i]>='0'&&a[i]<='9')
newa[j]=a[i];
j++;

else if(a[i]=='(')
pushStack(&s,a[i]);
else if(a[i]==')')

char ch=popStack(&s);
while(ch!='(')

newa[j]=ch;
j++;
ch=popStack(&s);



else

int x;
int stackVar,arrayVar;
do
stackVar=0;
arrayVar=0;
for(x=0;x<4;x++)
if(lev[x].ch==a[i])
arrayVar=lev[x].l;
if(lev[x].ch==s.c[s.top])
stackVar=lev[x].l;

if(arrayVar<=stackVar)
newa[j]=popStack(&s);j++;
else
pushStack(&s,a[i]);
while(arrayVar<=stackVar);

i++;

while(s.top!=-1)
newa[j]=popStack(&s);j++;
int y;
for(y=0;y<j;y++)
printf("%c",newa[y]);
system("PAUSE");
return 0;

(C语言中)逆波兰算法(及计算器)

Q.1: 用reverse Polish notation 表示12+3 是否是 "123+" ? 如果是, 不是和1 + 23的表示 相冲? (为了防止相冲,各个数字间是否需要特定符号隔开?)

Q.2: (Q.1 得到答复后再问)

非常感谢!

逆波兰式子又叫做后缀表达式。(相对于前缀和中缀,但是它俩都破坏了式子本身,所以用后缀)

12+3应该表达为12 3+。(实际无空格,为了好看)
先解决一个问题,就是123+会不会认为是1和23或者1和2和3,其实是不会的。一般后缀式都是用栈存储的,你在定义栈的时候里面的elemtype e(当然也可以用别的就是举例),这个elemtype是重命名的int。scanf或者cin输入的时候,你先输入12,这个就被存在栈的第一空里面(因为是%d嘛),再输入3就被存在第二空里面了。这个不会混淆。

逆波兰算法是这么工作的:在后缀式中扫描,可能会扫描到一堆数字,但是这时候如果扫描到了一个运算符(加减乘除等),这时候提取运算符并提取运算符前面紧挨着的那两个数字(注意是紧挨),然后这两个数字和这一个运算符进行运算。比如123+,扫描得12,扫描得3,扫描得+(电脑得到了+这个运算符),紧接着取前面紧挨的12和3,进行运算,就是12+3了。如(2+1) * 3就是21+3*。扫描得2,扫描得1,扫描得+,ok这时候2+1=3,3入栈,重新while扫描。扫描得3(刚才算出来刚入栈的那个),扫描得3,扫描得*,ok这时候3*3=9。

1+23这种后缀式是表达不出来的。后缀它的意义就在于两个数,他们的运算符关系紧挨在他们后面。这个1+只有一个数,还原算是就是+1,无意义。
参考技术A a+b ---> a,b,+
a+(b-c) ---> a,b,c,-,+
a+(b-c)*d ---> a,b,c,-,d,*,+
a+d*(b-c)--->a,d,b,c,-,*,+
a=1+3 ---> a=1,3 +
它的优势在于只用两种简单操作,入栈和出栈就可以搞定任何普通表达式的运算。其运算方式如下:
如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。本回答被提问者采纳
参考技术B 我是来围观的

以上是关于逆波兰算术表达式 C语言的主要内容,如果未能解决你的问题,请参考以下文章

中缀表达式转为后缀表达式(逆波兰式)求值

中缀表达式转为后缀表达式(逆波兰式)求值

(C语言中)逆波兰算法(及计算器)

150. 逆波兰表达式求值

用逆波兰表示法计算算术表达式的值。这段代码有啥错误,只有一个测试用例给了我错误的答案

算法表达式求值--逆波兰算法介绍