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

时间:2015-12-16 15:59:17

标签: c++ mathematical-expressions

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

这是我的代码:

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 y y x y

表达式应该是这样的:

  

SIN(PI *(AVG(Y,X)* Y)

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

  

罪(PI ** AVG(YYX)yyxyyx

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

非常感谢。

4 个答案:

答案 0 :(得分:3)

这部分处理s1 = createExp(q); q.pop(); s2 = createExp(q); q.pop(); 被严重破坏:

public void run() {
    while(true) {
        try {
          runOne();
        } catch(Throwable t) {
          // log t
        }
    }
}

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

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

答案 1 :(得分:1)

**来自字符串中的m,您在代码中明确地写了sin(pi*

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

答案 2 :(得分:0)

我对您的代码进行了一些小修改,它完美无缺:

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

但只有当您的运营商始终为*时,此功能才有效。如果你还需要其他操作员,那么你需要一个更复杂的东西。

答案 3 :(得分:0)

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

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

感谢大家:)