📜  将符号字符串解析为表达式

📅  最后修改于: 2022-05-13 01:57:08.375000             🧑  作者: Mango

将符号字符串解析为表达式

给定一个由数字和基本算术运算运算符(+、-、*、/)组成的字符串str形式的表达式,任务是求解该表达式。请注意,此程序中使用的数字是个位数,不允许使用括号。
例子:

方法:创建一个 Stack 类来存储数字和运算符(都作为字符)。堆栈是一种有用的存储机制,因为在解析表达式时,需要经常访问最后存储的项目;堆栈是后进先出 (LIFO) 容器。
除了 Stack 类之外,还创建了一个名为 express(表达式的缩写)的类,表示整个算术表达式。此类的成员函数允许用户使用字符串形式的表达式初始化对象、解析表达式并返回结果算术值。
以下是算术表达式的解析方式。
一个指针从左边开始,并被迭代以查看每个字符。它可以是数字(通常是 0 到 9 之间的一位字符)或运算符(字符+、-、* 和 /)。
如果字符是数字,则将其压入堆栈。遇到的第一个运算符也被压入堆栈。诀窍是处理后续运算符。请注意,当前运算符无法执行,因为它后面的数字尚未被读取。找到一个运算符只是我们可以执行前一个运算符符的信号,它存储在堆栈中。也就是说,如果序列 2+3 在堆栈上,我们等到找到另一个运算符后再执行加法。
因此,只要当前字符是运算符(第一个除外),前一个数字(上例中的 3)和前一个运算符(+) 就会从堆栈中弹出,将它们放在变量 lastval 和 lastop 中。最后,弹出第一个数字 (2) 并对这两个数字进行算术运算(得到 5)。
但是,当遇到优先级高于 + 和 – 的 * 和 / 时,无法执行表达式。在表达式 3+4/2 中,在执行除法之前不能执行 +。因此,2 和 + 被放回堆栈,直到执行除法。
另一方面,如果当前运算符是 + 或 -,则可以执行前一个运算符。即表达式4-5+6遇到+时,执行-即可,6/2-3遇到-时,执行除法即可。表 10.1 显示了四种可能性。

Previous OperatorCurrent OperatorExampleAction
+ or –* or /3+4/Push previous operator and previous number (+, 4)
* or /* or /9/3*Execute previous operator, push result (3)
+ or –+ or –6+3+Execute previous operator, push result (9)
* or /+ or –8/2-Execute previous operator, push result (4)

下面是上述方法的实现:

CPP
// C++ implementation of the approach
#include 
#include 
using namespace std;
 
// Length of expressions in characters
const int LEN = 80;
 
// Size of the stack
const int MAX = 40;
 
class Stack {
private:
    // Stack: array of characters
    char st[MAX];
 
    // Number at top of the stack
    int top;
 
public:
    Stack()
    {
        top = 0;
    }
 
    // Function to put a character in stack
    void push(char var)
    {
        st[++top] = var;
    }
 
    // Function to return a character off stack
    char pop()
    {
        return st[top--];
    }
 
    // Function to get the top of the stack
    int gettop()
    {
        return top;
    }
};
 
// Expression class
class Express {
private:
    // Stack for analysis
    Stack s;
 
    // Pointer to input string
    char* pStr;
 
    // Length of the input string
    int len;
 
public:
    Express(char* ptr)
    {
        pStr = ptr;
        len = strlen(pStr);
    }
 
    // Parse the input string
    void parse();
 
    // Evaluate the stack
    int solve();
};
 
void Express::parse()
{
 
    // Character from the input string
    char ch;
 
    // Last value
    char lastval;
 
    // Last operator
    char lastop;
 
    // For each input character
    for (int j = 0; j < len; j++) {
        ch = pStr[j];
 
        // If it's a digit then save
        // the numerical value
        if (ch >= '0' && ch <= '9')
            s.push(ch - '0');
 
        // If it's an operator
        else if (ch == '+' || ch == '-'
                 || ch == '*' || ch == '/') {
 
            // If it is the first operator
            // then put it in the stack
            if (s.gettop() == 1)
 
                s.push(ch);
 
            // Not the first operator
            else {
                lastval = s.pop();
                lastop = s.pop();
 
                // If it is either '*' or '/' and the
                // last operator was either '+' or '-'
                if ((ch == '*' || ch == '/')
                    && (lastop == '+' || lastop == '-')) {
 
                    // Restore the last two pops
                    s.push(lastop);
                    s.push(lastval);
                }
 
                // In all the other cases
                else {
 
                    // Perform the last operation
                    switch (lastop) {
 
                    // Push the result in the stack
                    case '+':
                        s.push(s.pop() + lastval);
                        break;
                    case '-':
                        s.push(s.pop() - lastval);
                        break;
                    case '*':
                        s.push(s.pop() * lastval);
                        break;
                    case '/':
                        s.push(s.pop() / lastval);
                        break;
                    default:
                        cout << "\nUnknown oper";
                        exit(1);
                    }
                }
                s.push(ch);
            }
        }
        else {
            cout << "\nUnknown input character";
            exit(1);
        }
    }
}
 
int Express::solve()
{
    // Remove the items from stack
    char lastval;
    while (s.gettop() > 1) {
        lastval = s.pop();
        switch (s.pop()) {
 
        // Perform operation, push answer
        case '+':
            s.push(s.pop() + lastval);
            break;
        case '-':
            s.push(s.pop() - lastval);
            break;
        case '*':
            s.push(s.pop() * lastval);
            break;
        case '/':
            s.push(s.pop() / lastval);
            break;
        default:
            cout << "\nUnknown operator";
            exit(1);
        }
    }
    return int(s.pop());
}
 
// Driver code
int main()
{
 
    char string[LEN] = "2+3*4/3-2";
 
    // Make expression
    Express* eptr = new Express(string);
 
    // Parse it
    eptr->parse();
 
    // Solve the expression
    cout << eptr->solve();
 
    return 0;
}


输出:
4

时间复杂度:O(N)。
辅助空间:O(N)。