如何从队列中的运算符和操作数创建数学表达式

How to create a mathematical expression from operators and operands in a queue

本文关键字:创建 操作数 表达式 运算符 队列      更新时间:2023-10-16

我正试图用队列中包含的运算符和操作数构建一个数学表达式(包括括号)。

这是我的代码:

string createExp (queue<char> q) {
    string s;
    string s1, s2;
    char c;
    while (!q.empty()) {
        c = q.front();
        if (c == 'x') {
            s += "x";
            q.pop();
        }
        else if (c == 'y') {
            s += "y";
            q.pop();
        }
        else if (c == 'a') {
            s += "avg(";
            q.pop();
            s1 = createExp(q);
            q.pop();
            s2 = createExp(q);
            q.pop();
            s += s1;
            s += ',';
            s += s2;
            s += ')';
        }
        else if (c == 's') {
            s += "sin(pi*";
            q.pop();
            op++;
        }
        else if (c == 'c') {
            s += "cos(pi*";
            q.pop();
            op++;
        }
        else {
            s += "*";
            q.pop();
        }
    }
    while (op > cp) {
        s += ")";
        cp++;
    }
    return (s);
}

正如您所看到的,在平均值(avg)的情况下,我试图递归调用该函数以获得下一个值序列。

例如,如果我的队列包含下一个值:

s m a y x y

表达式应该是这样的:

sin(pi*(avg(y,x)*y)

但是我的代码返回了这个序列:

sin(pi**平均值(yyx)yyx

你能帮我做这个吗?

非常感谢。

处理avg(-,-)的这一部分严重损坏:

s1 = createExp(q);
q.pop();
s2 = createExp(q);
q.pop();

你按值传递队列,这会创建它的副本。然后你就找不到递归弹出队列的次数了。但是您神奇地假设您应该只删除一个元素。如果其中一个参数中有函数调用或运算符,该怎么办?

更糟糕的是,递归处理队列的整个其余部分,而不仅仅是一个表达式。

**来自字符串中的m和您在代码中显式写入的sin(pi*

此外,递归到avg(当创建s1时,似乎对整个表达式进行了索引,因此您得到了yyx)。您必须确保它只从堆栈中读取一个完整的表达式,而不是其他内容。这很棘手,因为您需要区分例如avg(x,y)avg(x+y,y*x)之间的区别。

我对您的代码做了一个小修改,它运行得很好:

int cp = 0,  op = 0;
std::string createExp(std::queue< char >& q)
{
    std::string s;
    std::string s1, s2;
    char c;
    while (!q.empty())
    {
        c = q.front();
        if (c == 'x')
        {
            s += "x";
            q.pop();
        }
        else if (c == 'y')
        {
            s += "y";
            q.pop();
        }
        else if (c == 'a')
        {
            s += "avg(";
            q.pop();
            s1 = q.front(); // here
            q.pop();
            s2 = q.front(); // and here
            q.pop();
            s += s1;
            s += ',';
            s += s2;
            s += ')*';
        }
        else if (c == 's')
        {
            s += "sin(pi*";
            q.pop();
            op++;
        }
        else if (c == 'c')
        {
            s += "cos(pi*";
            q.pop();
            op++;
        }
        else
        {
//             s += "*";
            q.pop();
        }
    }
    while (op > cp)
    {
        s += ")";
        cp++;
    }
    return (s);
}

但是,只有当您的操作员始终为*时,这才会起作用。如果你还需要其他操作符,那么你需要一个更复杂的东西。

这是我的最后一个递归解决方案:

int cp = 0,  op = 0;
string recursiveExp (queue<char>& q) {
    char e;
    if (!q.empty()) {
        e = q.front();
        if (e == 'x' || e == 'y') {
            q.pop();
            s += e;
        }
        else if (e == 's') {
            q.pop();
            s += "sin(pi*";
            op++;
            recursiveExp(q);
            s += ")";
            cp++;
        }
       else if (e == 'c') {
            q.pop();
            s += "cos(pi*";
            op++;
            recursiveExp(q);
            s += ")";
            cp++;
        }
        else if (e == 'a') {
            q.pop();
            s += "avg(";
            op++;
            recursiveExp(q);
            s += ",";
            recursiveExp(q);
            s += ")";
            cp++;
        }
        else if (e == 'm'){
            q.pop();
            s += "(";
            op++;
            recursiveExp(q);
            s += "*";
            recursiveExp(q);
            s += ")";
            cp++;
        }
    }
    return s;
}

感谢大家:)