I'm trying to write a simple program to convert infix notation to prefix and postfix. So far the postfix one works perfectly. However, I can't seem to get the prefix conversion right. I used the shunting yard algorithm for both. Apologies beforehand if my code is a bit unusual (i.e. writing my own stack class instead of using #include, unnecessarily using other things), I have to meet assignment requirements (this is a college assignment). Here's what I've tried so far:
#include<iostream>
#include<string.h>
using namespace std;
const int Max=255;
class Stack
{
private:
char element[Max];
int top;
public:
Stack()
{
top=-1;
}
bool isFull()
{
if(top>=(Max-1)) return true;
else return false;
}
bool isEmpty()
{
if(top==-1) return true;
else return false;
}
bool push(char x)
{
if(!isFull())
{
top++;
element[top]=x;
return true;
}
else
{
cout<<"Stack is full"<<endl;
return false;
}
}
bool pop(char &x)
{
if(!isEmpty())
{
x=element[top--];
return true;
}
else
{
//cout<<"Stack is empty"<<endl;
return false;
}
}
char retrieve()
{
if(!isEmpty())
{
return element[top];
}
else
{
//cout<<"Stack is empty"<<endl;
return ' ';
}
}
};
class Converter
{
private:
public:
Converter(){}
bool isOperator(char x)
{
if(x=='+'||x=='-'||x=='*'||x=='/'||x=='^'||x=='('||x==')') return true;
else return false;
}
bool isOperand(char x)
{
if(x>='0'&&x<='9') return true;
else return false;
}
int Hierarchy(char x)
{
if(x=='+'||x=='-') return 1;
else if(x=='*'||x=='/') return 2;
else if(x=='^') return 3;
else return 0;
}
char*ToPostfix(char infix[])
{
Stack stack1;
char res[20];
int resindex=0;
for(int i=0;i<strlen(infix);i++)
{
if(isOperator(infix[i]))
{
if(infix[i]=='(')
{
stack1.push(infix[i]);
}
else if(infix[i]==')')
{
while(stack1.retrieve()!='(')
{
stack1.pop(res[resindex++]);
}
stack1.pop(res[resindex]);
}
else
{
while(Hierarchy(infix[i])<=Hierarchy(stack1.retrieve()))
{
stack1.pop(res[resindex++]);
}
stack1.push(infix[i]);
}
}
else if(isOperand(infix[i]))
{
res[resindex++]=infix[i];
}
}
while(!stack1.isEmpty())
{
stack1.pop(res[resindex++]);
}
res[resindex]='\0';
return res;
}
char*ToPrefix(char infix[])
{
char res[20];
strcpy(res,strrev(infix));
for(int i=0;i<strlen(res);i++)
{
if(res[i]=='(')
{
res[i]=')';
}
else if(res[i]==')')
{
res[i]='(';
}
}
strcpy(res,ToPostfix(res));
strcpy(res,strrev(res));
return res;
}
};
int main()
{
Converter convert;
char infix[20];
cout<<"Enter infix expression: ";
cin>>infix;
cout<<endl<<"Prefix: "<<convert.ToPrefix(infix)<<endl;
cout<<"Postfix: "<<convert.ToPostfix(infix)<<endl;
return 0;
}
when I try to convert a simple infix notation, i.e. 1*(2+3)/4^5-6, the postfix conversion is right (123+*45^/6-) but the prefix conversion returns the wrong answer (-*1/+23^456) instead of -/*1+23^456. can anyone help?
Actually, both answers are correct because you can switch the order of the division and the multiplication if multiplication comes first in infix. So your wrong answer is correct in this case. However, there is a left to right precedence, so your hierarchy handling is not correct: change else if(x=='*'||x=='/') return 2;.
Related
I wrote a c++ code to convert infix expression to postfix expression using stacks but whenever I try to return the popped value from the stack,it's not returning the string.The returned string is null instead of the original content of the stack.
Do I need to convert it into char first?strong text
input: A+B
output: AB
correct output: AB+
How to return string from member function in c++?
#include<bits/stdc++.h>
using namespace std;
#define MAX 1000
int top=-1;
string stck[MAX];
void push(char data)
{
top++;
*(stck+top)=data;
}
string pop()
{
if(top<0)
{
return "";
}
else
{
top--;
return (*(stck+top));
}
}
bool isstckempty()
{
if(top==-1){
return true;
}
else
return false;
}
int main()
{
string s;
cin>>s;
string ss="";
int len=s.length();
int j=0;
for(int i=0;i<len;i++)
{
if(isalpha(s[i]))
{
ss=ss+s[i];
}
else
{
if(s[i]=='(')
{
push(s[i]);
}
else if(s[i]==')')
{
j=i-1;
while((s[j]!='(')&&(j>0))
{
ss=ss+pop();
j--;
}
ss=ss+pop();
}
else if(s[i]=='+'||s[i]=='-')
{
j=i-1;
while((isstckempty()||s[j]!='(')&&(j>0))
{
ss=ss+pop();
j--;
}
push(s[i]);
}
else if(s[i]=='*')
{
j=i-1;
while((isstckempty()||s[j]!='(')&&(j>0))
{
ss=ss+pop();
j--;
}
push(s[i]);
}
else if(s[i]=='*')
{
j=i-1;
while((isstckempty()||s[j]!='(')&&(j>0))
{
ss=ss+pop();
j--;
}
push(s[i]);
}
}
}
while(!isstckempty){
ss=ss+pop();
}
cout<<ss<<endl;
return 0;
}
Your function pop() returns invalid data when top==0, because you decrement top before indexing the stack, and any array access with a negative index will be undefined. As others have said, don't implement your own stack, use std::stack and more obvious api's.
As my homework I have to write a program that calculates an equation given as string. A part of the program is a function parsing an infix expression into postfix. Here is my code:
void dijkstra(string& s)
{
int i,j=s.size();
stack < char > znaki;
string output=" ";
string znak;
for(i=0; i<j;++i)
{
if((int(s[i])>47&&int(s[i])<58)||s[i]=='.')
{
output+=s[i];
}
else if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')
{
output+=" ";
if(znaki.empty())
{
}
else
{
if((s[i]=='+'||s[i]=='-'))
{
znak=znaki.top();
znaki.pop();
output+=znak;
}
else if(s[i]=='*')
{
if(znaki.top()=='*'||znaki.top()=='/')
{
znak=znaki.top();
znaki.pop();
output+=znak;
}
}
else if(s[i]=='/')
{
if(znaki.top()=='*'||znaki.top()=='/')
{
znak=znaki.top();
znaki.pop();
output+=znak;
}
}
}
znaki.push(s[i]);
}
else if(int(s[i])=='(')
{
znaki.push(s[i]);
}
else if(int(s[i])==')')
{
while(znaki.top()!='(')
{
output+=znaki.top();
znaki.pop();
}
znaki.pop();
}
}
while(znaki.empty()!=true)
{
output+=znaki.top();
znaki.pop();
}
s=output;
}
The problem is that it works in all conditions except equations like 4/6. Any ideas? I've just made requested updates
#include<iostream>
#include<cstring>
using namespace std;
#define MAX 5
struct node
{
char data;
struct node *next;
};
class stack
{
public:
node *top;
stack() //constructor
{
top=NULL;
}
char Top() //return top element without popping
{
return(top->data);
}
int empty() //check empty
{
if(top==NULL)
return(1);
return(0);
}
void push(char x) //push function
{
node *p;
p=new node;
p->data=x;
p->next=top;
top=p;
}
char pop() //pop function
{
node *p;
char x;
p=top;
top=top->next;
x=p->data;
delete(p);
return(x);
}
int precedence(char x) //check precedence of operators
{
if(x=='(')
return 0;
else if(x=='+'||x=='-')
return 1;
else if(x=='*'||x=='/'||x=='%')
return 2;
return 3;
}
void infix_to_postfix(char infix[],char postfix[]);
};
void infix_to_postfix(char infix[],char postfix[])
{
stack s;
char x,token;
int i,j=0;
for(i=0;infix[i]!='\0';i++)
{
token=infix[i];
if(isalnum(token))
postfix[j++]=token;
else
if(token=='(')
s.push(token);
else
if(token==')')
{
while((x=s.pop())!='(')
postfix[j++]=x;
}
else
{
while(s.precedence(token)<=s.precedence(s.Top())&& !s.empty())
postfix[j++]=s.pop();
s.push(token);
}
}
while(!s.empty())
{
x=s.pop();
postfix[j++]=x;
}
postfix[j++]='\0';
}
int main()
{
char infix[30],postfix[30];
cout<<"\nEnter the infix expression::\n";
cin>>infix;
infix_to_postfix(infix,postfix);
cout<<"/nThe equivalent postfix expression is::"<<postfix;
return 0;
}
The above code is giving segmentation fault with gedit in Ubuntu...whereas when the same code when run with turbo C in Windows with the required changes as follows...runs correctly...
#include<stdio.h>
#include<conio.h>
#include<iostream.h>
#include<string.h>
#include<ctype.h>
#include<stdlib.h>
#define MAX 5
struct node
{
char data;
struct node *next;
};
class stack
{
public:
node *top;
stack() //constructor
{
top=NULL;
}
char Top() //return top element without popping
{
return(top->data);
}
int empty() //check empty
{
if(top==NULL)
return(1);
return(0);
}
void push(char x) //push function
{
node *p;
p=new node;
p->data=x;
p->next=top;
top=p;
}
char pop() //pop function
{
node *p;
char x;
p=top;
top=top->next;
x=p->data;
delete(p);
return(x);
}
int precedence(char x) //check precedence of operators
{
if(x=='(')
return 0;
else if(x=='+'||x=='-')
return 1;
else if(x=='*'||x=='/'||x=='%')
return 2;
return 3;
}
void infix_to_postfix(char infix[],char postfix[]);
};
void infix_to_postfix(char infix[],char postfix[])
{
stack s;
char x,token;
int i,j=0;
for(i=0;infix[i]!='\0';i++)
{
token=infix[i];
if(isalnum(token))
postfix[j++]=token;
else
if(token=='(')
s.push(token);
else
if(token==')')
{
while((x=s.pop())!='(')
postfix[j++]=x;
}
else
{
while(s.precedence(token)<=s.precedence(s.Top())&& !s.empty())
postfix[j++]=s.pop();
s.push(token);
}
}
while(!s.empty())
{
x=s.pop();
postfix[j++]=x;
}
postfix[j++]='\0';
}
int main()
{
char infix[30],postfix[30];
cout<<"\nEnter the infix expression::\n";
cin>>infix;
infix_to_postfix(infix,postfix);
cout<<"\nEquivalent postfix expression is::"<<postfix;
getch();
return 0;
}
Why is the problem arising in Ubuntu???
You never check whether your input stack is empty before directly dereferencing top->data. Specifically, this loop:
while(s.precedence(token)<=s.precedence(s.Top())&& !s.empty())
postfix[j++]=s.pop();
s.push(token);
can, and in your case will, dereference an empty stack because you check the empty state after you've already dereferenced the top pointer via s.Top(). You can avoid the inappropriate dereference by using boolean short-circuiting and the proper evaluation order:
while(!s.empty() && s.precedence(token)<=s.precedence(s.Top()))
postfix[j++]=s.pop();
s.push(token);
Input
A*(B+C/(D-A))
Output
The equivalent postfix expression is::ABCDA-/+*
That said, this is extremely brittle. Unless specifically instructed to do so there is no reason you shouldn't be using a custom stack in the first place, as the standard adapter std::stack<> will remove about 90% of this code, and I strongly suggest taking advantage of that.
Finally, this is flat-out bug. Windows or Ubuntu makes no difference. It invokes undefined behavior. That it didn't crash on Windows means you were lucky (or not, since you assumed it was ok because it didn't crash); not right. And in case you're wondering how I noticed this, I saw it in the code, but confirmed it with Valgrind, which confirmed my suspicion immediately.
Using Standard Library for the Heavy Lifting
This gets considerably simpler when you use classes from the standard library for most of the operations, as you can hopefully see below. I kept your algorithm intact, but just used the std::stack adapter and std::string classes for the guts:
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
static int precedence(char x) //check precedence of operators
{
if(x=='(')
return 0;
else if(x=='+'||x=='-')
return 1;
else if(x=='*'||x=='/'||x=='%')
return 2;
return 3;
}
std::string infix_to_postfix(const std::string& infix)
{
std::stack<char> s;
std::string postfix;
for (auto ch : infix)
{
if (isalnum(ch))
postfix.push_back(ch);
else if (ch == '(')
s.push(ch);
else if(ch == ')')
{
while (!s.empty())
{
ch = s.top();
s.pop();
if (ch == '(')
break;
postfix.push_back(ch);
}
}
else
{
while(!s.empty() && precedence(ch)<=precedence(s.top()))
{
postfix.push_back(s.top());
s.pop();
}
s.push(ch);
}
}
while(!s.empty())
{
postfix.push_back(s.top());
s.pop();
}
return postfix;
}
int main()
{
const char infix[] = "A*(B+C/(D-A)+2*(E-F))";
cout << "\nThe equivalent postfix expression is: " << infix_to_postfix(infix);
return 0;
}
Input
A*(B+C/(D-A)+2*(E-F))
Output
The equivalent postfix expression is: ABCDA-/+2EF-*+*
Here i have a code for converting Infix To Postfix using Stack
the code compiled without errors but my problem is When I enter any infix e.g A+B i got a postfix of AB without the operators or parenthesis i couldn't solve this problem and i have an exam tomorrow please save me and tell me What i am missing here and thanks a lot.....
#include <iostream>
#include <string.h>
using namespace std;
struct stack
{
int ptr;
char arr[50];
stack()
{
ptr=0;
}
char top()
{
return arr[ptr];
}
void push(char ch)
{
ptr++;
arr[ptr]=ch;
}
void pop()
{
ptr-- ;
}
};
void Convert(char[50],char[50]);
bool IsOperand(char);
bool TakesPrecedence(char,char);
void main()
{
char Reply;
do
{
char Infix[50],Postfix[50]="";
cout<<"Enter an Infix expression: "<<endl;
cin>>Infix;
Convert(Infix,Postfix);
cout<<"The equivalent postfix expression is: "<<endl<<Postfix<<endl;
cout<<endl<<"Do another (y/n)? ";
cin>>Reply;
}
while (Reply =='y');
}
void Convert(char Infix[50],char Postfix[50])
{
stack OperatorStack;
char TopSymbol,Symbol;
int L;
for(unsigned k=0;k<strlen(Infix);k++)
{
Symbol=Infix[k];
if (IsOperand(Symbol))
{
L=strlen(Postfix);
Postfix[L]=Symbol;
Postfix[L+1]='\0';
}
else
{
while ( OperatorStack.ptr && TakesPrecedence(OperatorStack.top(),Symbol))
{
TopSymbol= OperatorStack.top();
OperatorStack.pop();
L=strlen(Postfix);
Postfix[L]=TopSymbol;
Postfix[L+1]='\0';
}
if( OperatorStack.ptr && Symbol==')')
OperatorStack.pop();
else
OperatorStack.push(Symbol);
}
}
while(OperatorStack.ptr)
{
TopSymbol=OperatorStack.top();
OperatorStack.pop();
L=strlen(Postfix);
Postfix[L+1]='\0';
}
}
bool IsOperand(char ch)
{
if((ch >='a' &&ch <= 'z') ||(ch >='A' &&ch <= 'Z')||(ch >='0' &&ch <= '9'))
return true;
else
return false;
}
bool TakesPrecedence(char OperatorA,char OperatorB)
{
if(OperatorA='(')
return false;
else if(OperatorB='(')
return false;
else if(OperatorB=')')
return true;
else if(OperatorA='^' && (OperatorB='^'))
return false;
else if(OperatorA='^')
return true;
else if(OperatorB='^')
return false;
else if(OperatorA='*' || (OperatorA='/'))
return true;
else if(OperatorB='*' || (OperatorB='/'))
return false;
else
return true;
}
Pretty sure
if(OperatorA='(')
and all other should be
if(OperatorA=='(')
But my main advice is for you to start using a debugger. This could have easily been spotted during debugging. I can't stress enough how important knowing how to debug is.
I wrote this program and it supposed to test for the correct use of the three grouping symbols "(",")";"[","]"; and "{","}". It is using the array implementation of the stacks and supposed to evaluate if it is good string or a bad string. For example: (a+b), [(a-b)+c] would be good and )a+b( etc. would be bad string. When i run the program i get only one error. I thought i am missing a semi-colon or something, but after looking through the code several time,i can't find it. Maybe i got tunnel vision. Can you please see what the problem here is? This is the error: project1.cpp:41: error: expected initializer before 'while'.
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
const int DefaultListSize = 100;
typedef char Elem;
class Astack {
private:
int size;
int top;
Elem *listArray;
public:
Astack (int sz = DefaultListSize)
{size = sz; top= 0; listArray = new Elem[sz];}
~Astack() {delete [] listArray;}
void clear() {top=0;}
bool push(const Elem& item) {
if (top == size) return false;
else {listArray[top++] = item; return true;}}
bool pop(Elem& it) {
if (top==0) return false;
else {it = listArray[--top]; return true;}}
bool topValue(Elem& it) const {
if (top==0) return false;
else {it = listArray[top-1]; return true;}}
bool isEmpty() const {if (top==0) return true;
else return false;}
int length() const{return top;}
}; //end of class Astack
Astack s;
const string LEFTGROUP="([{";
const string RIGHTGROUP=")]}";
int main()
while (!EOF) {
while (!EOL) {
ch = getc();
if (ch == LEFTGROUP[0]) {
s.push(ch);
}
if (ch == LEFTGROUP[1] {
s.push(ch);
}
if (ch == LEFTGROUP[2] {
s.push(ch);
}
} //checking for openers
while (!EOL) {
ch = getc();
if (s.top() == LEFTGROUP[0]) {
if (ch == RIGHTGROUP[0]) {
s.pop();
}
}
if (s.top() == LEFTGROUP[1]) {
if (ch == RIGHTGROUP[1]) {
s.pop();
}
}
if (s.top() == LEFTGROUP[2]) {
if (ch == RIGHTGROUP[2]) {
s.pop();
}
}
if (!s.empty()) {
cout<<"Bad String."<<endl;
else {
cout<<"Good String."endl;
}
}
}
return 0;
You forgot a { at the beginning of int main(). You should also end with }
int main(){
//your while code
return 0;
}