c语言 后缀表达式计算
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言 后缀表达式计算相关的知识,希望对你有一定的参考价值。
写了一个后缀表达式的计算,exp为传过来的后缀表达
定义了栈来存数,但最后的运行的结果不对,有看不出那里逻辑错哦
哪位高手可以帮我看看
double CalResult(char exp[]) /*后缀表达式的的计算*/
char c;
numstack numst;
double d1,d2,dr;
int k=0;
int i=0;
char a[50];
char * s;
init2 (&numst); /*栈的实现*/
c=exp[k++];
while (c!='\0')
if (c=='+'||c=='-'||c=='*'||c=='/'||c=='%')
d2=pop2(&numst);
d1=pop2(&numst);
switch(c)
case '+': dr=d1+d2;
case '-': dr=d1-d2;
case '*': dr=d1*d2;
case '/': dr=d1/d2;
case '%': dr=(double)((int)d1%(int)d2);
push2(&numst,dr);
if (c>='0'&&c<='9'||c=='.')
while (c!='|')
a[i++]=c;
c=exp[k++];
s=a;
d1=(double)atof(s);
push2(&numst,d1);
c=exp[k++];
dr=numst.num[numst.top];
return dr;
其中栈的实现部分
typedef struct
double num[100];
int top;
int size;
numstack;
void init2(numstack *st) /*初始化顺序栈*/
st->size=0;
st->top=0;
double pop2(numstack *a) /*出栈*/
if (a->size==0)
exit(-1);
a->size--;
return a->num[--(a->top)];
void push2(numstack *a,double num) /*入栈*/
a->size++;
a->num[(a->top)++]=num;
a[i++]=c;
c=exp[k++];
//此处再加上a[i]='\0';表示字符串结束看看。 参考技术A 你的程序不好看!
没法看见你的栈结构,以及栈操作! 参考技术B 俺不懂
C语言数据结构算法——简单表达式求值(支持计算小数及负数)
样例输入输出
输入为一段简单表达式(中缀),表达式中的数据可以是小数
以及整数
,负数
前后都有括号分隔,以下是一段输入样例:
4.5*(3.8-0.9*2)+2.5*(9.6/(-2.4))
输出为计算结果即 -1
。
中缀表达式转后缀表达式
代码如下,算法思路在注释里了,改进了算法加入了对小数
以及负数
的支持:
/*
以下为中缀表达式转后缀表达式:
while (从exp读取字符ch,ch!='\\0')
ch为数字:
将后续的所有数字均依次存放到postexp中,并以字符'#'标志数值串结束;
ch为左括号'(':
将此括号进栈到Optr中;
ch为右括号')':
将Optr中出栈时遇到的第一个左括号'('以前的运算符依次出栈并存放到postexp中,然后将左括号'('出栈;
ch为'+'或'-':
出栈运算符并存放到postexp中,直到栈空或者栈顶为'(',然后将'+'或'-'进栈;
ch为'*'或'/':
出栈运算符并存放到postexp中,直到栈空或者栈顶为'('、'+'或'-',然后将'+'或'-'进栈;
若exp扫描完毕,则将Optr中所有运算符依次出栈并存放到postexp中。
增添内容:
负数的判断:
表达式首出现减号一定为负数,左括号后为减号该减号代表负数
小数点的处理:
小数点直接进postexp,小数点前的数每次乘10,小数点后的数每次除以10
*/
void trans(char *exp, char postexp[])
char e;
SqStack *Optr; //定义运算符栈指针
InitStack(Optr); //初始化运算符栈
int i=0; //i作为postexp的下标
while (*exp != '\\0') //exp表达式未扫描完时循环
switch(*exp)
case '(': //判定为左括号
exp++; //获取左括号后字符
if (*exp == '-')//左括号后为减号则一定为负数
postexp[i++] = *exp; //减号进postexp
exp++;
while(*exp != ')') //依次读取完负数的数值部分
postexp[i++] = *exp;
exp++;
postexp[i++]='#';
exp++; //将负数对应的右括号处理掉(无需进栈)
break;
else
Push(Optr,'('); //左括号进栈
break;
case ')': //判定为右括号
Pop(Optr,e); //出栈元素e
while (e!='(') //不为'('时循环
postexp[i++]=e; //将e存放到postexp中
Pop(Optr,e); //继续出栈元素e
exp++; //继续扫描其他字符
break;
case '+': //判定为加号
while (!StackEmpty(Optr)) //栈不空循环
GetTop(Optr,e); //取栈顶元素e
if (e!='(') //e不是'('
postexp[i++]=e; //将e存放到postexp中
Pop(Optr,e); //出栈元素e
else //e是'(时退出循环
break;
Push(Optr,*exp); //将'+'或'-'进栈
exp++; //继续扫描其他字符
break;
case '-':
if (i == 0) //减号出现在表达式首位一定为负数
postexp[i++] = *exp;
exp++;
while(*exp != ')')
postexp[i++]=*exp;
exp++;
postexp[i++]='#';
exp++; // ')'
break;
else //以下内容同加号
while (!StackEmpty(Optr)) //栈不空循环
GetTop(Optr,e); //取栈顶元素e
if (e!='(') //e不是'('
postexp[i++]=e; //将e存放到postexp中
Pop(Optr,e); //出栈元素e
else //e是'(时退出循环
break;
Push(Optr,*exp); //将'+'或'-'进栈
exp++; //继续扫描其他字符
break;
case '*': //判定为'*'或'/'号
case '/':
while (!StackEmpty(Optr)) //栈不空循环
GetTop(Optr,e); //取栈顶元素e
if (e=='*' || e=='/')
postexp[i++]=e; //将e存放到postexp中
Pop(Optr,e); //出栈元素e
else //e为非'*'或'/'运算符时退出循环
break;
Push(Optr,*exp); //将'*'或'/'进栈
exp++; //继续扫描其他字符
break;
default: //处理数字字符和点
while ((*exp>='0' && *exp<='9') || *exp=='.') //判定为数字字符或点
postexp[i++]=*exp; //全部进postexp即可
exp++;
postexp[i++]='#'; //用#标识一个数值串结束
while (!StackEmpty(Optr)) //此时exp扫描完毕,栈不空时循环
Pop(Optr,e); //出栈元素e
postexp[i++]=e; //将e存放到postexp中
postexp[i]='\\0'; //给postexp表达式添加结束标识
DestroyStack(Optr); //销毁栈
后缀表达式求值
代码如下:
/*
后置表达式求值算法如下:
while (从postexp读取字符ch,ch!='\\0')
ch为'+':
从Opnd栈中出栈两个数值a和b,计算c=b+a;将c进栈;
ch为'-':
从Opnd栈中出栈两个数值a和b,计算c=b-a;将c进栈;
ch为'*':
从Opnd栈中出栈两个数值a和b,计算c=b*a;将c进栈;
ch为'/':
从Opnd栈中出栈两个数值a和b,若a不零,计算c=b/a;将c进栈;
ch为数字字符:
将连续的数字串转换成数值d,将d进栈;
返回Opnd栈的栈顶操作数即后缀表达式的值;
增添内容:
利用flag增添对负数的处理以及对小数点的处理
*/
double compvalue(char *postexp)
int flag = 1;
double a, b, c, d, e, i;
SqStack1 *Opnd; //定义操作数栈
InitStack1(Opnd); //初始化操作数栈
while (*postexp != '\\0') //postexp字符串未扫描完时循环
switch (*postexp)
case '+': //判定为'+'号
Pop1(Opnd, a); //出栈元素a
Pop1(Opnd, b); //出栈元素b
c = b + a; //计算c
Push1(Opnd, c); //将计算结果c进栈
postexp++;
break;
case '-': //判定为'-'号
postexp++; //获取减号后元素
if (*postexp >= '0' && *postexp <= '9') //若减号后为数字则为负数
flag = -1; //记flag为-1记录数值符号
break;
else
Pop1(Opnd, a); //出栈元素a
Pop1(Opnd, b); //出栈元素b
c = b - a; //计算c
Push1(Opnd, c); //将计算结果c进栈
break;
case '*': //判定为'*'号
Pop1(Opnd, a); //出栈元素a
Pop1(Opnd, b); //出栈元素b
c = b*a; //计算c
Push1(Opnd, c); //将计算结果c进栈
postexp++;
break;
case '/': //判定为'/'号
Pop1(Opnd, a); //出栈元素a
Pop1(Opnd, b); //出栈元素b
if (a != 0)
c = b / a; //计算c
Push1(Opnd, c); //将计算结果c进栈
postexp++;
break;
else //错误处理
printf("\\n\\t除零错误!\\n");
exit(0); //异常退出
postexp++;
break;
default: //处理数字字符
d = 0; //转换成对应的数值存放到d中
i = 1.0; //处理小数用以每往后一位数除以10
while ((*postexp >= '0' && *postexp <= '9') || *postexp == '.')
if (*postexp == '.') //小数点后没往后一位数其值除以10
i /= 10;
postexp++;
continue;
if (i >= 1) //小数点前的情况
d = 10 * d + (*postexp - '0');
postexp++;
else //小数点后的情况
d += i * (*postexp - '0');
postexp++;
Push1(Opnd, flag * d); //将数值d进栈
flag = 1; //重新记符号为正号
postexp++;
break;
GetTop1(Opnd, e); //取栈顶元素e
DestroyStack1(Opnd);//销毁栈
return e; //返回e
运行示例
编写主函数如下:
int main(int argc, char const *argv[])
char exp[]="4.5*(3.8-0.9*2)+2.5*(9.6/(-2.4))";
char postexp[MaxSize];
trans(exp, postexp);
cout << "中缀表达式 : " << exp << endl;
cout << "后缀表达式 : " << postexp << endl;
cout << "表达式的值 : " << compvalue(postexp) << endl;
return 0;
运行结果如下:
想要完整代码(就是顺序栈部分你们也可以自行百度)可下载我上传的资源:C语言数据结构算法-简单表达式求值(支持计算负数及小数),
主要重要的部分已经在这啦~
以上是关于c语言 后缀表达式计算的主要内容,如果未能解决你的问题,请参考以下文章
数据结构(C语言版)严蔚敏->用栈求解表达式(中缀表达式后缀表达式)
数据结构(C语言版)严蔚敏->用栈求解表达式(中缀表达式后缀表达式)