Arithmetic Evaluation using Stacks and Postfix Notation - c++

I'm a C++ newcomer.
For the next project in class, the professor asked us to code a program that calculates a mathematical expression, that we input an infix notation, convert it to postfix and calculates it. I think I have pretty much finished the code, but there are some lines that I'm probably doing wrong and I don't really know what is it. Can you please take a look at it and tell me why am I wrong.
#include <iostream>;
#include <stack>;
#include <string>;
using namespace std;
bool operatorCheck(char c)
{
if (c == '+' || c == '-' || c == '*' || c == '/')
{
return true;
}
return false;
}
int priority(char c)
{
if (c == '*' || c == '/')
{
return 2;
}
else if (c == '+' || c == '-')
{
return 1;
}
return 0;
}
string InfixToPostfix(string expression)
{
stack<char> operators;
string postfix;
for (int i = 0;i< expression.length();i++)
{
if (expression[i] == ' ')
{
continue;
}
else if (expression[i] >= '0' && expression[i] <= '9')
{
string temp;
temp += expression[i];
int temp2 = i + 1;
while (true)
{
if (expression[temp2] >= '0' && expression[temp2] <= '9')
{
temp += expression[temp2];
temp2 += 1;
}
else
{
break;
}
}
postfix= postfix + temp + " ";
}
else if (operators.empty())
{
operators.push(expression[i]);
}
else if (operatorCheck(expression[i]))
{
if (priority(operators.top()) < priority(expression[i]))
{
operators.push(expression[i]);
}
else
{
while (!operators.empty() && priority(operators.top()) < priority(expression[i]))
{
postfix += operators.top();
operators.pop();
}
operators.push(expression[i]);
}
}
else if (expression[i] == '(')
{
operators.push(expression[i]);
}
else if (expression[i] == ')')
{
while (!operators.empty() && operators.top() != '(')
{
postfix += operators.top();
operators.pop();
}
operators.pop();
}
}
while (!operators.empty())
{
postfix += operators.top();
operators.pop();
}
return postfix;
}
//Main program
int main()
{
string expression;
stack<int> calc;
cout << "Welcome to my program!" << endl;
cout << "This program will help you to calculate arithmetic expression." << endl;
cout << "Please enter an arithmetic expression (Remember to enter space between numbers and operators):" << endl;
getline(cin, expression);
string postfix = InfixToPostfix(expression);
cout << postfix << endl;
for (int i = 0;i < postfix.length();i++)
{
if (postfix[i] == ' ')
{
continue;
}
else if (postfix[i] >= '0' && postfix[i] <= '9')
{
string temp;
int temp2 = i + 1;
temp += postfix[i];
while (true)
{
if (postfix[temp2] >= '0' && postfix[temp2] <= '9')
{
temp += expression[temp2];
temp2 += 1;
}
else
{
break;
}
}
int n = atoi(temp.c_str());
calc.push(n);
}
else if (postfix[i] == '+')
{
int temp1 = calc.top();
calc.pop();
int temp2 = calc.top();
calc.pop();
int result = temp2 + temp1;
calc.push(result);
}
else if (postfix[i] == '-')
{
int temp1 = calc.top();
calc.pop();
int temp2 = calc.top();
calc.pop();
int result = temp2 - temp1;
calc.push(result);
}
else if (postfix[i] == '*')
{
int temp1 = calc.top();
calc.pop();
int temp2 = calc.top();
calc.pop();
int result = temp2 * temp1;
calc.push(result);
}
else if (postfix[i] == '/')
{
int temp1 = calc.top();
calc.pop();
int temp2 = calc.top();
calc.pop();
int result = temp2 / temp1;
calc.push(result);
}
}
cout << calc.top() << endl;
}
For example, with this expression ( ( 7 + 6 ) * ( 16 - 2 ) ) / 2,
It returns 7 6 +16 6 2 -*2 / ( there is an extra 6) for the postfix. Why is this happened?

Related

Made an infix to postfix converter and calculator using an array based stack in c++. The calculations don't work. Only returns the top of the stack

My problem is that my evaluatePostfix() function is not calculating operands. It only returns the top of the stack in the converted postfix expression.
So for example, my output is:
Enter a infix expression: 1+4
your postfix expression is:
14+
your result is:
4
Why am I not getting 5?
Here's my main():
int main()
{
string infixExp = "";
cout << "Enter a infix expression: ";
cin >> infixExp;
cout << "your postfix expression is: " << endl;
infixToPostfix(infixExp);
cout << endl;
cout << "your result is: " << endl;
cout << evaluatePostfix(infixExp) << endl;
}
Here's evaluatePostfix():
int evaluatePostfix(string expression)
{
ArrayStack<int> S;
for (int i = 0; i < expression.length(); i++)
{
if (expression[i] == ' ' || expression[i] == ',') continue;
else if(IsOperator(expression[i]))
{
int operand2 = S.peek();
S.pop();
int operand1 = S.peek();
S.pop();
int result = PerformOperation(expression[i], operand1, operand2);
S.push(result);
}
else if(IsNumericDigit(expression[i]))
{
int operand = 0;
while (i < expression.length() && IsNumericDigit(expression[i]))
{
operand = operand * 10 + expression[i] - '0';
i++;
}
i--;
S.push(operand);
}
}
return S.peek();
}
Here's PerformOperation(), IsOperator(), IsNumericDigit(). These are all in evaluatePostfix.
bool IsNumericDigit(char C)
{
if (C >= '0' && C <= '9')
{
return true;
}
else
{
return false;
}
}
bool IsOperator(char C)
{
if (C == '+' || C == '-' || C == '*' || C == '/')
{
return true;
}
else
{
return false;
}
}
int PerformOperation(char operation, int operand1, int operand2)
{
if (operation == '+')
{
return operand1 + operand2;
}
else if (operation == '-')
{
return operand1 - operand2;
}
else if (operation == '*')
{
return operand1 * operand2;
}
else if (operation == '/')
{
return operand1 / operand2;
}
else
{
cout << "error" << endl;
}
return -1;
}
Lastly, here is infixToPostfix():
void infixToPostfix(string s)
{
ArrayStack<char> stackPtr;
string postfixExp;
for (int i = 0; i < s.length(); i++)
{
char ch = s[i];
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))
{
postfixExp += ch;
}
else if (ch == '(')
{
stackPtr.push('(');
}
else if (ch == ')')
{
while(stackPtr.peek() != '(')
{
postfixExp += stackPtr.peek();
stackPtr.pop();
}
stackPtr.pop();
}
else
{
while (!stackPtr.isEmpty() && prec(s[i]) <= prec(stackPtr.peek()))
{
postfixExp += stackPtr.peek();
stackPtr.pop();
}
stackPtr.push(ch);
}
}
while (!stackPtr.isEmpty())
{
postfixExp += stackPtr.peek();
stackPtr.pop();
}
cout << postfixExp << endl;
}

My program of infix to postfix gives runtime error

Below is an simple program to convert infix expression to postfix expression. It takes an infix expression in main program and after passing values in function converter, it returns a postfix expression as string.
#include<iostream>
#include<stdio.h>
#include<string>
#include <stack>
using namespace std;
int priority(char o) {
if (o == '(' || o == ')')
return -1;
else if (o == '*' || o == '/')
return 2;
else if (o == '+' || o == '-')
return 1;
else if (o == '^' )
return 3;
}
string converter(stack <char>s, string in) {
string pf;
int i;
for (i = 0; i < in.length(); i++) {
if ((in[i] >= 'a' && in[i] <= 'z') || (in[i] >= 'A' && in[i] <= 'Z') ){
pf+= in[i];
}
else if (in[i] == '(') {
s.push(in[i]);
}
else if (in[i] == ')') {
while (s.top() != '(' && (!s.empty())) {
char temp = s.top();
pf += temp;
s.pop();
}
}
else {
if (s.empty()) {
s.push(in[i]);
}
else {
if (priority(in[i]) > s.top()) {
s.push(in[i]);
}
else if (priority(in[i]) == s.top()&&(in[i]=='^')) {
s.push(in[i]);
}
else {
while (priority(in[i]) <= s.top()&&(!s.empty())) {
char temp = s.top();
pf += temp;
s.pop();
}
s.push(in[i]);
}
}
}
}
while (!s.empty()) {
char temp = s.top();
pf += temp;
s.pop();
}
return pf;
}
int main() {
string infix,postfix;
cout << "input an infix expression"<<endl;
cin >> infix;
stack <char> s;
postfix = converter(s, infix);
cout << "Postfix expression is:" << postfix;
return 0;
}
Every time I try to run the program, it gives runtime error.
It works till taking an infix expression but the function aborts abnormally.
I can't find the bug. I use visual studios. Is it a problem in my visual studios or a logic error, really don't know.
This bit:
while (priority(in[i]) <= s.top()&&(!s.empty()))
Accessing a stack's top when it's empty invokes undefined behavior, and that's exactly what's happening here, as priority(in[i]) <= s.top() will be checked first.
You should move the !s.empty() condition first. If it evaluates to true then the second condition will not be checked. This is called Short-circuit evaluation.
while (!s.empty() && priority(in[i]) <= s.top())

Stack calculator

I found this code online so I could study stack calculators, but when I try to enter an expression for the program to evaluate, it gives me 78. Every time. I've combed through it to see if I could debug it by myself, but I have no clue how to fix this. I've added the comments myself to make things more readable. Could anyone help?
#include<iostream>
#include<stack>
#include<cmath>
using namespace std;
int pri(char ch) //precedence checking
{
switch (ch)
{
case '-':
case '+': return 1;
case '*':
case '/': return 2;
case '^': return 3;
case '(':
case ')': return 4;
default: return -1;
}
}
int calculate(char op, int l , int r) //actual calculations
{
if(op == '+') return l + r;
if(op == '-') return l - r ;
if(op == '*') return l * r;
if(op == '/')
{
if(r > 0)
{
return l/r;
}
return 0;
}
if(op == '^') return pow(l,r);
return -1;
}
int main(void)
{
string equ;
cout << "Enter an expression: ";
getline(cin, equ);
char math[equ.size()+1];
int l = sizeof(math)/sizeof(char);
stack<char> s;
stack<int> op_s;
int i = 0;
while(math[i] != '\0')
{
if(math[i] == '(')
{
s.push('(');
}
else if(math[i] == ')')
{
while(s.top() != '(')
{
int r = op_s.top();
op_s.pop();
int l = op_s.top();
op_s.pop();
int re = calculate(s.top(),l,r);
op_s.push(re);
s.pop();
}
s.pop();
}
else if(math[i] == '+' || math[i] == '-' || math[i] == '*' || math[i] == '/' || math[i] == '^')
{
int pC = pri(math[i]);
while(!s.empty() && pri(s.top()) >= pC)
{
int r = op_s.top();
op_s.pop();
int l = op_s.top();
op_s.pop();
int re = calculate(s.top(),l,r);
op_s.push(re);
s.pop();
}
s.push(math[i]);
}
else
{
op_s.push(int(math[i])- 48);
}
i++;
}
while(!s.empty())
{
int r = op_s.top();
op_s.pop();
int l = op_s.top();
op_s.pop();
int re = calculate(s.top(),l,r);
op_s.push(re);
s.pop();
}
cout <<"Result: " << op_s.top() << endl;
return 0;
}
OK So I didn't go through everything with a fine toothed combed, but one obvious issue is that the char values from equ are never copied into the math array.
Below I just removed the C style math array and instead loop through the char values in equ (I renamed the equ variable to math).
Also note I only tested this with 5*5, I did not do any further testing beyond that.
/** Removed for brevity**/
int main( )
{
string math{ "5*5" };
//cout << "Enter an expression: ";
//getline(cin, math);
stack<char> s;
stack<int> op_s;
for ( auto i = 0; i < math.size( ); i++ )
{
if( math[ i ] == '(' )
{
s.push( '(' );
}
else if(math[ i ] == ')')
{
while( s.top( ) != '(' )
{
int r = op_s.top();
op_s.pop();
int l = op_s.top();
op_s.pop();
int re = calculate(s.top(),l,r);
op_s.push(re);
s.pop();
}
s.pop();
}
else if(math[i] == '+' || math[i] == '-' || math[i] == '*' || math[i] == '/' || math[i] == '^')
{
int pC = pri(math[i]);
while(!s.empty() && pri(s.top()) >= pC)
{
int r = op_s.top();
op_s.pop();
int l = op_s.top();
op_s.pop();
int re = calculate(s.top(),l,r);
op_s.push(re);
s.pop();
}
s.push(math[i]);
}
else
{
op_s.push(int( math[ i ] ) - 48 );
}
}
while(!s.empty())
{
int r = op_s.top();
op_s.pop();
int l = op_s.top();
op_s.pop();
int re = calculate(s.top(),l,r);
op_s.push(re);
s.pop();
}
cout <<"Result: " << op_s.top() << endl;
return 0;
}

How come the open and close brackets not showing in the output?

In C++, I am trying to convert these infix expressions (, ), +, -, *, and / to postfix using stacks, but the output does not print out all of the inputs. Parenthesis is not showing in the output after the program runs. There are no errors too.
This image shows the output after it compiles:
The code:
#include <iostream>
#include <stack>
#include <strings.h>
using namespace std;
int operatorPrecedence(char operators);
void infixtoPostfix(string exp);
int main()
{
string exp;
cout << "Enter Infix Expression: "; cin >> exp;
infixtoPostfix(exp);
return 0;
}
int operatorPrecedence(char operators){
//Checking precedence of operators
if (operators == '/') return 2;
else if (operators == '*') return 2;
else if (operators == '+') return 1;
else if (operators == '-') return 1;
else return -1;
}
void infixtoPostfix(string exp){
stack<char> s;
s.push('N');//Element in stack to indicate end of stack
int len = exp.length();
string ns;//Final string for result
for(int i = 0; i < len; i++){
//Storing operand into display string
if ((exp[i] >= 'A' && exp[i] <= 'Z') || (exp[i] >= 'a' && exp[i] <='z') || (exp[i] >= '0' && exp[i] <= '9'))
ns += exp[i];
//Checking for braces/Parentheses
else if (exp[i] == '(')
s.push(exp[i]);
else if (exp[i] == ')'){
while (s.top() != 'N' && s.top() != '('){
char c = s.top();
s.pop();
ns += c;
}
//Popping parentheses if empty
if (s.top() == '('){
char c = s.top();
s.pop();
}
}
else{
//Checking whether scanned operator is less than operator stored in the stack
while (s.top() != 'N' && operatorPrecedence(exp[i]) <= operatorPrecedence(s.top())){
char c = s.top();
s.pop();
ns += c;
}
s.push(exp[i]);
}
}
//Popping out everything else stored in the stack
while (s.top() != 'N'){
char c = s.top();
s.pop();
ns += c;
}
cout << "Postfix Expression: " << ns << endl;
}

Post fix calculator, returns wrong value

I'm Writing a program to implement postfix calculator, its giving me completely wrong answers.
Really appreciate the help
class stacks {
public:
typedef int List;
static const int size = 100;
stacks() {
use = 0;
}
void push(List entry) {
data[use] = entry;
++use;
}
List pop() {
if(!empty()) {
--use;
return data[use];
}
}
bool empty() const {
return use == 0;
}
int Size() const {
return use;
}
private:
List data[size];
int use;
};
int main() {
stacks s;
string input;
int final;
ifstream infile("foo.txt",ios::in);
while (getline(infile, input))
cout << "Expression: ";
for (int i = 0; i<input.length(); i++) {
cout << input[i];
auto oper1 = s.pop();
auto oper2 = s.pop();
if(input[i] == '1' || input[i] == '2' || input[i] == '3' || input[i] == '4' || nput[i] == '5' || input[i] == '6' || input[i] == '7' || input[i] == '8' || input[i] == '9')
s.push(input[i] - '0');
if(input[i] == '+')
s.push(oper1 + oper2);
if(input[i] == '-')
s.push(oper1 - oper2);
if(input[i] == '*')
s.push(oper1 * oper2);
if(input[i] == '/')
s.push(oper1 / oper2);
}
final = s.pop();
cout << endl << "Value = " << final << "." << endl << endl;
}
What do you recommend?
Thanks
You need to wait to pop() until you know you have an operator. You're popping stuff off the stack when you shouldn't be.