C/C++ expression evaluation (including multi-digit numbers)

Personal homepage:There are still unknowns waiting to be explored_C language difficulties, data structures, algorithms-CSDN Blog

Special column:Algorithm_There are still unknown blogs waiting to be explored-CSDN Blog

Table of contents

I. Introduction

2. Analysis

analyze

Finally, go directly to the code!


I. Introduction

Expression evaluation is a relatively basic code regarding the use of the stack. While writing, I fully exercised my brain's thinking and code debugging abilities.

If you are given a calculation expression on paper, you can definitely calculate it, but when you want to use code to implement it, you will feel that you have no idea. Next, let me "operate" it for you!

2. Analysis

analyze

First, start with a relatively simple expression and see how this expression is calculated.

 Initially, we need two stacks, one to store the operands and the other to store the operator stack.

The expression is stored in a string type (in C language, an array of char type will also work). Then iterate through each element in turn.

  1. First determine whether the element is a number. If so, go directly to the operand stack.
  2. If this element is a left parenthesis, '( ' will enter the symbol stack directly (the priority of parentheses is higher than that of ordinary operators)
  3. If this element is a right parenthesis ')', perform calculations in sequence (that is, pop two numbers from the operand stack and pop a symbol from the symbol stack) until the top of the symbol stack is a left parenthesis, pop the left parenthesis off the stack, and then end the loop .
  4. If this element is an ordinary symbol, you need to determine the priority of the symbol. If the symbol to be pushed onto the stack has a high priority, just push it onto the stack; otherwise, calculate it first and then push it onto the stack.
  5. The last step is to calculate the number remaining in the stack until the symbol stack is empty and there is only one number left in the operand stack. Then just output this number.

Finally, go directly to the code!

#include <iostream>
using namespace std;
#include <stack>
#include <unordered_map>
#include <string>

stack<int>num;
stack<char>op;
string str;

// 存储运算符的优先级,等价于将一个;‘+’ == 1
unordered_map<char, int>pr = { {'+', 1}, {'-', 1}, {'*', 2}, {'/', 2} };

// 计算函数
void eval()
{
    // 从操作数栈弹出两个数,弹出的第一个数是双目操作符右边的数,要注意
    int a = num.top(); num.pop();
    int b = num.top(); num.pop();
    // 从符号栈弹出一个符号
    char opp = op.top(); op.pop();
    // 计算
    int c = 0;
    if (opp == '+') c = b + a;
    else if (opp == '-') c = b - a;
    else if (opp == '*') c = b * a;
    else if (opp == '/') c = b / a;
    // 将得数进行压栈操作
    num.push(c);
}

int main()
{
    // C++ 输入输出的加速语句
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    // 读入表达式
    cin >> str;
    
    for (int i = 0; i < str.size(); i++)
    {
        // auto 是一个关键字,系统可以根据后面赋值的数据类型自动进行匹配类型
        auto c = str[i];
        // 判断这个字符是不是数字
        if (isdigit(c))
        {
            auto j = i;
            int x = 0;
            // 如果这个数字的后面还是数字的话,证明数字不止一位,要进行加权操作
            while (j < str.size() && isdigit(str[j]))
            {
                x = x * 10 + str[j] - '0';
                j++;
            }
            // 将i移到j - 1的位置上,因为j在最后一个循环中+1操作了
            // j的位置现在是在相当于第一个不是数字的位置上,然后这个判断语句结束后,
            // i会继续+1,所以i要移到j前一个位置上,来让下一个循环到指定的位置上
            i = j - 1;
            num.push(x);
        }
        else if (c == '(') op.push(c);// 遇到左括号直接压栈
        else if (c == ')')// 遇到右括号,计算到符号栈栈顶是左括号,然后左括号出栈
        {
            while (op.size() && op.top() != '(') eval();
            op.pop();
        }
        else// 一般情况,注意一定是while循环,不懂的可以去搜一下表达式树,方便理解
        {
            while (op.size() && pr[op.top()] >= pr[c]) eval();
            op.push(c);
        }
    }
    // 处理最后栈里的元素
    while (op.size()) eval();
    // 输出栈顶元素
    cout << num.top() << endl;

    return 0;
}

Guess you like

Origin blog.csdn.net/qq_73435980/article/details/134982829