RPN калькулятор / калькулятор - PullRequest
0 голосов
/ 07 июня 2019

Итак, мне нужно сделать постфиксный калькулятор или RPN-калькулятор, вопрос звучит так:

Задача - написать упрощенный калькулятор, который работает только с целыми числами.Ваш код должен предоставить функцию под названием define, которая принимает один аргумент: 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 голосов
/ 07 июня 2019

Обратите внимание, что предоставленный алгоритм работает, только если он получает постфиксное выражение, а не инфиксное выражение.

Первая проблема:

Теперь взгляните на следующую строку:

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;


Общие улучшения

функция: isdigit

Первое, что я бы посоветовал вам сделать, это удалить заявление 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 типа. Вам на самом деле не нужно искать здесь ответ, а нужно отлаживать свой код и видеть, что не так. Пожалуйста, используйте инструменты, которые вы получили здесь, и удачи!

EDIT:

Для более сложного решения в стиле 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...