Я работаю над реализацией алгоритма Shunting Yard для оценки простых выражений. Код, кажется, работает, но падает, если есть пробелы. Это удивительно, потому что есть специальная проверка c для пробела, которая, кажется, просто не ловит его.
using namespace std;
mpz_class exprToTokens(string expression);
int precedence(const char op);
mpz_class applyOperation(const mpz_class a, const mpz_class b, const char op);
int main() {
try {
while(true)
{
cout << "enter an expression: ";
string expr;
cin >> expr;
if( expr == "e")
{
break;
}
cout << "output: " << exprToTokens(expr) << endl;
}
} catch( const std::exception & ex ) {
cerr << "message: " << ex.what() << endl;
}
return 0;
}
mpz_class exprToTokens(string expression)
{
stack<char> operators;
stack<mpz_class> output;
unsigned int i = 0;
while(i < expression.length())
{
if(isspace(static_cast<unsigned char>(expression.at(i))))//skip white space
{
cout << "is space" << endl;//never happens
i++;
continue;
}
else if(isdigit(expression[i]))
{
unsigned int j = i;
while(i < expression.length() && isdigit(expression[j]))
{
j++;
}
const string number = expression.substr(i, j-i);
const mpz_class term(number);
output.push(term);
i = j;
continue;
}
else//token is an operator
{
while(!operators.empty() && precedence(operators.top() >= precedence(expression[i])))
{
const mpz_class val1 = output.top();
output.pop();
const mpz_class val2 = output.top();
output.pop();
const char op = operators.top();
operators.pop();
output.push(applyOperation(val1, val2, op));
}
operators.push(expression[i]);
}
i++;
}
/*process remaining operations and values on stacks*/
while(!operators.empty())
{
const mpz_class val2 = output.top();//something bad happens here when spaces are around operator
output.pop();
const mpz_class val1 = output.top();
output.pop();
const char op = operators.top();
operators.pop();
output.push(applyOperation(val1, val2, op));
}
return output.top();
}
int precedence(const char op)
{
if(op == '+' || op == '-')
return 1;
if(op == '*' || op == '/')
return 2;
return 3;
}
mpz_class applyOperation(const mpz_class a, const mpz_class b, const char op)
{
switch(op)
{
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
default: throw invalid_argument("syntax not recognized");
}
}
Например, 3+3
дает 6
результат, но 3 + 3
вызывает ошибку сегментации. Любые идеи?
В стороне вопрос: алгоритм Shunting Yard преобразует инфикс в постфиксную нотацию. Строго говоря, принято модифицировать алгоритм для фактической оценки выражения, но больше ли это алгоритм Шунтирующего двора? Для нормального алгоритма не нужен ли другой алгоритм для вычисления выражения в постфиксной записи?