Обратите внимание, что предоставленный алгоритм работает, только если он получает постфиксное выражение, а не инфиксное выражение.
Первая проблема:
Теперь взгляните на следующую строку:
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;
}