Stack application: expression evaluation (write a small calculator by yourself) explanation + code implementation


A stack of applications: expression evaluation carried out to achieve
the expression evaluates to achieve and know infix expression evaluation postfix notation method almost
since Postfix expression operators appear in order of calculation , That is, after knowing the suffix expression, you can find the value of this formula

Operation priority definition

Insert picture description here
You can put θ 1 \theta1θ 1 is regarded as an element of the stack,θ 2 \theta2
Is it troublesome to regard θ 2 as an inbound element of the formula (corresponding to c in the code)? ? ? You can understand

  1. For'(', when it is ready to be put on the stack, its priority can be understood as the highest, so the four arithmetic operations on the top of the stack have lower priority than him
  2. For'(', when it is put on the stack, its priority becomes lower, so the priority of the four arithmetic operations after him is higher than him
  3. For ')', its priority is the same as the priority of'(' after being pushed onto the stack, so it has a lower priority than the four arithmetic operations at the top of the stack when it is ready to be pushed onto the stack
  4. For the four arithmetic operations, these four operators are all left-associative, so for the four arithmetic operations, when the element to be pushed onto the stack is the same as the element on the top of the stack, the priority of the top of the stack is greater
  5. We define'#' as the end of the expression, this symbol has the lowest priority

Code

Define operand and operator stack

In order to realize the simplicity, I always use the structure of the character type Data member, so each operand is only one bit (of course, you can also implement multi-digit operations, just implement the operand stack singular)

#include"stdio.h"
#include"stdlib.h"

#define add 10

//建立栈  有操作数和操作符栈,为了方便统一设置成char类型成员的结构体  以顺序栈实现 为了程序简单,在malloc后统一没有增加失败检验
//注意我为了方便才讲数据栈和操作符栈统一写成有char域的结构体, 你可以讲数据栈写成有int域的结构体
typedef struct SNode {
    
    
    char* Data; /* 存储元素的数组 */
    int Top;      /* 栈顶指针 */
    int MaxSize;       /* 堆栈最大容量 */
}* PNode;//运算符  操作数

Related operations on the stack


void InitStack(PNode stack) {
    
    
    stack->MaxSize = 5; //开始的栈大小为5  之后不够再加
    stack->Top = 0;
    stack->Data = (char*)malloc(sizeof(char) * stack->MaxSize);
}

void Push(PNode stack, char e) {
    
    
    if (stack->Top == stack->MaxSize + 1) {
    
    
        stack->Data = (char*)realloc(stack, sizeof(char)*(stack->MaxSize + add));
        stack->MaxSize = stack->MaxSize + add;
    }
    stack->Data[stack->Top++] = e;
}

void Pop(PNode stack, char* e) {
    
    
    if (stack->Top != 0)
        *e = stack->Data[--stack->Top];
}

char GetTop(PNode stack) {
    
    
    return stack->Data[stack->Top - 1];
}

Implementation of expression evaluation related functions

Define operator precedence

Note that I only implemented + − ∗ / +-* /+/ Priority of related operators, if you need to implement others, you have to consider this operator and'(',')','# and '+ − ∗ / +-* /+/ etc., also consider this operator and associativity (such as exponential operation bit right associativity)


/*栈的应用:表达式求值:*/
//假设仅有 + - * / 四个运算 和( ) 对应ASCII 43 45 42 47 40 41  # 35 代表起始符和终止符
//若想增加指数运算可以定义优先级 但要注意:指数为右结合

char Precede(PNode optr, char c) {
    
     //比较栈顶op与c的优先级
    char op = GetTop(optr);
    if (op == c && c == '(') return '<'; // 处理((情况
    else if (op == '(' && c == ')')  return '=';
    else if (op == '(') return '<';
    else if (c == '(')   return '<';
    else if (c == '#')   return '>';
    else if (c == ')')  return '>';
    else if (op == '#') return '<';
    else if (c == op && (c == 43 || c == 45 || c == 42 || c == 47))
        return '>';   //+ - * / 为左结合性
    else if ((op == 42 || op == 47) && (c == 43 || c == 45))
        return '>';
    else if (((op == 43 || op == 45) && (c == 43 || c == 45)) || ((op == 42 || op == 47) && (c == 42 || c == 47)))
        return '>'; //同一级运算符 从左到右结合
    else if (((op == 43 || op == 45) && (c == 42 || c == 47)))
        return '<'; //c的优先级大
}
Implement calculation function
char Operate(char num1, char x, char num2) {
    
     //进行运算 在此时已近转化成了int值对应的char
    int n1 = num1 - 48;
    int n2 = num2 - 48;
    printf("operate %d %c %d\n", n1, x, n2);
    switch (x){
    
    
        case'+': return n1 + n2 + 48;
        case'-': return n1 - n2 + 48;
        case'*': return n1 * n2 + 48;
        case'/': return n1 / n2 + 48;
    }
}
Implement input value function

Note that "#" represents the end of the input expression

int EvaluateExpression() {
    
    
    PNode optr = (PNode)malloc(sizeof(struct SNode));
    PNode opnd = (PNode)malloc(sizeof(struct SNode));;
    InitStack(optr);    InitStack(opnd);    
    Push(optr, '#');    printf("%c", GetTop(optr));   char c = getchar();
    
    char x; //保存弹出来的操作符
    char num1, num2; //保存弹出来的数字
    while (c != '#' || GetTop(optr) != '#') {
    
    
        //printf("%c\n", c);
        if (c > 47 && c < 58) {
    
     // 输入的位操作数
            Push(opnd, c);  c = getchar();
        }
        else {
    
    
            switch (Precede(optr, c)) {
    
    
                case'<': Push(optr, c); c = getchar(); break;
                case'=': Pop(optr, &x); c = getchar(); break;
                case'>': Pop(optr, &x); Pop(opnd, &num2); Pop(opnd, &num1);
                    Push(opnd, Operate(num1, x, num2)); break;
            }
        }
    }
    int num = GetTop(opnd) - 48; //转化成int
    return num; 
}
int main() {
    
    
    int a = EvaluateExpression();
    printf("结果是: %d", a);
}


result

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_43779658/article/details/105167726