Prefix to Postfix conversion with parentheses - c++

I am really stuck in make conversion of special prefix to postfix operation on our task, let me describe the task similarly :
We have such operation to use as operations in our prefixes, here is the method that i am checking them :
bool isOperator(string c)
{
if (c == "log" || c == "exp" || c == "sum" || c == "div" || c == "abs" || c == "sqrt" || c == "sub" || c == "product" || c == "max" || c== "min" || c == "mod" ) // you may add operator here
return true;
return false;
}
Anyway example prefix instructions can have parentheses to make operation precedence, this is what I am stuck at. I know, I need to implement such a recursion, but i can't find a way.
div ( sqrt 5 ) 3
Output should be
5 sqrt 3 div
Another example :
div ( sum ( exp 2 3 ) ( sqrt 5 ) ) 3
Output
2 3 exp 5 sqrt sum 3 div
Every operation, parentheses or number should have space between elements in assumed condition.
My stack implementation
Stack.h
#include<iostream>
using namespace std;
struct node {
string op ;
node *next;
};
struct Stack {
node * head;
void create();
void close();
void push (node *);
node* pop();
node* top();
bool isEmpty();
};
Stack.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "stack.h"
#include <iostream>
#include <stdlib.h>
void Stack::create() {
head = NULL;
}
void Stack::close() {
node *p;
while (head) {
p = head;
head = head->next;
//delete [] p->data;
delete p;
}
}
void Stack::push(node *newdata) {
node *newnode = new node;
newnode = newdata;
newnode->op = newdata->op;
newnode->next = head;
head = newnode;
}
node *Stack::pop() {
if (isEmpty())
return NULL;
node *topnode = head;
head = head->next;
//delete topnode;
return topnode;
}
node *Stack::top() {
if (isEmpty())
return NULL;
node *topnode = head;
//delete topnode;
return topnode;
}
bool Stack::isEmpty() {
return (head == NULL);
}
as #PaulMcKenzie mentioned, i've tried an implementation below, sub_array string array contains the word list without spaces.
bool isLeftParanthesis(string c)
{
if (c == "(" ) // you may add operator here
return true;
return false;
}
bool isRightParanthesis(string c)
{
if (c == ")") // you may add operator here
return true;
return false;
}
int main()
{
string prefix;
getline(cin, prefix);
istringstream iss(prefix);
istringstream iss2(prefix);
int count1 = 0, count2 = 0;
string postfix = "";
Stack *st = new Stack;
string t1, t2;
string sub;
string *sub_array;
while (iss >> sub) {
count1++;
}
sub_array = new string[count1];
while (iss2 >> sub) {
sub_array[count2] = sub;
count2++;
}
int l = count1;
int right_p_count = 0;
for (int i = 0; i < count1; i++)
{
if (isRightParanthesis(sub_array[i]))
{
right_p_count++;
}
}
string *postfixes = new string[right_p_count];
int index_right_p = 0;
for (int i = 0; i < count1; i++) {
while (!isRightParanthesis(sub_array[i]))
{
node *n = new node;
n->op = sub_array[i];
st->push(n);
i++;
if (i == count1)
{
break;
}
}
if( i != count1){
if (isRightParanthesis(sub_array[i])) {
postfix = "";
while (!isLeftParanthesis(st->top()->op))
{
string t = st->pop();
if (!isOperator(t) && !isLeftParanthesis(t) && !isRightParanthesis(t)) {
postfix = t + " " + postfix;
}
else if (isOperator(t)) {
postfix = postfix + " " + t;
}
}
st->pop();
postfixes[index_right_p] = postfix;
index_right_p++;
}
}
postfix = "";
while ( !st->isEmpty() && index_right_p == right_p_count && i == count1)
{
string t = st->pop();
if (!isOperator(t) && !isLeftParanthesis(t) && !isRightParanthesis(t)) {
postfix = t+" "+postfix;
}
else if (isOperator(t)) {
postfix = postfix+""+t;
}
else {
break;
}
}
}
string result = "";
for (int i = 0; i < right_p_count; i++)
{
result = result + "" + postfixes[i];
}
result = result + " " + postfix;
cout << result << endl;
}
Variable postfix refers to output postfix, but my output is not wrong for some of the operations such as :
div ( sqrt 5 ) 3
When i saw a parantheses i am checking if it is left or right, using right one for trigger.
abs ( product -2 -4 -8 )
Expected output is :
-2 -4 -8 product abs
UPDATE : I solved stack problem myself, but found out that, algorithm calculates some expressions wrongly...
Example expression :
3 2 3 exp sum
Expected output :
sum 3 ( exp 2 3 )
My output :
2 3 exp 3 sum
My algorithm which is using right parentheses as triggers calculates it wrongly and I don't know how to implement this control into that, are there any suggestions ?

Related

Construct Expression tree for multi digit number

I want to construct a expression tree for a multi digit number Like given expression is (122+30) and the post order traversal of this gives "122 30 +"
But this code creates the expression tree and gives post order traversal of a single digit expression only like (1+2)
#include <bits/stdc++.h>
using namespace std;
// Tree Structure
typedef struct node
{
char data;
struct node *left, *right;
} * nptr;
// Function to create new node
nptr newNode(char c)
{
nptr n = new node;
n->data = c;
n->left = n->right = nullptr;
return n;
}
unsigned int getOperand(char ch) {
if(ch >= '0' && ch <= '9'){
return ch - '0';
}
return 0;
}
// Function to build Expression Tree
nptr build(string& s)
{
// Stack to hold nodes
stack<nptr> stN;
// Stack to hold chars
stack<char> stC;
nptr t, t1, t2;
// Prioritising the operators
int p[123] = { 0 };
p['+'] = p['-'] = 1, p['/'] = p['*'] = 2, p['^'] = 3,
p[')'] = 0;
for (int i = 0; i < s.length(); i++)
{
if (s[i] == '(') {
// Push '(' in char stack
stC.push(s[i]);
}
// Push the operands in node stack
else if (getOperand(s[i]))
{
t = newNode(s[i]);
stN.push(t);
}
else if (p[s[i]] > 0)
{
// If an operator with lower or
// same associativity appears
while (
!stC.empty() && stC.top() != '('
&& ((s[i] != '^' && p[stC.top()] >= p[s[i]])
|| (s[i] == '^'
&& p[stC.top()] > p[s[i]])))
{
// Get and remove the top element
// from the character stack
t = newNode(stC.top());
stC.pop();
// Get and remove the top element
// from the node stack
t1 = stN.top();
stN.pop();
// Get and remove the currently top
// element from the node stack
t2 = stN.top();
stN.pop();
// Update the tree
t->left = t2;
t->right = t1;
// Push the node to the node stack
stN.push(t);
}
// Push s[i] to char stack
stC.push(s[i]);
}
else if (s[i] == ')') {
while (!stC.empty() && stC.top() != '(')
{
t = newNode(stC.top());
stC.pop();
t1 = stN.top();
stN.pop();
t2 = stN.top();
stN.pop();
t->left = t2;
t->right = t1;
stN.push(t);
}
stC.pop();
}
}
t = stN.top();
return t;
}
// Function to print the post order
// traversal of the tree
void postorder(nptr root)
{
if (root)
{
postorder(root->left);
postorder(root->right);
cout << root->data;
}
}
int main()
{
string s ;
getline(cin,s);
nptr root = build(s);
// Function call
postorder(root);
return 0;
}
what changes should I do so that it can handle multi digit expression.

Postfix expression evaluation using stack

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 postix 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;
}

Implementing linked list on manipulating multiple list order with C++

Disclaimer: This is homework and I am pretty much a complete beginner in programming (only took an intro class to C a few years ago). If it matters, this is from a Competitive Programming class. I appreciate all feedback besides on the question itself like good programming practices, naming conventions...etc. I am new to coding, but love it and want to improve.
Consider n lists that are initialized with a single member that corresponds to its list number, i.e.:
#1: 1
#2: 2
#3: 3
...
Input:
First line contains n m where 1 ≤ n ≤ 1000000, 1 ≤ m ≤ 2000000;
Followed by m lines of k a b, where k is either 0 or 1 and denotes the type of manipulation:
k = 0: find member a and move from its position to behind member b
k = 1: move the entire list of #a list and place it behind the #b list
Output:
Print the lists in order after all the commands are executed. The question specifically states no whitespaces at the end of each line.
What I've tried:
#include <iostream>
#include <sstream>
#include <vector>
#include <ctime>
using namespace std;
class List {
private:
struct Node {
int data;
Node *next;
};
Node *head;
public:
List() {
head = NULL;
}
Node *GetHead() {
return head;
}
Node *GetPrevNode(int value) { // Gets the previous node to the node I am trying to move
Node *temp, *peek;
temp = head;
peek = temp->next;
if (head->data == value)
return head;
else {
while (peek != NULL) {
if (peek->data == value) {
return temp;
}
else {
temp = temp->next;
peek = temp->next;
}
}
return NULL;
}
return NULL;
}
Node *GetNode(int value) { // Gets the actual node I'm trying to move
Node *temp;
temp = head;
while (temp != NULL) {
if (temp->data == value) {
return temp;
}
else {
temp = temp->next;
}
}
return NULL;
}
void PushNode(int value) {
Node *temp = new Node;
temp->data = value;
temp->next = NULL;
if (head == NULL) {
head = temp;
}
else {
head->next = temp;
}
}
void MoveNode(Node *prevFrom, int value, Node *dest) { // called on the FROM list
Node *tempDestNext, *from;
tempDestNext = dest->next;
if (prevFrom->data == value) {
from = prevFrom;
}
else {
from = prevFrom->next;
}
//different cases
if (dest->next == from) {
return;
}
else if (from->next == dest) {
from->next = dest->next;
dest->next = from;
if (from == prevFrom) {
head = dest;
}
else {
prevFrom->next = dest;
}
}
else {
Node *tempFromNext;
tempFromNext = from->next;
dest->next = from;
if (from == head) {
head = tempFromNext;
}
else {
prevFrom->next = tempFromNext;
}
from->next = tempDestNext;
}
}
void ConcList(Node *headFrom) { // called on the DESTINATION list
if (head == NULL) {
head = headFrom;
}
else {
Node *temp;
temp = head;
while (temp != NULL) {
if (temp->next == NULL) {
temp->next = headFrom;
break;
}
else {
temp = temp->next;
}
}
}
}
void PrintList() {
Node *temp;
temp = head;
while (temp != NULL) {
cout << " " << temp->data;
temp = temp->next;
}
}
};
struct Move {
int type, from, to;
};
void MarkNodePos(vector<int> &NodePos, int type, int from, int to) { // record on which list a node is
switch (type) {
case 0:
NodePos[from - 1] = NodePos[to - 1];
break;
case 1:
for (int i = 0; i < NodePos.size(); i++) {
if (NodePos[i] == (from - 1)) {
NodePos[i] = (to - 1);
}
}
break;
}
}
int RandomNum(int min, int max) {
int range = max - min + 1;
int num = rand() % range + min;
return num;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0); // my teacher told us to include this code for speed optimization
int n, m;
cin >> n >> m;
cin.ignore();
vector<List> line;
for (int i = 0; i < n; i++) {
List temp;
temp.PushNode(i + 1);
line.push_back(temp);
}
vector<int> NodePos;
for (int i = 0; i < n; i++) {
NodePos.push_back(i);
}
string instrc;
Move step;
srand(time(NULL));
for (int i = 0; i < m; i++) {
int mode = 0; // switch between input and testing mode
switch (mode) {
case 0: {
getline(cin, instrc);
stringstream ss(instrc);
ss >> step.type >> step.from >> step.to;
break;
}
case 1:
stringstream ss;
ss << RandomNum(0, 1) << " " << RandomNum(1, n) << " " << RandomNum(1, n);
ss >> step.type >> step.from >> step.to;
cout << step.type << " " << step.from << " " << step.to << endl;
break;
}
if (step.from != step.to) {
switch (step.type) {
case 0:
int from, to;
from = NodePos[step.from - 1];
to = NodePos[step.to - 1];
line[from].MoveNode(line[from].GetPrevNode(step.from), step.from, line[to].GetNode(step.to));
MarkNodePos(NodePos, step.type, step.from, step.to);
break;
case 1:
if (line[step.from - 1].GetHead() != NULL) {
line[step.to - 1].ConcList(line[step.from - 1].GetHead());
List clear;
line[step.from - 1] = clear;
MarkNodePos(NodePos, step.type, step.from, step.to);
}
break;
}
}
}
for (int i = 0; i < n; i++) {
cout << "#" << (i + 1) << ":";
line[i].PrintList();
if (i != (n - 1))
cout << "\n";
}
return 0;
}
An example:
Input:
6 4
0 4 3
0 6 5
1 2 5
1 6 5
Output:
#1: 1
#2:
#3: 3 4
#4:
#5: 5 6 2
#6:
I keep getting wrong answer from the judge but as you can seen, I used a random number generator to test out my program and from my testing it all seems fine. I really have no clue what to look for. What could be causing the error?

Issues printing binary tree using breadth-first traversal in C++?

I'm writing a program that converts an expression in prefix notation to an expression tree. I'm having trouble getting the correct problem and I believe something is wrong with my print function which uses breadth first traversal. For example, when I input +-*1234, I get the output below. However, the 1 and the 2 should be the first two nodes in Depth 3. Could anybody point me in the right direction or explain what is happening?
Output:
Enter a prefix expression: +-*1234
Depth 0: +
Depth 1: - 4
Depth 2: * 3 1 2
Depth 3: [Empty][Empty][Empty][Empty][Empty][Empty][Empty][Empty]
My program:
#include <iostream> // For cout, cin
#include <cctype> // For isdigit
#include <queue> // For queue, push, pop, front
#include <algorithm> // For max
using namespace std;
class node {
public:
// CONSTRUCTOR
node(char data);
char data;
node *left, *right;
};
node::node(char data)
{
this -> data = data;
this -> left = NULL;
this -> right = NULL;
}
class next_node {
public:
// CONSTRUCTOR
next_node(node *tree_node);
node *tree_node;
next_node *next;
};
next_node::next_node(node *tree_node)
{
this->tree_node = tree_node;
next = NULL;
}
class tree {
public:
// CONSTRUCTOR
tree() { root = NULL; }
// Member Functions
void add_node(node *ptr);
void insert(char data);
void build(string prefix);
void print();
int get_height(node *ptr);
int double_num(int n);
bool isOperator(char sym);
node *remove_node()
{
if (root != NULL) {
node *ptr = root -> tree_node;
root = root -> next;
return ptr;
}
}
node *get_root()
{
return (root -> tree_node);
}
private:
next_node *root;
};
void tree::add_node(node *ptr)
{
if (root == NULL) root = new next_node(ptr);
else {
next_node *new_ptr = new next_node(ptr);
new_ptr -> next = root;
root = new_ptr;
}
}
void tree::insert(char data)
{
// If number
if(isdigit(data)) {
node *new_ptr = new node(data);
add_node(new_ptr);
// If operator
} else if (isOperator(data)) {
node *new_ptr = new node(data);
new_ptr -> left = remove_node();
new_ptr -> right = remove_node();
add_node(new_ptr);
}
}
void tree::build(string prefix)
{
// Scan from right to left
for (int i = prefix.length() - 1; i >= 0 ; i--) {
insert(prefix[i]);
}
}
void tree::print()
{
queue<node*> values;
node * root_ptr = get_root();
queue<char> line;
if (root_ptr) values.push(root_ptr);
else {
values.push(NULL);
}
while (!values.empty())
{
node * current_node = values.front();
values.pop();
line.push(current_node -> data);
if (current_node -> left) {
values.push(current_node -> left);
}
if (current_node -> right) {
values.push(current_node -> right);
}
}
for(int i=0; i < get_height(root_ptr); i++) {
cout << "Depth " << i << ": ";
for(int j=0; j < double_num(i); j++) {
if (!line.empty()) {
if (line.front() == NULL) {
cout<< "Empty";
} else {
cout << line.front() << " ";
line.pop();
}
} else if (line.empty()) {
cout << "[Empty]";
}
}
cout << "\n";
}
}
int tree::get_height(node *ptr) {
if(ptr == NULL ) return 0;
else {
return (1 + max(get_height(ptr -> left),
get_height(ptr -> right)));
}
}
int tree::double_num(int n){
if (n == 0) {
return 1;
} else {
return 2 * double_num(n - 1);
}
}
bool tree::isOperator(char sym)
{
return ( sym == '+' ||
sym == '-' ||
sym == '*' ||
sym == '/' ||
sym == '^' ||
sym == '(' ||
sym == ')' );
}
int main()
{
string user_input;
tree expr_tree;
cout << "Enter a prefix expression: ";
cin >> user_input;
// Build binary tree and print result
expr_tree.build(user_input);
expr_tree.print();
return 0;
}`

Infix to Postfix to Output (Postfix Calculator) using stacks

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.