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

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

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

这是我的代码:

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)

但是我的代码return这个序列:

sin(pi**avg(yyx)yyxyyx

你能帮我解决这个问题吗?

非常感谢。

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

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

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

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

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

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

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

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;
}

感谢大家:)