第五周项目5-后缀表达式(栈)!!!

问题及代码:

/*     
Copyright (c)2016,烟台大学计算机与控制工程学院     
All rights reserved.     
文件名称:ysx.cpp     
作 者:于苏显   
完成日期:2016年11月12日     
版 本 号:v1.0     
     
     
问题描述:利用sqstack.h中栈的基本运算,实现将一个算术表达式转换为对应的后缀表达式的算法。
          例如,输入(56-20)/(4+2)
          输出后缀表达式::56#20#-4#2#+/  和 运算结果:6
          要求在数字后加#。
输入描述:算术表达式   
程序输出:后缀表达式 和 对后缀表达式求值的结果
*/     

利用顺序栈算法库求后缀表达式运算结果


#include "sqstack.h"
#include <math.h>
int wrong=0;   //判断表达式是否正确(全局变量)
struct  //定义运算符优先级
{
    char ch;   //运算符
    int pri;   //优先级
}
lpri[]= {{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}},//左运算符为栈顶运算符
rpri[]= {{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};//右运算符为表达式运算符
//若遇到')'(优先级为1)将'('后入栈的运算符依次出栈
bool Match(char *s)    //判断括号是否匹配
{
    char c;
    int match=1;
    SqStack *p;
    InitStack(p);
    for(int i=0; s[i]!='\0'&&match; i++)
    {
        if(s[i]=='(') Push(p, s[i]);
        else if(s[i]==')')
        {
            if(GetTop(p,c)) Pop(p,c);
            else
            {
                match=0;
                break;
            }
        }
    }
    if(StackEmpty(p)&&match==1)
        return true;
    else
        return false;
}

int leftpri(char op)    //求左运算符op的优先级
{
    int i;
    for (i=0; i<7; i++)
        if (lpri[i].ch==op)
            return lpri[i].pri;
}

int rightpri(char op)  //求右运算符op的优先级
{
    int i;
    for (i=0; i<7; i++)
        if (rpri[i].ch==op)
            return rpri[i].pri;
}

bool InOp(char ch)       //判断是否为运算符
{
    if (ch=='(' || ch==')' || ch=='+' || ch=='-' || ch=='*' || ch=='/')
        return true;
    else
        return false;
}

int Precede(char op1,char op2)  //比较运算符优先级
{
    if (leftpri(op1)==rightpri(op2))
        return 0;
    else if (leftpri(op1)<rightpri(op2))
        return -1;
    else
        return 1;
}

void trans(char *exp,char *postexp) //将算术表达式exp转换成后缀表达式postexp
{
    SqStack *opstack;               //定义运算符栈
    int i=0,first=0;                //i作为postexp的下标
    char ch;
    InitStack(opstack);   //用初始化栈运算为栈分配空间
    Push(opstack, '=');
    while (*exp!=NULL)      
    {
        if (InOp(*exp))       //运算符
        {
			if(*exp=='+'||*exp=='-'||*exp=='*'||*exp=='/')
			{
				if( (*(exp-1)=='+'||*(exp-1)=='-'||*(exp-1)=='*'||*(exp-1)=='/') || *(exp+1)==NULL || first==0)
				//若表达式中有两个连续的算术运算符或首位,末位字符为算术运算符,表达式错误
				//经测试,当*exp为首位字符时,*(exp-1)='?'(不知道原因)
				{
					wrong=1;
				    return;
				}
			}
			if(*exp==')' && *(exp-1)=='(')
			{
				wrong=1;
			    return;
			}
            GetTop(opstack, ch);   //取得栈顶的运算符
            switch(Precede(ch ,*exp))
            {
            case -1:           //栈顶运算符的优先级低(进栈)
                Push(opstack, *exp);
                exp++;     //继续扫描
				first++;
                break;
            case 0:        //只有括号满足这种情况
                Pop(opstack, ch);      //将(退栈
                exp++;     //继续扫描
                break;
            case 1:             //退栈并输出到postexp中
                postexp[i++]=ch;
                Pop(opstack, ch);//出栈后不执行exp++,继续用当前运算符比较
                break;
            }
        }
        else if ((*exp>='0' && *exp<='9')||*exp=='.')    //数字
        {
            while ((*exp>='0' && *exp<='9')||*exp=='.') 
            {
                if( (*exp=='.' && *(exp-1)=='.') || (*(exp+1)=='('))//连续两个 '.' 或数字后直接跟'(' 表达式错误
                {
                    wrong=1;
                    return;
                }
                postexp[i++]=*exp++;
				first++;
            }
            postexp[i++]='#';   //用#标识一个数值串结束
        }
        else//出现除了运算符和数字以外的字符,表达式错误
        {
            wrong=1;
            return;
        }
    }
    Pop(opstack, ch);
    while (ch!='=')  //此时exp扫描完毕,退栈到'='为止
    {
        postexp[i++]=ch;
        Pop(opstack, ch);
    }
    postexp[i]='\0';    //给postexp表达式添加结束标识
    DestroyStack(opstack);
}

double compvalue(char postexp[])
{
    struct//定义数值栈
    {
        float data[MaxSize];
        int top;
    } st;
    int f;
    double d;
    char ch;
    int t=0;
    st.top=-1;
    ch=postexp[t++];
    while (ch)//postexp字符串未扫描完时循环
    {
        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 '*':
            st.data[st.top-1]=st.data[st.top-1]*st.data[st.top];
            st.top--;
            break;
        case '/':   //未表达st.data[st.top]==0的情形
            st.data[st.top-1]=st.data[st.top-1]/st.data[st.top];
            st.top--;
            break;
        default:
            d=0; //将数字字符转换成数值存放到d中
            f=-1;
            while ((ch>='0' && ch<='9')||ch=='.')
            {
                if(ch!='.') //整数情况
                {
                    d=10*d+ch-'0';
                    ch=postexp[t++];
                }
                else  //小数情况
                {
                    ch=postexp[t++];//越过小数点,扫描到字符串的下一位
					while(ch>='0' && ch<='9')//扫描到小数点后的数字被读取完为止
					{
						d+=pow(10,f)*(ch-'0');
						f--;
						ch=postexp[t++];
					}
                }
            }
           st.data[++st.top]=d;
        }
       ch=postexp[t++];
    }
   return st.data[st.top];
}

int main()
{
    char exp[100];
    char postexp[200];
    printf("  表达式的转换与求值\n\n");
    printf("请输入表达式\n");
    scanf("%s",exp);
    if(!Match(exp)) wrong=1;
    trans(exp,postexp);
    if(!wrong)//表达式正确,输出后缀表达式和运算结果
    {
        printf("中缀表达式: %s\n",exp);
        printf("后缀表达式: %s\n",postexp);
        printf("表达式的值为: %g\n",compvalue(postexp));
    }
    else//表达式错误
        printf("表达式有误\n");
    return 0;
}


 


运行结果:



知识点总结:使用了顺序栈算法库,括号是否匹配,熟练了后缀表达式的转换和求值方法。

学习心得:在老师给出的原始代码的基础上加了些功能,可以实现 小数的运算,能判断出错误的表达式和错误的书写方式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值