栈与队列(四)中缀计算器代码

来源:互联网 发布:php属于前端还是后端 编辑:程序博客网 时间:2024/05/22 08:16

中缀计算器(先中缀转后缀,再RPN计算)

关于代码想说的:

1.有人会问为什么要做两个栈         解决:因为在中缀转后缀中第一个栈被销毁的

2.缓冲量的作用            解决:接收空格

3.如何结合中缀转后缀和RPN计算       解决:将中缀转后追的输出放进数组string中,然后在RPN计算中本来要输入的直接在数组里拿就好,注意不要忘记空格


/*************************************************************************    > File Name: 中缀计算器.c    > Author: geeker    > Mail: 932834897@qq.com    > Created Time: 2017年02月08日 星期三 15时32分41秒 ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <math.h>#include <ctype.h>#define stacksize 20//栈的最大容量#define maxbuffer 10//缓冲量char string[50];//定义一个字符数组,将中缀转后缀的输出数据放到数组中,再取数组元素进行逆波兰计算typedef char ElemType;//19-25行是给中缀转后缀用的typedef struct{    ElemType *base;    ElemType *top;    int maxsize;}sqStack;typedef double bElemType;//28-33行是给逆波兰计算用的typedef struct{    bElemType *base;    bElemType *top;    int maxsize;}bsqStack;void InitStack(sqStack *s)//初始化{    s->base=(ElemType *)malloc(stacksize * sizeof(ElemType));    if(!s->base)//分配失败退出程序   {       exit(0);   }    s->top=s->base;    s->maxsize=stacksize;}void Push(sqStack *s,ElemType e)//压栈{    if(s->top-s->base>=s->maxsize)    {        return;    }    *(s->top)=e;//给当前栈顶赋值    s->top++;//栈顶元素加1}void Pop(sqStack *s,ElemType *e)//出栈{    if(s->top==s->base)    {        return;    }    *e=*--(s->top);}int StackLen(sqStack s)//计算容量{    return(s.top-s.base);}void bInitStack(bsqStack *s)//再次初始化(为什么要再次初始化、压栈等等,因为在中转后的change函数中已经把栈给销毁了,所以要重新建立){    s->base=(bElemType *)malloc(stacksize * sizeof(bElemType));    if(!s->base)    {        exit(0);    }    s->top=s->base;    s->maxsize=stacksize;}void bPush(bsqStack *s,bElemType e)//再次压栈{    if(s->top-s->base>=s->maxsize)    {        return;    }    *(s->top)=e;    s->top++;}void bPop(bsqStack *s,bElemType *e)//再次出栈{    if(s->top==s->base)    {        return;    }    *e=*--(s->top);}int bStackLen(bsqStack s)//再次求栈容量{    return(s.top-s.base);}void DestroyStack(sqStack *s)//销毁栈{    free(s->base);    s->base=s->top=NULL;    s->maxsize=0;}void DestroyBStack(bsqStack *s)//再次销毁栈{    free(s->base);    s->base=s->top=NULL;    s->maxsize=0;}int change()//就是中缀转后缀的一个函数,然而区别就在于将输出的数据存入到string数组中,所以每一次printf就会跟string[i++];{    sqStack s;    char c,e;    InitStack(&s);    int i=0;    printf("请输入中缀表达式,以#为结束标志\n");    scanf("%c",&c);    while(c!='#')    {        while(c>='0'&&c<='9')        {            printf("%c",c);            string[i++]=c;//关键。。把输出的数据放到数组中             scanf("%c",&c);            if(c<'0'||c>'9')            {                printf(" ");                string[i++]=' ';            }        }        if(')'==c)        {            Pop(&s,&e);            while('('!=e){                printf("%c ",e);                string[i++]=e;                string[i++]=' ';                Pop(&s,&e);            }        }        else if('+'==c||'-'==c)        {            if(!StackLen(s))            {                Push(&s,c);            }            else            {                do                {                    Pop(&s,&e);                    if('('==e)                    {                        Push(&s,e);                    }                    else                    {                        printf("%c",e);                            string[i++]=e;                    }                }while(StackLen(s)&&'('!=e);                Push(&s,c);            }        }        else if('*'==c||'/'==c||'('==c)        {            Push(&s,c);        }        else if('#'==c)        {            break;        }        else        {            printf("\n出错,程序输入错误\n");            return -1;        }        scanf("%c",&c);    }        while(StackLen(s))        {            Pop(&s,&e);        printf("%c ",e);            string[i++]=e;            string[i++]=' ';        }        printf("\n");        string[i]='\0';        printf("%s\n",string);        string[i]='#';//这里特别重要,很容易忘记,忘记了很难找到错误,切记!        DestroyStack(&s);        return 0;}int main()//这个main函数其实就是一个逆波兰计算器,区别就是将数组中的数据当做本来要输入的字符,即char *p=string;c=*p++;然后c就是那个看做输入的字符,逆波兰在前面的博客已经有算法,不多解释{    bsqStack s;    char c;    double d,e;    char str[maxbuffer];//缓冲    int f=0;    change();    bInitStack(&s);    printf("请按逆波兰表达式输入带计算数据,数据与运算符之间用空格隔开,以#作为结束标志\n");    char *p=string;//关键    c=*p++;    while(c!='#')    {                while(isdigit(c)||c=='.')        {            str[f++]=c;            str[f]='\0';            if(f>=10)            {                printf("error,输入单个数据过大\n");                return -1;            }//缓冲区最大范围        //    scanf("%c",&c)            c=*p++;//这里本来是输入的,但所有数据已存在数组中            if(c==' ')            {                d=atof(str);//功能                bPush(&s,d);                f=0;                break;            }        }        switch(c)        {            case'+':                bPop(&s,&e);                bPop(&s,&d);                bPush(&s,d+e);                break;            case'-':                bPop(&s,&e);                bPop(&s,&d);                bPush(&s,d-e);                break;            case'*':                bPop(&s,&e);                bPop(&s,&d);                bPush(&s,d*e);                break;            case'/':                bPop(&s,&e);                bPop(&s,&d);                if(e!=0)                {                    bPush(&s,d/e);                }                else                {                    printf("\nerror,除数不能为0\n");                    return -1;                }                break;        }    //    scanf("%c",&c);        c=*p++;    }    bPop(&s,&d);    printf("\n最终计算结果为: %lf\n",d);    DestroyBStack(&s);//别忘记销毁栈    return 0;}


5 0
原创粉丝点击