栈的应用—计算表达式的值

一个表达式由数字和运算符组成,建立两个栈,一个栈用来存数,另一个栈用来存运算符,再利用栈的基本操作来实现表达式的计算

#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR -1
#define MAX_SIZE 30
typedef int ElemType;
typedef int Status;

栈的结构体

typedef struct
{
    int top;
    int bottom;
    ElemType array[MAX_SIZE];
}SqStack;

字符串的结构体

typedef struct String
{
    char ch[MAX_SIZE];
    int length;
}String;

出始化栈

Status Init_Stack(SqStack *S)
{
    S->top = S->bottom =0;

    return OK;
}

压入栈

Status Push(SqStack *S, int e)
{
    if(S->top == MAX_SIZE - 1)
    {
        return ERROR;
    }
    else
    {
        S->array[S->top] = e;
        S->top++;
    }
    return OK;
}

弹出栈

int Pop(SqStack *S)
{
    int e;
    if(S->top == S->bottom)
    {
        return ERROR;
    }
    else
    {

        e = S->array[S->top - 1];
        S->top--;
        return e;
    }
}

创建一个字符串类型的表达式

Status StrCreate(String *S)
{
    int i = 0;
    int len = 0;

    printf("温馨提示:输入括号必须是英文状态,每个字符之间不要出现空格, 否则就会读取或计算出错呦!\n");
    printf("Please enter a expression:\n");
    gets(S->ch);

    while(S->ch[i] != '\0')
    {
        len++;
        i++;
    }

    S->length = len;

    return OK;
}

判断字符是否为运算符

Status isOperator(char c)
{
    int a;
    switch(c)
    {//是运算符返回1  是数字返回0 是空格返回-1
        case '+':
        case '-':
        case '*':
        case '/':
        case '(':
        case ')':
            a = 1;
            break;
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            a = 0;
            break;
        case ' ':
            a = -1;
            break;
    }
    return a;
}

判断运算符的优先级

Status PRI(char oper1,char oper2)
{
//如果oper1>oper2返回1    如果oper1<oper2返回-1   如果oper1,,oper2是左右括号返回0
    int pri = 0;
    switch(oper1)
    {
        case '+':
        case '-':
            if(oper2 == '+' || oper2 == '-')
                pri = 1;        //oper1>oper2
            else
                pri = -1;
            break;
        case '*':
        case '/':
            if(oper2 == '*' || oper2 == '/' || oper2 == '+' || oper2 == '-' || oper2 == ')')
              pri = 1;
            else
              pri = -1;
            break;
        case '(':
            if(oper2==')')       //右括号右侧不能马上出现左括号
            {
                printf("语法错误\n");
                exit(0);
            }
            else
                pri=-1;       //oper1<oper2
            break;
        case ')':
            if(oper1=='(')
               pri=0;
            else
                pri=1;
            break;
                break;
    }
    return pri;
}

读取字符串中的数字

//若是多位数(例如:125,是字符1、字符2和字符5),要把字符串转化成数字
int Dushu(int n[], int j)//n[]是存放数字字符的数组  是数字字符的个数
{
    int c;
    int k;//c、k是循环变量
    int l;
    int e = 0;//转化之后的数字

    l = j;
    for(c = 0; c <= j; c++)
    {
        for(k = l - c; k > 0; k--)
        {
            n[c] = n[c]*10;
        }
    }
    for(k = 0; k <= j; k++)
    {
        e = e + n[k];
    }
    return e;
}

两个数的计算结果

int Calc(int a,int oper,int b)
{
    int e;//计算的结果
    switch(oper)     //根据运算符计算
    {
        case '+':
            e = a+b;
            break;
        case '-':
            e = a-b;
            break;
        case '*':
            e = a*b;
            break;
        case '/':
            if(b!=0)
              e = a/b;
            else
            {
                printf("除数不能为0!\n");
                exit(0);
            }
            break;
    }
    return e;
}

解析字符串表达式

Status ParseExpression(SqStack *S1, SqStack *S2, String *S)
{                  //S1是存放数字的栈  S2是存放运算符的栈
    int i = 0;//循环变量  遍历字符串
    int j = 0;//多位数的位数
    int a = 0;
    int b = 0;//a是运算符标记位,b数字标记位,用来判断表示的规范(例如:若表达式只有数字或只有运算符)
    int n[MAX_SIZE];//存放多位数的  字符数字
    int flag = 0;
    Push(S2, '#');

    while(S->ch[i] != '\0')
    {
        if(isOperator(S->ch[i]) == 1)
        {
            if(flag == 0)
            {
                if(S->ch[i] == '(')
                {
                    Push(S2, S->ch[i]);
                    i++;
                }
                else
                {
                    Push(S2, S->ch[i]);
                    flag++;
                    i++;
                }
            }
            else
            {
                switch(PRI(S2->array[S2->top - 1], S->ch[i]))
                {
                    case 1:
                        if(S->ch[i] == '(')
                        {
                            Push(S2, S->ch[i]);
                            flag = 0;
                            i++;
                        }
                        else if(S->ch[i] == ')')
                        {
                            Push(S1, Calc(Pop(S1), Pop(S2), Pop(S1)));
                            while(S2->array[S2->top-1] != '(')
                            {
                                Push(S1, Calc(Pop(S1), Pop(S2), Pop(S1)));
                            }
                            Pop(S2);
                            if(S2->array[S2->top - 1] == '#')
                            {
                                flag = 0;
                            }
                            printf("\n");
                            i++;
;                        }
                        else
                        {
                            Push(S1, Calc(Pop(S1), Pop(S2), Pop(S1)));
                            Push(S2, S->ch[i]);
                            i++;
                        }
                        break;
                    case -1:
                        if(S->ch[i] == ')')
                        {
                            Push(S1, Calc(Pop(S1), Pop(S2), Pop(S1)));
                            while(S2->array[S2->top-1] != '(')
                            {
                                Push(S1, Calc(Pop(S1), Pop(S2), Pop(S1)));
                            }
                            Pop(S2);
                            if(S2->array[S2->top - 1] == '#')
                            {
                                flag = 0;
                            }
                            i++;
                        }
                        else
                        {
                            Push(S2, S->ch[i]);
                            i++;
                        }
                        break;
                }
            }
            a++;
        }
        else if(isOperator(S->ch[i]) == 0)
        {
             n[j] = S->ch[i] - '0';//把ASCLL码转化成数字

            if(isOperator(S->ch[i+1]) == 1 || S->ch[i+1] == '\0')
            {
                Push(S1, Dushu(n, j));
                j = 0;
                i++;
            }
            else
            {
                j++;
                i++;
                b++;
            }
            b++;
        }
        else if(isOperator(S->ch[i]) != 1 || isOperator(S->ch[i]) != 0)
        {
            printf("Expression error!\n");
            break;
        }
    }

    if(i >= S->length - 1)
    {   //表达式遍历完了之后,栈中可能还存有元素(例如:表达式中有括号),则需把栈中元素弹出并计算,直到栈空为止
        while((S1->top != S1->bottom + 1) && (S2->top != S2->bottom + 1))
        {
            Push(S1, Calc(Pop(S1), Pop(S2), Pop(S1)));
        }

        if(a != 0 && b != 0)
        {
            printf(" = %d\n", S1->array[S1->bottom]);
        }
        else
        {
            printf("Expression error.\n\n");
        }
    }

    return OK;
}

主方法

int main()
{
    String S;
    SqStack S1;
    SqStack S2;

    Init_Stack(&S1);
    Init_Stack(&S2);

    StrCreate(&S);

    ParseExpression(&S1, &S2, &S);

    return 0;
}

运行结果:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值