I am writing a code that evaluates a given Postfix expression. Each operand and operator is separated by a blank space and the last operator is followed by a blank space and an 'x'.
Example:
Infix expression: (2*3+4)*(4*3+2)
Postfix expression: 2 3 * 4 + 4 3 * 2 + * x
"x" implies the end of expression.
The input (Postfix expression) is given as a string from by another function that converts an infix expression to a postfix expression.
The function for postfix evaluation is:
int pfeval(string input)
{
int answer, operand1, operand2, i=0;
char const* ch = input.c_str();
node *utility, *top;
utility = new node;
utility -> number = 0;
utility -> next = NULL;
top = new node;
top -> number = 0;
top -> next = utility;
while((ch[i] != ' ')&&(ch[i+1] != 'x'))
{
int operand = 0;
if(ch[i] == ' ') //to skip a blank space
i++;
if((ch[i] >= '0')&&(ch[i] <= '9')) //to gather all digits of a number
{
while(ch[i] != ' ')
{
operand = operand*10 + (ch[i]-48);
i++;
}
top = push(top, operand);
}
else
{
top = pop(top, operand1);
top = pop(top, operand2);
switch(ch[i])
{
case '+': answer = operand2 + operand1;
break;
case '-': answer = operand2 - operand1;
break;
case '*': answer = operand2 * operand1;
break;
case '/': answer = operand2 / operand1;
break;
case '^': answer = pow(operand2, operand1);
break;
}
top = push(top, answer);
}
i++;
}
pop(top, answer);
cout << "\nAnswer: " << answer << endl;
return 0;
}
The output for the example I've given should be "140" but what I get is "6". Please help me find the error.
The push and pop methods are as follows (in case somebody wants to review):
class node
{
public:
int number;
node *next;
};
node* push(node *stack, int data)
{
node *utility;
utility = new node;
utility -> number = data;
utility -> next = stack;
return utility;
}
node* pop(node *stack, int &data)
{
node *temp;
if (stack != NULL)
{
temp = stack;
data = stack -> number;
stack = stack -> next;
delete temp;
}
else cout << "\nERROR: Empty stack.\n";
return stack;
}
while((ch[i] != ' ')&&(ch[i+1] != 'x'))
You drop out of this loop as soon as a) the current character is a space, or b) the next character is 'x'. The current character becomes a space pretty early in the process; you only process a small portion of the string.
Try comparing with the following code.
#include<iostream>
using namespace std;
#include<conio.h>
#include<string.h>
#include<math.h>
class A
{
char p[30],ch;
int i,top,s[30],y1,y2,x,y,r;
public:
A()
{
top=-1;
i=0;
}
void input();
char getsymbol();
void push(int);
int pop();
void evaluation();
};
void A :: input()
{
cout<<"enter postfix expression\n";
gets(p);
}
char A :: getsymbol()
{
return p[i++];
}
void A :: push(int ch)
{
if(top==29)
cout<<"stack overflow\n";
else
s[++top]=ch;
}
int A :: pop()
{
if(top==-1)
{
cout<<"stack underflow\n";
return 0;
}
else
return s[top--];
}
void A :: evaluation()
{
ch=getsymbol();
while(ch!='\0')
{
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')
{
cout<<"enter the value for "<<ch;
cin>>x;
push(x);
}
if(ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch=='^')
{
y2=pop();
y1=pop();
if(ch=='+')
{
y=y1+y2;
push(y);
}
else if(ch=='-')
{
y=y1-y2;
push(y);
}
else if(ch=='^')
{
y=y1^y2;
push(y);
}
else if(ch=='*')
{
y=y1*y2;
push(y);
}
else if(ch=='/')
{
y=y1/y2;
push(y);
}
else
{
cout<<"entered operator has no value\n";
}
}
ch=getsymbol();
}
if(ch=='\0')
{
r=pop();
cout<<"the result is "<<r;
}
}
int main()
{
A a;
int m=0;
while(m==0)
{
a.input();
a.evaluation();
cout<<"enter 0 to continue 1 to exit\n";
cin>>m;
}
getch();
return 0;
}
Related
I am writing code for postfix expression evaluation with +,-,*,/ and ^ operators. It should take input from the command line as a string which is a postix notation of an expression (whitespace is used as a delimiter). The program should print the result of the expression on the console.
The code I have written works fine for all test cases with integer values. E.g. it works for input: 2 2 2 * +
I have tried to change the stack input value to float rather than an int but it still doesn't work.
using namespace std;
struct node
{
float data ;
node *next ;
};
class stack
{
private :
node *head;
public :
stack()
{
head = NULL;
}
void push(float a)
{
node * temp = new node();
temp ->data = a ;
temp -> next = head ;
head = temp ;
}
int pop()
{
node *temp = head ;
head = temp->next ;
int a = temp->data ;
delete temp;
return a;
}
int see_top()
{
if(is_empty())
return 0 ;
node * temp = head ;
return (temp->data);
}
int is_empty()
{
if(head == NULL)
return 1;
else
return 0 ;
}
};
int is_digit(char a)
{
if(a >= '0' && a<= '9')
return 1;
else
return 0;
}
int is_operand(char a)
{
switch(a)
{
case '+' :
case '-' :
case '*' :
case '/' :
case '^' : return 1;
default : return 0;
}
}
float operation(float a , float b , char sym)
{
float ans ;
switch(sym)
{
case '+' : ans = a + b ;
break;
case '-' : ans = a - b ;
break ;
case '*' : ans = a*b ;
break ;
case '/' : ans = a/b ;
break ;
case '^' : ans = pow(a,b) ;
break ;
default : break ;
}
return ans ;
}
int main()
{
char exp[100];
stack s ;
float num=0 , num1=0 , num2=0 ;
int l , i ;
cout << "Enter the posfix expression : ";
cin.getline(exp,100);
l=strlen(exp);
for(i=0;i<l;i++)
{
if(is_digit(exp[i]))
{
num = 0;
while(exp[i]!=' ')
{
int a = exp[i++]- '0';
num = 10*num + a ;
}
s.push(num);
}
else if(is_operand(exp[i]))
{
num2 = s.see_top();
s.pop();
num1 = s.see_top();
s.pop();
num = operation(num1 , num2 , exp[i]);
s.push(num);
}
else
continue;
}
num = s.see_top();
s.pop();
cout << "Answer : " << num ;
return 0 ;
}
When I try to input an expression with some float values, it doesn't return the correct value. E.g. ideally for an expression 0.5 0.5 *, it should return 0.25 but it rather returns 225. For expression 0.1 0.1 + it returns -36.
The code looks very good! .
You are almost there. There are three problems in the code:
pop() casts everything to int
see_top() casts everything to int
The decimal point parsing does not work.
Here is an updated pop() and see_top(). Notice that they now return float.
float pop()
{
node *temp = head;
head = temp->next;
float a = temp->data;
delete temp;
return a;
}
float see_top()
{
if (is_empty())
return 0;
node *temp = head;
return (temp->data);
}
Parsing of decimal points is probably best fixed by adding a switch statement.
You really have a new state once you see a decimal point. See the code below. I have also added code to handle '-' character. I use the pow() math function to add in the decimal part of the number. I would move the number parsing into a function, but did not want to completely change your code. Here is the full solution:
#include <cmath>
#include <iostream>
using namespace std;
struct node {
float data;
node *next;
};
class stack {
private :
node *head;
public :
stack()
{
head = NULL;
}
void push(float a)
{
node *temp = new node();
temp->data = a;
temp->next = head;
head = temp;
}
float pop()
{
node *temp = head;
head = temp->next;
float a = temp->data;
delete temp;
return a;
}
float see_top()
{
if (is_empty())
return 0;
node *temp = head;
return (temp->data);
}
int is_empty()
{
if (head == NULL)
return 1;
else
return 0;
}
};
bool is_digit(char a)
{
return (a >= '0' && a <= '9') || a == '.' || a == '-';
}
bool is_operand(char a)
{
switch (a) {
case '+' :
case '-' :
case '*' :
case '/' :
case '^' : return true;
default : return false;
}
}
float operation(float a, float b, char sym)
{
float ans;
switch (sym) {
case '+' : ans = a + b;
break;
case '-' : ans = a - b;
break;
case '*' : ans = a * b;
break;
case '/' : ans = a / b;
break;
case '^' : ans = pow(a, b);
break;
default : break;
}
return ans;
}
int main()
{
char exp[100];
stack s;
float num = 0, num1 = 0, num2 = 0;
int l, i;
cout << "Enter the posfix expression : ";
cin.getline(exp, 100);
l = strlen(exp);
for (i = 0; i < l; i++) {
int exponent = 0;
int sign = 1;
if (is_digit(exp[i])) {
num = 0;
while (exp[i] != ' ') {
switch (exp[i]) {
case '.':exponent = -1;
break;
case '-':
sign = -1; // handle the negative sign
break;
default:int a = exp[i] - '0';
if(exponent >= 0) {
num = pow(10, exponent) * num + a;
++exponent;
} else {
num = pow(10, exponent) * a + num;
--exponent;
}
}
++i;
}
num *= sign; // If there was a '-', multiply by -1
s.push(num);
} else if (is_operand(exp[i])) {
num2 = s.see_top();
s.pop();
num1 = s.see_top();
s.pop();
num = operation(num1, num2, exp[i]);
s.push(num);
} else
continue;
}
num = s.see_top();
s.pop();
cout << "Answer : " << num;
return 0;
}
Alternative Solution Using std::istringstream
For a little extra fun, I rewrote some of the input processing to use std::istringstream. stringstream is very powerful, and should always be considered when doing parsing. I find that the string to double conversion functions in c++ is confusing and error prone. So, if you are allowed to use stringstream, this may be helpful. It removes the need to search for decimal points because stringstream will do the conversion for you. it will handle all the edge cases. Here is the stringstream solution:
#include <iostream>
#include <cmath>
#include <sstream>
using namespace std;
struct node {
float data;
node *next;
};
class stack {
private :
node *head;
public :
stack()
{
head = NULL;
}
void push(float a)
{
node *temp = new node();
temp->data = a;
temp->next = head;
head = temp;
}
float pop()
{
node *temp = head;
head = temp->next;
float a = temp->data;
delete temp;
return a;
}
float see_top()
{
if (is_empty())
return 0;
node *temp = head;
return (temp->data);
}
bool is_empty()
{
if (head == NULL)
return true;
else
return false;
}
};
int is_digit(char a)
{
if (a >= '0' && a <= '9')
return 1;
else
return 0;
}
int is_operand(char a)
{
switch (a) {
case '+' :
case '-' :
case '*' :
case '/' :
case '^' : return 1;
default : return 0;
}
}
float operation(float a, float b, char sym)
{
float ans;
switch (sym) {
case '+' : ans = a + b;
break;
case '-' : ans = a - b;
break;
case '*' : ans = a * b;
break;
case '/' : ans = a / b;
break;
case '^' : ans = pow(a, b);
break;
default : break;
}
return ans;
}
int main()
{
// char exp[100];
stack s;
float num = 0, num1 = 0, num2 = 0;
cout << "Enter the posfix expression : ";
std::string input_line;
std::getline(cin, input_line);
std::istringstream token_stream(input_line); // Parse words from input_line
std::string token;
while (token_stream >> token) {
// Check the first character of the token. It is n operand, then use it
// You could move the size() check to the is_operand() function
if (token.size() == 1 && is_operand(token[0])) {
char operand = token[0];
num2 = s.see_top();
s.pop();
num1 = s.see_top();
s.pop();
num = operation(num1, num2, operand);
s.push(num);
} else {
std::istringstream number_stream(token); // convert number tokens to floats
if(number_stream >> num) {
s.push(num);
}
}
}
num = s.see_top();
s.pop();
cout << "Answer : " << num;
return 0;
}
I have the following code. The problem is that if I choose an option, for example option #2 to sort the elements the program it's closing and I don't understand why... I'm using Eclipse IDE. The functions do the following:
a) A function to insert a data in a list that does not allow duplicate values (if the value does
not exist, pasting takes place at the beginning of the list). Payload elements to be integer.
b) A function to insert a data in a list so the list remains sorted ascending. Payload elements
to be integer
c) A function to determine the number of elements divisible by a z value received as
parameter.
d) A function to determine the number of elements greater than the information from the
first node of the list.
e) A function that determines the number of occurrences of a given value in the list.
#include<iostream>
using namespace std;
char menu()
{ char choice;
cout<<"********Choose an option********* \n" ;
cout<<"1. duplicate check\n";
cout<<"2. Sort the elements \n";
cout<<"3. Determine elements divisible by a value given Z \n";
cout<<"4. Determine the number of elements greater than the first node\n";
cout<<"5. Determine the number of occurrences in a list\n";
cout<<"6. -----Exit-----\n";
cin>>choice;
return choice;
}
struct node
{
int value;
node* prev;
node* next;
};
typedef node* pnode;
int nro=0;
void showlist(pnode start, int div)
{
nro=0;
if(start!=NULL)
{
while(start!=NULL)
{
if(start->value%div==0)
{
nro++;
cout<<start->value<<" ";
}
start=start->next;
}
}
}
void checkvalue(pnode start, int nr)
{
nro=0;
if(start!=NULL)
{
while(start!=NULL)
{
if(start->value==nr)
{
nro++;
}
start=start->next;
}
}
}
bool checkduplicates(pnode start, int val)
{
if(start==NULL) return false;
else
{
while(start!=NULL)
{
if(start->value==val) return true;
start=start->next;
return false;
}
}
}
void sort(pnode start)
{
pnode p=start;
pnode q=NULL;
while(p->next!=NULL)
{
q=p->next;
while(q!=NULL)
{
if(p->value > q->value)
{
int aux;
aux=p->value;
p->value=q->value;
q->value=aux;
}
q=q->next;
}
p=p->next;
}
}
void showbig(pnode start)
{
pnode q=start->next;
while(q!=NULL)
{
if(q->value > start->value)
{
cout<<q->value<<" ";
}
q=q->next;
}
}
int main()
{
pnode start=NULL;
pnode end=NULL;
pnode aux=NULL;
char choice;
int number;
do{
choice=menu();
switch(choice)
{
case '1':
int z;
cout<<"Value: ";
cin>>z;
if(start==NULL)
{
start = new node;
start->value=z;
start->next=NULL;
start->prev=NULL;
end=start;
aux=start;
}
else
{
aux= new node;
aux->value=z;
aux->next=start;
start->prev=aux;
aux->prev=NULL;
start=aux;
}
if (!checkduplicates(start,z))
{cout<<"Duplicate value. Cannot insert.\n";
break;}
break;
case '2':
sort(start);
break;
case '3':
cout<<"Value: ";
cin>>z;
showlist(start,z);
if(nro==0) cout<<"No values found.\n";
else cout<<"\n";
break;
case '4':
showbig(start);
cout<<"\n";
break;
case '5':
cout<<"Value: ";
cin>>z;
checkvalue(start,z);
if(nro==0) cout<<"No values found.\n";
else cout<<nro<<"\n";
break;
default: cout<<"Exit \n";
}
} while (choice !='6');
return 0;
}
sort(start);
is failing because start is NULL which means p is NULL
pnode p = start;
And you try to dereference a NULL pointer here
while (p->next != NULL)
I'm struggling with the printing of a binary tree that I coded. It's a little program where you can type in different states and then it orders them alphabetically in the binary tree and afterwards it should print them out again, in alphabetic order.
How should I start with the listing function? I read in the internet that a recursive algorithm would be the best, but I don't really know how to do that with my setup.
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int insertInt()
{
int x;
cin>>x;
while(cin.fail())
{
cout<<"Error! Please enter a valid integer: ";
cin.clear();
cin.ignore();
cin>>x;
}
return x;
}//closes insertInt
struct node
{
string info;
node* right;
node* left;
}; //closes node
class States
{
private:
node* start;
public:
void insert();
void delete();
void list();
void search();
States();
}; //closes States class
States::States()
{
start = new node;
start -> left = NULL;
start -> right = NULL;
start -> info = " ";
}
void States::insert()
{
string state;
char c;
node *temp, *p, *s;
p = start;
s = start;
temp = new node;
temp ->info = state;
cout<<"Please enter the state you want to add: ";
cin>>state;
if(s -> info == " ")
{
s -> info = state;
cout<<"Added state "<<state<<"to the list.\n";
cout<<"Ready to continue? (enter y)";
cin>>c;
return;
}//close if
else
{
while(true)
{
//moving pointer until next level is empty
if(s->info > temp->info && s->left != NULL)
{
s = s->left;
continue;
}//close if
if(s->info < temp->info && s->right != NULL)
{
s = s->right;
continue;
}//close if
//inserting the new node
if(s->info > temp->info && s-> left == NULL)
{
s -> left = temp;
break;
}//close if
if(s->info < temp->info && s->right == NULL)
{
s->right = temp;
break;
}//cloese if
}//close while loop
}//close else
}//close insert function
void States::list()
{
node *p, *s;
p = start;
s = start;
if(start->info == " ")
cout<<"Nothing to display!\n";
if(s->left == NULL)
cout<<"-"<<s->info<<endl;
}
void States::search()
{
string state;
cout<<"Please enter the state you're looking for: ";
cin>>state;
node *s, *temp;
s = start;
temp = new node;
temp ->info = state;
while(true)
{
if(s->info == state)
{
cout<<"Found your state!\n";
break;
}
if(s->info > temp->info)
{
if(s->left == NULL)
break;
else
s = s->left;
continue;
}//close if
if(s->info < temp->info)
{
if(s->right == NULL)
break;
else
s = s->right;
continue;
}//close if
}//close while loop
}//close search function
int main()
{
States s1;
int c;
int exit = 0;
while(exit == 0)
{
cout<<"----------------------------------------------------------------------\n";
cout<<"\t\tChoose one of the following options\n";
cout<<"\t\t\t\t(1) Add a state\n";
cout<<"\t\t\t\t(2) List states\n";
cout<<"\t\t\t\t(3) Search for state\n";
cout<<"\t\t\t\t(4) Delete state\n";
cout<<"\t\t\t\t(5) Exit\n";
cout<<"----------------------------------------------------------------------\n";
c = insertInt();
switch(c)
{
case 1:
s1.insert();
break;
case 2:
s1.list();
break;
case 3:
s1.search();
break;
case 4:
s1.delete();
break;
case 5:
exit = 1;
cout<<"Exiting...\n";
break;
default:
cout<<"Error. Please enter a valid integer.\n";
}//close switch
}//closes while loop
}//closes main
Say that node is a pointer of type Node* representing some node of your tree. Then inorder(Node*) is defined as follows:
void inorder(Node* node)
{
if (!node) // end the recursion if node == nullptr
return;
inorder(node->left); // display the left subtree
std::cout << node->info << " "; // display the current node
inorder(node->right); // display the right subtree
}
I need to create a RPN (postfix notation) calculator which makes simple operations (+, -, *, /), while using a linked list to maintain the stack. I have got the majority of it done but am running into a few problems. I can calculate any two numbers with one operand (ex: 5 5 + = 10), but cannot do anything more than that. I have done some research online, and watched a few YouTube videos to get where I am at now, but most use the stack reference to do it. I have tried to combine tutorials on that, along with how to make my own stack.
I am quite new to this and am pretty lost on how to calculate a larger expression (ex: 5 5 5 + + = 15), and I also need to check for errors, which I have completed some, but the ones I'm struggling with are "too many operators," and "too many operands." With too many operators I'm assuming it has something to do with not being able to pop off a value because there isn't one there, but that's as far as I can get (if it's right, still not quite sure how to implement it). Any help with any of these 3 things, or anything else you can see here would greatly be appreciated.
#include<iostream>
#include<string>
#include<sstream>
#include<iomanip>
using namespace std;
class SLLNode
{
double data;
SLLNode *top;
SLLNode *ptr;
public:
SLLNode()
{
top = NULL;
ptr = NULL;
}
void pushVal(double val)
{
SLLNode *next = new SLLNode;
next -> data = val;
next -> ptr = top;
top = next;
}
double popVal()
{
SLLNode *next = new SLLNode;
next = top;
top = top -> ptr;
next -> ptr = NULL;
return next -> data;
delete next;
}
void print()
{
SLLNode *next = new SLLNode;
next = top;
cout << "= " << next -> data << endl << ">>";
next = next -> ptr;
delete next;
}
};
bool isOperator(const string& input)
{
string ops[] = {"+", "-", "*", "/"};
for(int i = 0; i < 4; i++)
{
if(input == ops[i])
{
return true;
}
}
return false;
}
void performOp(const string& input, SLLNode& stack)
{
double fVal, sVal;
int result = 0;
sVal = stack.popVal();
fVal = stack.popVal();
if(input == "+")
{
stack.pushVal(fVal + sVal);
}
else if(input == "-")
{
stack.pushVal(fVal - sVal);
}
else if(input == "*")
{
stack.pushVal(fVal*+ sVal);
}
else if(input == "/" && sVal != 0)
{
stack.pushVal(fVal / sVal);
}
if(input == "/" && sVal == 0)
{
cout << "Error: Division by zero" << endl;
result = 1;
}
if(result == 0)
{
stack.print();
}
}
int main()
{
string input;
SLLNode stack;
cout << "::::::::::::::::RPN CALCULATOR:::::::::::::::::" << endl;
cout << "::TYPE IN A POSTFIX EXPRESSION OR 'q' TO QUIT::" << endl;
cout << ":::::::::::::::::::::::::::::::::::::::::::::::" << endl << endl;
cout << ">>";
while(true)
{
cin >> input;
double num;
if(istringstream(input) >> num)
{
stack.pushVal(num);
}
else if (isOperator(input))
{
performOp(input, stack);
}
else if (input == "q")
{
return 0;
}
else
{
cout << "Error: Invalid input" << endl;
}
}
}
First I would recommend you use std::map<double> instead of rolling your own linked list, unless it is for learning purposes.
The main problem is in SLLNode::popVal() and SLLNode::print() where things got a little bit confused.
Here is what you need to change to fix it:
double popVal()
{
SLLNode *next = top -> ptr;
double ret = top -> data;
delete top;
top = next;
return ret;
}
void print()
{
cout << "= " << top -> data << endl << ">>";
}
There are many other things you could improve in your code but that should answer your question.
You have two operators, '*' and '+' in your expression to calculate multiplication. I have added & rearranged a bit of error checking,
int
performOp(const string& input, SLLNode& stack)
{
double fVal, sVal;
int result = 0;
if( stack.size < 2 )
{
cout << "Error: too few operands" << end;
stack.print();
return 1;
}
sVal = stack.popVal();
fVal = stack.popVal();
if(input == "+")
{
stack.pushVal(fVal + sVal);
}
else if(input == "-")
{
stack.pushVal(fVal - sVal);
}
else if(input == "*")
{
stack.pushVal(fVal * sVal); //problem was here
}
else if(input == "/" )
{
if(sVal == 0)
{
cout << "Error: Division by zero" << endl;
stack.print();
return 1;
}
stack.pushVal(fVal / sVal);
}
return 0;
}
Define a list node that contains head/tail, and counts the elements in your stack,
#include<iostream>
#include<string>
#include<sstream>
#include<iomanip>
using namespace std;
class SLLNode //single link list
{
public:
SLLNode *next;
double data;
SLLNode()
{
next = NULL;
data = 0;
}
void print()
{
SLLNode *node = NULL;
cout << "= " << data << endl << ">>";
}
};
Your stack implementation leaks memory, allocates unnecessary nodes, and is missing a couple of useful stack operations that will help you solve some of your problems. You need a destructor that empties your list in case you forget to empty it, and it would help to have a print the entire list. Anyway,
class SLList //single link list
{
SLLNode *head;
SLLNode *tail;
int _count;
public:
SLList()
{
head = NULL;
tail = NULL;
_count = 0;
}
~SLList()
{
while( !empty() ) { pop(); }
}
int size() { return _count; }
bool empty() { return (!head); return false; }
void push(double val)
{
SLLNode *node = new SLLNode;
node->data = val;
node->next = head;
++_count;
if(!tail) tail = node;
head = node;
}
double pop()
{
SLLNode *node = NULL;
if(!head) return 0;
node = head;
double val = node->data;
head = node->next;
--_count;
if(!head) tail = NULL;
delete node;
return val;
}
double tip()
{
SLLNode *node = NULL;
if(!head) return 0;
node = head;
double val = node->data;
return val;
}
void print()
{
SLLNode *node = NULL;
if(!head) return;
for( node=head; node; node=node->next )
node->print();
}
};
You might want to add more operators, extract that,
bool isOperator(const string& input);
int performOp(const string& input, SLList& stack);
static string BINOPS[] = {"+", "-", "*", "/"};
bool
isOperator(const string& input)
{
for(int i = 0; i < 4; i++) //should get size of BINOPS
{
if(input == BINOPS[i])
{
return true;
}
}
return false;
}
Check your stacksize prior to extracting items from your stack,
int
performOp(const string& input, SLList& stack)
{
double fVal, sVal;
int result = 0;
if( stack.size() < 2 )
{
cout<<"Error: too few operands"<<endl;
stack.print();
return 1;
}
sVal = stack.pop();
fVal = stack.pop();
if(input == "+")
{
stack.push(fVal + sVal);
}
else if(input == "-")
{
stack.push(fVal - sVal);
}
else if(input == "*")
{
stack.push(fVal * sVal);
}
else if(input == "/" )
{
if(sVal == 0)
{
cout << "Error: Division by zero" << endl;
stack.print();
return 1;
}
stack.push(fVal / sVal);
}
return 0;
}
You need some way to print your list. The forth language used ".", so here I have added a case to print the list using ".",
int
main()
{
string input;
SLList stack;
cout<<"::::::::::::::::RPN CALCULATOR:::::::::::::::::"<<endl;
cout<<"::TYPE IN A POSTFIX EXPRESSION OR 'q' TO QUIT::"<<endl;
cout<<":::::::::::::::::::::::::::::::::::::::::::::::"<<endl<<endl;
double num;
while(true)
{
cout << ">>";
cin >> input;
if(istringstream(input) >> num)
{
stack.push(num);
}
else if (isOperator(input))
{
performOp(input, stack);
}
else if (input == ".")
{
stack.print();
double val = stack.tip();
cout << "= " << val << endl << ">>";
}
else if (input == "q")
{
return 0;
}
else
{
cout << "Error: Invalid input" << endl;
}
}
}
I also cleaned up a couple of other errors.
Good day, everyone! I'm new in C++ (and here in stackoverflow as well) and I need help from you experts.
I have here a code that should ask the user for the infix expression then converts it to postfix and outputs the result (postfix calculator). However, I cannot convert postfix to output instantly so as soon as it displays the postfix expression, it asks for the postfix expression again (with spaces after e.g., 1 2 + ) before outputting the real answer.
There is no error or warning but when I run the program, the computer says "file.exe has stopped working" after displaying the postfix expression. So the program is able to convert infix to postfix expression correctly but there is still some jinx when displaying the output.
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
struct node {
char data;
node *next;
};
node *top=NULL;
node *bottom=NULL;
node *key;
node *last;
node *before_last;
void push (const char Symbol) {
key = new node;
key->data = Symbol;
key->next = top;
top = key;
}
void push_for_output (node* &stack, int key) {
node* newNode = new node;
newNode->data = key;
newNode->next = stack;
stack = newNode;
}
const char pop() {
if (!top) {
cout << "Stack underflow\n" << endl;
return ' ';
}
node* key = top;
top = top->next;
char ch = key->data;
delete key;
return ch;
}
int pop_for_output (node* &stack) {
int key = stack->data;
node* nodeToDelete = stack;
stack = stack->next;
delete nodeToDelete;
return key;
}
bool isOperator (char *token) {
if (strcmp(token, "+") == 0) {
return true;
}
else if (strcmp(token, "-") == 0) {
return true;
}
else if (strcmp(token, "*") == 0) {
return true;
}
else if (strcmp(token, "/") == 0) {
return true;
}
else {
return false;
}
}
const bool is_empty() {
return !top;
}
int postfix(const char *infix) {
char infix_ch[100]={NULL};
char postfix_ch[100]={NULL};
node* stack = NULL;
strcpy(infix_ch,"(");
strcat(infix_ch, infix);
strcat(infix_ch,")");
char symbol[5]={NULL};
char temp[5]={NULL};
for(int i=0; i<strlen(infix_ch); i++) {
symbol[0]=infix_ch[i];
if(symbol[0]=='(')
push(symbol[0]);
else if(symbol[0]==')') {
symbol[0]=pop( );
while(symbol[0]!='(') {
strcat(postfix_ch, symbol);
symbol[0]=pop( );
}
}
else if(symbol[0]=='^' || symbol[0]=='*' || symbol[0]=='/' || symbol[0]=='+' || symbol[0]=='-') {
if(symbol[0]=='*' || symbol[0]=='/') {
temp[0]=pop( );
while(temp[0]=='^' || temp[0]=='*' || temp[0]=='/') {
strcat(postfix_ch, temp);
temp[0]=pop( );
}
push(temp[0]);
}
else if(symbol[0]=='+' || symbol[0]=='-') {
temp[0]=pop( );
while(temp[0]!='(') {
strcat(postfix_ch, temp);
temp[0]=pop( );
}
push(temp[0]);
}
push(symbol[0]);
}
else
strcat(postfix_ch, symbol);
}
cout << "Postfix: " << postfix_ch;
char postfix[80];
cout << "\nEnter postfix expression (include spaces between each operand and/or operator): ";
cin.getline(postfix, 80);
char *tokens = strtok(postfix, " ");
while (tokens != NULL) {
if (isOperator (tokens)) {
int operand2 = pop_for_output(stack);
int operand1 = pop_for_output(stack);
int result;
if (strcmp(tokens, "+") == 0) {
result = operand1 + operand2;
}
else if (strcmp(tokens, "-") == 0) {
result = operand1 - operand2;
}
else if (strcmp(tokens, "*") == 0) {
result = operand1 * operand2;
}
else if (strcmp(tokens, "/") == 0) {
result = operand1 / operand2;
}
push_for_output (stack, result);
}
else {
push_for_output (stack, atoi (tokens));
}
tokens = strtok(NULL, " ");
}
cout << pop_for_output(stack);
system("pause");
return 0;
}
int main( ) {
char infix_values[100]={NULL};
cout << "Enter the infix equation: ";
cin >> infix_values;
postfix(infix_values);
}
I'm a newbie and I really need help from you experts. I will really appreciate it if you help me correct my program. Thank you very much and have a nice day!
One possible issue is that the pop_for_output() function never checks for an empty/NULL stack like you do in pop(). If an invalid postfix expression is entered, or if your parsing is incorrect, you could very easily get into the case of referencing a NULL pointer which could very well explain the crash.