使用顺序栈实现表达式求值(含c与c++)

 首先声明,此代码只能运算表达式的各部分运算后都是个位数字的类型

列如9*2-3,无法运算,因为9*2=18大于10了.若想知道原因,代码后面注释有

//栈的九个基本操作
//1.构造空栈
//2.销毁栈
//3.清空栈
//4.判断是否为空
//5.求栈长
//6.取栈顶元素
//7.入栈
//8.出栈
//9.遍历栈
#include <iostream>
#include <stdio.h>
using namespace std;
#include <stdlib.h>
#define MAXSIZE 100
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0//error错误
#define INFEASIBLE -1//infeasible不能实行的
#define OVERFLOWER -2//宏定义后面不用加分号
typedef int Status;
//Status是函数的类型,其值是函数结果状态代码;
typedef char SElemType;
//顺序栈的表示
typedef struct{
    SElemType *base;//栈底指针
    SElemType *top;
    int stacksize;//栈可用最大容量
}SqStack;
//顺序栈的初始化
//括号里面是地址
Status InitStack(SqStack &S){
    S.base=new SElemType[MAXSIZE];
    //C++语法,分配空间
    if(!S.base)exit (OVERFLOWER);//储存分配失败
    S.top=S.base;//栈顶指针等于栈底指针,栈为空
    S.stacksize=MAXSIZE;
    return OK;
}
//判断栈是否为空,是则返回TRUE,否则返回FALSE
//这个就与初始化不同,参数不为地址
Status StackEmpty(SqStack S){
    if(S.top==S.base){
        return TRUE;
    }
    else return FALSE;
}
//求顺序栈的长度
Status StackLength(SqStack S){
    return S.top-S.base;
}
Status ClearStack(SqStack S){
    if (S.base){S.top=S.base;return OK;} 
    return FALSE;      
//如果栈存在,清空    
}
Status DestroyStack(SqStack &S){
    if(S.base){
        delete S.base;
//释放base空间,因为当时是用它申请空间
        S.stacksize=0;
        S.base=S.top=NULL;
    }
    return OK;
}
//取栈顶元素
SElemType GetTop(SqStack S){
        return *--S.top;
        S.top++;
//		*--S.top;
}
//顺序栈的入栈操作
//传递的元素不是地址
Status Push(SqStack &S,SElemType e){
    if (S.top-S.base==S.stacksize)
    {
       return ERROR;
//满了,返回错误值,或者增加空间
    }
    else{ 
        *S.top=e;//当时写成*S.top==e;了.看完我人傻了 
    //因为构造的就是指针
    //指向元素
        S.top++;
    //地址加一
    //这两步也可以化简为*S.top++=e
        return OK;}   
}
//出栈
Status pop(SqStack &S,SElemType &e){
    if(S.top==S.base){//S.top==s.top这是人写的,我傻了 
        return ERROR;
    }
    else{
        S.top--;
        e=*S.top;
        //注意取用的是top下面的元素
        //可以简写为e==*--S.top
    return OK;
    }
}
//遍历栈
Status StackTraverse(SqStack S){
    char *p=S.base;
    if(S.base=S.top){
        return ERROR;
    }
    else for(p;p<S.top;p++){
         cout<<*p<<endl;
         return OK;
    }
    return ERROR;
}
//利用上述基本操作进行表达式求值
char OP[7]={'+','-','*','/','(',')','#'};
//OP位运算符集合
bool in(char c){
    for(int i=0;i<7;i++){
        if(c==OP[i]){
            return true;
        }
    }
    return false;
}//判断是否为运算符
//判断算数符号优先级,注意字符串与字符的区别,一般来说,单引号引字符,双引号引字符串,且字符可以直接比较
char operator_priority[7][7]={
    {'>','>','<','<','<','>','>'},
    {'>','>','<','<','<','>','>'},
    {'>','>','>','>','>','>','>'},
    {'>','>','>','>','>','>','>'},
    {'<','<','<','<','<','=',' '},
    {'>','>','>','>',' ','>','>'},
    {'<','<','<','<','<',' ','='}
};//第一行第一个[0,0],第一个0代表行
char Precede(char a,char c){
    int i;
    for(i=0;i<7;i++){
        if(a==OP[i]){break;
        }
    }
    int j;
    for(j=0;j<7;j++){
        if(c==OP[j]){
          break;
        }
    }
    return operator_priority[i][j];
}
//表达式求值
//比较两个字符可以用==,因为如果是字符串,比较的是地址
char operate(char tian,char b,char di){
	//之前这里面我用了char c;但发现好像有问题,因为到166行时c='-',但我也不确定 
    int d;
    int tlee;
    d=tian-'0';
    tlee=di-'0';
    int h;
    char r; 
    //计算的时候要注意顺序
	//注意类型转化 char转int,-'0'
	//int转char,+'0' 
    if(b=='+'){h=tlee+d; r=h+'0';return r;};
    if(b=='-'){h=tlee-d; r=h+'0';return r;};
    if(b=='*'){
	h=tlee*d;
	r=h+'0';
	return r;};
    if(b=='/'){h=tlee/d;r=h+'0';return r;};
    return FALSE;
}
int main(){
	cout<<"请输入运算表达式并以#结尾"<<endl;
    SqStack OPTR;
    //运算符栈,operator运算符
    SqStack OPND;
    //运算数栈
    InitStack(OPTR);
    Push(OPTR,'#');//这里如果写Push(OPTR,#)代码运行就会有问题 
    InitStack(OPND);
    char c=getchar();
    //获取字符
    SElemType e;
    SElemType a;
    SElemType b;
    SElemType f;
    SElemType tian;
    SElemType di;
     while (c!='#'||GetTop(OPTR)!='#')
    //while (c!='#')本来以为我可以改变书上的算法,因为我不理解
	//为什么要那么写,好复杂,这样写就可以了,后来发现#是必须要比较的 
    //进栈条件:栈顶元素不为#或者获取字符不为#
    //结束条件栈顶元素为#,c为#
    //如果c为#,栈顶元素不为#,返回真,进栈去比较 
    {
        if(!in(c)){Push(OPND,c);c=getchar();}
        //不是运算符的话,进运算数栈
        else//是运算符,要比较运算优先级
//        f=Precede(GetTop(OPTR),c);
//        switch(f)这种方法容易出问题 
			switch(Precede(GetTop(OPTR),c)){
            case '<'://栈顶优先权低
            Push(OPTR,c);c=getchar();
            break;
            case '='://出栈,脱括号
            pop(OPTR,c);c=getchar();
            break;
            case '>'://栈顶优先权高,出栈,并将运算结果入栈
            pop(OPTR,b);//出一个运算符
            pop(OPND,tian);pop(OPND,di);//出两个运算数
            Push(OPND,operate(tian,b,di));//把运算数结果压进去
            break;
        }
    } 
    cout<<"结果为"; 
    cout<<GetTop(OPND);
}
//可谓是写代码6个小时,检查代码一个星期 ,这一个星期我天天检查错误,每次都找半天,
//但每次又都能找到错误,每次都以为马上就成功了,谁知道错误无穷无尽,
//检查出的问题有比较的时候==又写成=了,还有取用栈顶元素与弹出栈顶元素的理解错了,因此取用的代码写错了
//因为经过分析自己时取用函数和入栈函数肯定有错,去用函数想了半天,改了半天,
//回过头居然发现前面自己居然能将赋值语句写成==,头一次犯这种错误
//char类型用单引号, 还有一个错误是运算符栈与运算数栈搞错了 
//还有一个问题是强制转化的问题,列如int A=(int)B;而B是char类型的 我语言之间都弄混了,

//debug调试教训,把代码都分开,一行一行的运行,查看数据结果比如第164行和第165到171,我调试的时候以164行那种来调试,找到错误的位置,
//但不知道原因,花费很长时间想不通怎么改,后来变为165到171这种,一下就知道问题所在了


//只能算个位数字以内的原因
//之前所有的问题都可以解决,唯独最后一个,是元素类型的设置有问题,因为是char类型的,
//列如int 19,不能转化为char '19',要string类型才行,而我刚开始做的时候就觉得太复杂,
//想先写个位数的加减乘除,而且char类型的相关操作不容易出错,但我却忽视了,在这个过程中会出现十位数的数字,因此要进行大改才行.

参考教材:清华大学出版社,数据结构(c语言版),严蔚敏,吴伟民编著

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值