RPN计算器/后修正计算器

时间:2019-06-06 21:33:43

标签: c++ types stack

所以,我必须要制作一个后缀计算器或RPN计算器,问题就像

任务是编写仅对整数有效的简化计算器。您的代码必须提供一个称为评估的函数,该函数带有一个参数:std :: string并返回整数。计算器必须以以下方式工作:

  1. 它逐个字符地读取一个字符串,
  2. 如果它读取一个数字,则会将其放在自己的内部堆栈中,
  3. 如果它读取空格,则必须忽略它,
  4. 如果它读取一个字符+,-,*或/,则对堆栈的两个最高元素执行操作,将其删除并将结果放在堆栈中,
  5. 当到达std :: string参数的末尾时,它返回栈顶。

代码:

using namespace std;

int evaluate(string);
bool isdigit(char c);
bool isOp(char c);

bool isdigit(char c)
{
    if (c >= '0' && c <= '9')
    {
        return true;
    }
    return false;
}

int main()
{

    string str;
    cout << "\n Enter the input : ";
    cin >> str;

    evaluate(str);
}

int evaluate(string str)
{
    stack<int> mystack;
    stack<int> vals;

    for (int i = 0; i < str.size(); i++)
    {
        char c = str[i];
        if (isdigit(c))
        {
            vals.push(c);
        }
        else if (c == ' ')
        {
            c = ' ';
            cout << str;
        }
        else
        {
            int value1, value2, result;

            value2 = vals.top();
            vals.pop();

            value1 = vals.top();
            vals.pop();

            switch (str[i])
            {
                case '+':
                    result = value1 + value2;
                    mystack.push(result);
                    break;

                case '-':
                    result = value1 - value2;
                    mystack.push(result);
                    break;

                case '*':
                    result = value1 * value2;
                    mystack.push(result);
                    break;

                case '/':
                    result = value1 / value2;
                    mystack.push(result);

                    break;
            }

            cout << "result is " << mystack.top();

        }
    }
}

我期望实际的答案,但是我想程序并没有忽略         空间,当我输入不带空格的字符串时,仍然有一个         错误的输出

1 个答案:

答案 0 :(得分:-1)

请注意,所提供的算法仅在获得后缀表达式而不是中缀表达式时才有效。

第一个问题:

现在,请看以下一行:

vals.push(c);

c是一个字符,而vals是一个整数stack。当c在您的代码中显示1时,c ++编译器实际上看到'0' + 1。例如:

对于输入23+,您将获得结果:101。为什么? '2' != 2'3' != 3。实际上计算是: '0' + 2 + '0' + 3,意思是48 + 2 + 48 + 3,因为'0' == 48在ASCII代码中。

要解决这个小问题,您要做的就是将插入vals堆栈中的值减少'0':

vals.push(c - '0');

现在输入23+的结果为:5。

第二个问题:

您正在使用两个堆栈,而不是实际需要的堆栈。当您将结果值推入第二个堆栈(mystack)时,实际上无论何时获得表达式的另一部分,您都无法访问它(或者说使用它的值变得更加复杂),例如:

23+5*

您可以调试这种情况(使用正在使用的IDE的监视表/调试代码功能),并看到您正在尝试访问第一个结果的5个,而在第一个堆栈中没有任何剩余内容,因为结果存储在第二个中。解决方案:使用单个堆栈。

case '+':
    result = value1 + value2;
    //mystack.push(result);
    vals.push(result);
    break;


常规改进

功能:等轴

我建议您做的第一件事是删除if语句-您不需要它。以下代码可以解决问题:

bool isdigit(char c) {
    return c >= '0' && c <= '9';
}

如果此句子将给您true,则该函数将返回true,否则将返回false

第二件事,就像注释中所说的那样,该函数已经存在于标准c ++库中。只需使用:

#include <cctype>

然后将您的实现删除到该函数。具有相同名称的相同功能已经存在:http://www.cplusplus.com/reference/locale/isdigit/

重要!

之所以给出此答案,是因为我一生都有额外的时间,而且我正处于无聊的境地,但更重要的是,因为我认为它可以帮助您了解如何调试代码以及​​解决未来(甚至更复杂)的情况。这类问题是Debug questions类型。您实际上不必在这里寻找答案,而可以调试您的代码并查看问题所在。请明智地使用此处提供的工具,祝您好运!

编辑:

对于更多的c ++样式的解决方案,在更高的难度下,您可以看到以下解决方案(请像从c ++一样欢迎您考虑):

int evaluate(string str) {
    // [] () -> {} ====> READ ABOUT: Lambda expressions

    stack<int> vals;

    /*
     * pop
     * ---
     * Returns the top value of a stack, and the pop it from the stack.
     */
    auto pop = [] (stack<int> &s) -> int {
        int res = s.top();
        s.pop();
        return res;
    };

    /*
     * op
     * --
     * Returns a function that execute the selected operator on two integers params.
     */
    auto op = [] (char op) -> std::function<int(int, int)> {
        switch (op) {
            case '+':
            default : return [] (int a, int b) -> int { return a + b; };
            case '-': return [] (int a, int b) -> int { return a - b; };
            case '*': return [] (int a, int b) -> int { return a * b; };
            case '/': return [] (int a, int b) -> int { return a / b; };
        }
    };

    /*
     * for_each is a loop implementation in c++ as part of the standard library (std).
     * It's get the first iterator place (str.begin()), end iterator place (str.end()), and function to execute on
     * each value in the collection (between start and end iterators).
     */
    std::for_each(str.begin(), str.end(), [&vals, pop, op] (char c) {
        if (isdigit(c)) vals.push(c - '0');
        else if (c != ' ') vals.push(op(c)(pop(vals), pop(vals)));
        // op(c) -> returns a function according to the operator
        // op(c)(n1, n2) -> use the returned operator on n1 and n2
        // pop(vals) -> function that returns the top value of the stack, and then pop it from the stack.
        // op(c)(pop(vals), pop(vals)) -> apply the selected op on the first two values in the stack
    });
    cout << "The result is: " << vals.top() << endl;
}