为什么我的数学表达式评估功能无法在Windows上运行?

时间:2014-07-07 19:33:22

标签: c++ windows macos function expression

我在C ++中创建了一个函数来评估数学表达式。例如,您将函数传递给字符串20 + 10 * 3,函数返回一个字符串,该字符串是提供的表达式的结果。在这种情况下,函数将返回50

上述功能适用于OSX和Windows以及上面的表达式。但是当您提供包含括号的表达式时,它只能在OSX上正常工作。

例如,(10 + 2) * 2适用于OSX,但在Windows上会产生此错误:

terminate called after throwing an instance of 'std::invalid_argument'

这是我的功能:

string evalExpression(string expr) {
    int res = 0;
    int getnextnum = 0;
    int iter = 0;
    int i = 0;
    int temp_i;
    int i2;
    int temp_n_size;
    int ns;
    int second_eval_size;
    int bcount = 0;
    bool bstarted = 0;
    string b = "";
    string opp = "";
    string num = "";
    string num1 = "";
    string num2 = "";
    string ans = "";
    vector<string> numholder;
    vector<string> temp_numholder;

    if (numholder.size() != 0)
    numholder.clear();

    for (char & c : expr) {
        if (c == '0' or c == '1' or c == '2' or c == '3' or c == '4' or c == '5' or
        c == '6' or c == '7' or c == '8' or c == '9') {
            // c is a number
            num += c;

        } else if (c == '+' or c == '-' or c == '*' or c == '/') {
            // c is an operator
            numholder.push_back(num);
            if (c == '+') {
                opp = "+";
            }
            else if (c == '-') {
                opp = "-";
            }
            else if (c == '*') {
                opp = "*";
            }
            else if (c == '/') {
                opp = "/";
            }
            else if (c == '%') {
                opp = "%";
            }
            numholder.push_back(opp);
            num = "";
        }
        else if (c == ']') {
            // end of expression
            numholder.push_back(num);
        }
        else if (c == '(' or c == ')') {
            // c is a round bracket
            if (c == '(') {
                b = "(";
            }
            else {
                b = ")";
                numholder.push_back(num);
            }
            num = "";
            numholder.push_back(b);
        }
    }
    ns = numholder.size();

    STARTB:for (i = 0; i < ns; i++) {
        if (numholder[i] == "(") {
            temp_i = i;
            i2 = i;
        }
        if (numholder[i] == ")") {
            temp_i = i - temp_i;
        }
    }

    for (i = 1; i < temp_i; i++) {
        temp_numholder.push_back(numholder[i2+i]);
    }
    temp_n_size = temp_numholder.size();
    for (i = 0; i < temp_n_size;i++) {
        if (temp_numholder[temp_n_size-i-1] == "/") {
            ans = to_string(stof(temp_numholder[temp_n_size-i-2]) / stof(temp_numholder[temp_n_size-i]));
            temp_numholder[temp_n_size-i-2] = ans;
            temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-1);
            temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-1);
        }
    }

    for (i = 0; i < temp_n_size; i++) {
        if (temp_numholder[temp_n_size-i-1] == "*") {
            ans = to_string(stof(temp_numholder[temp_n_size-i-2]) * stof(temp_numholder[temp_n_size-i]));
            temp_numholder[temp_n_size-i-1] = ans;
            temp_numholder.erase(temp_numholder.begin()+temp_n_size-i);
            temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-2);
        }
    }

    for (i = 0; i < temp_n_size; i++) {
        if (temp_numholder[temp_n_size-i-1] == "+") {
            //cout << ns-i-3 << endl;
            if (temp_n_size-i-3 >= 0) {
                if (temp_numholder[temp_n_size-i-3] == "-") {
                    temp_numholder[temp_n_size-i-2] = to_string(stof(temp_numholder[temp_n_size-i-2]) * -1);
                    temp_numholder[temp_n_size-i-3] = "+";
                }
            }
            ans = to_string(stof(temp_numholder[temp_n_size-i-2]) + stof(temp_numholder[temp_n_size-i]));
            temp_numholder[temp_n_size-i-1] = ans;
            temp_numholder.erase(temp_numholder.begin()+temp_n_size-i);
            temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-2);
        }
    }

    for (i = 0; i < temp_n_size; i++) {
        if (temp_numholder[temp_n_size-i-1] == "-") {
            ans = to_string(stof(temp_numholder[temp_n_size-i-2]) - stof(temp_numholder[temp_n_size-i]));
            temp_numholder[temp_n_size-i-1] = ans;
            temp_numholder.erase(temp_numholder.begin()+temp_n_size-i);
            temp_numholder.erase(temp_numholder.begin()+temp_n_size-i-2);
        }
    }

    for (i = 1; i <= temp_i; i++) {
        numholder.erase(numholder.begin()+i2+1);
    }
    if (ans != "")
        numholder[i2] = to_string(stoi(ans));

    for (i = 0; i < numholder.size(); i++) {
        if (numholder[i] == "") {
            numholder.erase(numholder.begin()+i);
        }
    }

    if (temp_numholder.size() != 0) {
        temp_numholder.clear();
    }

    for (i = 0; i < numholder.size();i++) {
        if (numholder[i] == "(" or numholder[i] == ")") {
            goto STARTB;
        }
    }

    for (i = 0; i < ns; i++) {
        if (numholder[ns-i-1] == "/") {
            ans = to_string(stof(numholder[ns-i-2]) / stof(numholder[ns-i]));
            numholder[ns-i-2] = ans;
            numholder.erase(numholder.begin()+ns-i-1);
            numholder.erase(numholder.begin()+ns-i-1);
        }
    }

    for (i = 0; i < ns; i++) {
        if (numholder[ns-i-1] == "*") {
            ans = to_string(stof(numholder[ns-i-2]) * stof(numholder[ns-i]));
            numholder[ns-i-1] = ans;
            numholder.erase(numholder.begin()+ns-i);
            numholder.erase(numholder.begin()+ns-i-2);
        }
    }

    for (i = 0; i < ns; i++) {
        if (numholder[ns-i-1] == "+") {
            //cout << ns-i-3 << endl;
            if (ns-i-3 >= 0) {
                if (numholder[ns-i-3] == "-") {
                    numholder[ns-i-2] = to_string(stof(numholder[ns-i-2]) * -1);
                    numholder[ns-i-3] = "+";
                }
            }
            ans = to_string(stof(numholder[ns-i-2]) + stof(numholder[ns-i]));
            numholder[ns-i-1] = ans;
            numholder.erase(numholder.begin()+ns-i);
            numholder.erase(numholder.begin()+ns-i-2);
        }
    }
    for (i = 0; i < ns; i++) {
        if (numholder[ns-i-1] == "-") {
            ans = to_string(stof(numholder[ns-i-2]) - stof(numholder[ns-i]));
            numholder[ns-i-1] = ans;
            numholder.erase(numholder.begin()+ns-i);
            numholder.erase(numholder.begin()+ns-i-2);
        }
    }

    i = 0;
    for (i = 0; i < ns;i++) {
        ans = numholder[ns-i-1];
    }

    expr = to_string(stoi(ans));

    return expr;
}

我很欣赏我的功能很乱,并且可能一切都不正确,但我真的很感激,如果有人能看看,帮我找出错误。

1 个答案:

答案 0 :(得分:0)

我很惊讶这个程序有效。有些部分代码我不理解,例如:

STARTB:for (i = 0; i < ns; i++) {
    if (numholder[i] == "(") {
        temp_i = i;
        i2 = i;
    }
    if (numholder[i] == ")") {
        temp_i = i - temp_i;
    }
}

变量temp_ii2可能会在循环结束前被覆盖 示例表达式:(6 +(4 * 5))* 2
如果numholder包含多个左括号。

检查中的更多项目:

if / else /如果梯子难以阅读
在您的程序中,您可以使用switchcase语句使代码更易于阅读(在我看来):

  switch (c)
  {
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
        // c is a number
        num += c;
        break;
    case '*':
    case '/':
    case '+':
    case '-':
      // c is an operator
      numholder.push_back(num);
      std::string s(c);  // Simplified all nested if statements.
      numholder.push_back(s);
      break;
    // And so on.

重复代码片段
为什么要复制多个代码片段而不是使用变量:

ans = to_string(stof(temp_numholder[temp_n_size-i-2]) / stof(temp_numholder[temp_n_size-i]));

在开始评估表达式之前,您似乎可以创建两个类型为double的变量:

  double argument1 = 0.0;
  double argument2 = 0.0;
  argument1 = stof(temp_numholder[temp_n_size-i-2]);
  argument2 = stof(temp_numholder[temp_n_size-i]);
  switch (operator)
  {
    case '*':
      ans = to_string(argument1 * argument2);
      break;
    case '/':
      ans = to_string(argument1 * argument2);
      break;
    case '+':
      ans = to_string(argument1 * argument2);
      break;
    case '-':
      ans = to_string(argument1 * argument2);
      break;
  }

使用适当的数据结构
您的程序以我向小学生演示数学的方式评估表达式:通过擦除复杂表达式并插入简化并重新启动解析/评估过程。非常非常慢。通过使用其他数据结构,例如 stacks trees ,计算机可以更快地完成这项工作。

在StackOverflow和网页上搜索“c ++表达式评估”,希望会有一些简单而正确的例子。