I recently started to learn C++ and came across this problem in a book "Object Oriented Programming in C++" by Robert Lafore.
The author has a program in the book which creates a Parser. I found a problem with the original program in the book which breaks at one of the input expressions I am providing. Therefore I tried to make changes and made it recursive. It works fine with the inputs I am providing.
I am more concerned about correctness and programming style of the program I have written. I believe I have made many mistakes. Any comments would be very helpful.
#include <iostream> using namespace std; const char SIZE = 40; class Stack { private: char array[SIZE]; char top; public: Stack():top(-1) { } void push(char v) { if (!is_full()) { array[++top] = v; } } char pop() { if (!is_empty()) { return array[top--]; } throw "Stack is empty. Pop failed"; } bool is_full() { return top >= SIZE ? true : false; } bool is_empty() { return top == -1; } char get_top() { return top; } }; bool is_operator(char c) { return (c == '*' || c == '/' || c == '+' || c == '-'); } bool is_dm_operator(char c) { return (c == '*' || c == '/'); } bool is_value(char c) { return (c >= '0' && c <= '9'); } void resolve_op_recursively(Stack& e_stack, char in) { if (e_stack.get_top() == 0) //stack has only 1 operand { e_stack.push(in); } else { char last_val = e_stack.pop(); char last_op = e_stack.pop(); if (is_dm_operator(in) && !is_dm_operator(last_op)) // 2 + 3 * 5 case only { e_stack.push(last_op); e_stack.push(last_val); e_stack.push(in); } else { char first_val = e_stack.pop(); switch (last_op) { case '/': e_stack.push(first_val / last_val); break; case '*': e_stack.push(first_val * last_val); break; case '+': e_stack.push(first_val + last_val); break; case '-': e_stack.push(first_val - last_val); break; default: break; } resolve_op_recursively(e_stack, in); } } } void parse_expression_using_stack(Stack& e_stack, const char * input) { while (*input) { char in = *input; if (in != ' ') { if (is_value(in)) { e_stack.push(in - '0'); } else if (is_operator(in)) { resolve_op_recursively(e_stack, in); } else { cout << "unknow expression" << endl; } } input++; } } void solve_expression_using_stack(Stack& e_stack) { while(e_stack.get_top()) { char second_operand = e_stack.pop(); char operator_ = e_stack.pop(); switch (operator_) { case '+': e_stack.push(e_stack.pop() + second_operand); break; case '-': e_stack.push(e_stack.pop() - second_operand); break; case '*': e_stack.push(e_stack.pop() * second_operand); break; case '/': e_stack.push(e_stack.pop() / second_operand); break; default: cout << "unkown operand " << operator_ << endl; } } } void solve_expression_and_match_result(const char * input, char expected_result) { Stack e_stack; char result; cout << "Expression: " << input; parse_expression_using_stack(e_stack, input); solve_expression_using_stack(e_stack); result = e_stack.pop(); cout << " Got solution: " << static_cast<int>(result) << " Expected Solution: " << static_cast<int>(expected_result) << " Test: "; if (result == expected_result) { cout << "\nPASSED" << endl; } else { cout << "\nFAILED" << endl; } } int main(int argc, const char * argv[]) { const char * expressions[20] = { static_cast<const char *>("5 / 5 + 3 - 6 * 2"), // why static_cast here? what is const_cast static_cast<const char *>("3 * 7 - 1 + 5 / 3"), static_cast<const char *>("3 * 5 - 4"), static_cast<const char *>("3 + 5 - 4"), static_cast<const char *>("2 / 6 * 3 / 2"), static_cast<const char *>("3 + 6 * 9 / 3 - 7"), static_cast<const char *>("9 - 5 / 5 * 2 + 6"), static_cast<const char *>("7 + 3 * 4 / 2 - 5 * 6"), static_cast<const char *>("4 * 5 + 3 - 4 / 2"), static_cast<const char *>("4 / 2 * 5 + 3 - 4"), static_cast<const char *>("5 + 3 * 4 / 2 - 3"), static_cast<const char *>("5 - 3 + 4 / 2"), static_cast<const char *>("5 * 3 / 2 - 2"), static_cast<const char *>("5 * 2 / 4 + 9 - 2") }; char solutions[20] = { 5 / 5 + 3 - 6 * 2, 3 * 7 - 1 + 5 / 3, 3 * 5 - 4, 3 + 5 - 4, 2 / 6 * 3 / 2, 3 + 6 * 9 / 3 - 7, 9 - 5 / 5 * 2 + 6, 7 + 3 * 4 / 2 - 5 * 6, 4 * 5 + 3 - 4 / 2, 4 / 2 * 5 + 3 - 4, 5 + 3 * 4 / 2 - 3, 5 - 3 + 4 / 2, 5 * 3 / 2 - 2, 5 * 2 / 4 + 9 - 2 }; for (int i = 0; i < 20; ++i) { if (expressions[i]) { solve_expression_and_match_result(expressions[i], solutions[i]); } } return 0; }
std::stack
instead of rolling your own?\$\endgroup\$