Link to home
Start Free TrialLog in
Avatar of v8forlyfe
v8forlyfe

asked on

Infix to postfix C++

Hey, I'm trying to write a program that reads an infix expression from a file, converts it to postfix, and prints it out.  I am probably at least 70% done but am stuck on a few key things:
1)Making sure my constructor is serving it's purpose, not sure why it is supposed to have an arg
2)printing my posfix and infix correctly
3)setting up my main() correctly

If someone could just run through these things to get me un-stuck I'd appreciate it.  Also, I havn't had a chance to check my logic in my actual convert method because I havn't been able to print anything yet.  It only prints nonsense.  That's why the more complicated parts are commented out.  Heres the code:



// Specification file for InfixToPostfix.h

#ifndef H_InfixToPostfix
#define H_InfixToPostfix
#include <iostream>
#include <string>
#include <stack>

using namespace std;

class infixToPostfix
{
public:
	void convertToPostfix();
	bool precedence(char newop, char old);
	void getInfix(string);
	void showInfix();
	void showPostfix();
	infixToPostfix(string = ""); //Default constructor
		
private:
	string  ifx;
	string  pfx;
};

infixToPostfix::infixToPostfix(string rtIfx)
{
ifx = rtIfx;
}
void infixToPostfix::getInfix(string a)
{
ifx = a;
}
void infixToPostfix::showPostfix()
{
cout << pfx;
}
void infixToPostfix::showInfix()
{
cout << ifx;
}
void infixToPostfix::convertToPostfix()
{
string postfixString;
stack<char> optrStk;
char item;

for(int i = 0; i <= ifx.length(); i++)
{
	if(ifx[i] == '*' || ifx[i] == '/' || ifx[i] == '+' || ifx[i] == '-')
	{
		if(!optrStk.empty())
		{
			item = optrStk.top();
			if((precedence(ifx[i], item)) == true)
			optrStk.push(ifx[i]);
			else if((precedence(ifx[i], item)) == false)
			//cout << item;
			optrStk.pop();
			optrStk.push(ifx[i]);
		}
		if(optrStk.empty()== true)
		{
			optrStk.push(ifx.at(i));
		}
	}		
// 	else if(ifx[i] == '(')
// 	{
// 		optrStk.push(ifx[i]);		
// 	}
// 	else if(item == ')')
// 	{
// 		while(optrStk.top() != '(')
// 		{
// 		item = optrStk.top();
// 		optrStk.pop();
// 		cout << item;
// 		}
// 	optrStk.pop();
//	}			
	else
	{
		//cout << ifx[i];
	}
}
}
bool infixToPostfix::precedence(char newop, char old)
{
bool higher;
if(newop == '*' || newop == '/' && old == '+' || old == '-')
	higher = true;
else if(newop == '+' || newop == '-' && old == '*' || old == '/')
	higher = false;
else if(newop == '*' || newop== '/' && old == '*' || old == '/')
	higher = true;
else if(newop == '+' || newop == '-' && old == '+' || old == '-')
	higher = true;
return higher;
}
	


#endif

#include <iostream>
#include <fstream>
#include <string>
#include "infixToPostfix.h"

using namespace std;

int main()
{

	infixToPostfix  InfixExp;
	string infix;

	ifstream infile;

	infile.open("Data.txt");

	if(!infile)
	{
		cout<<"Cannot open input file. Program terminates!!!"<<endl;
		return 1;
	}
	else{
	getline(infile,infix);
	InfixExp.getInfix(infix);
	//InfixExp.showInfix();
	

	
	InfixExp.convertToPostfix();// perform conversion


	InfixExp.showPostfix();


	infile.close();
	}

	return 0;
}

Open in new window

SOLUTION
Avatar of lucky_james
lucky_james
Flag of India image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of v8forlyfe
v8forlyfe

ASKER

Hey thanks for the help so far, sorry for my vagueness.  I need to "get" the infix expression from the file and set it to ifx if that makes sense, and I'm not sure if that part is doing it's job or not, because it's printing out a bunch of binary crap.  Question marks, random jargon I don't understand, nothing from the actual file which only contains infix expressions.

And as far as my main goes, you answered part of that already, I just wanted to make sure my functions were being called correctly and were in the right order.
Avatar of phoffric
1. If you do not know what the purpose of the argument to the constructor is, then why did you include an argument in the first place?
2. >> printing my posfix and infix correctly
3 >> setting up my main() correctly
Could you give specifics as to what is wrong?

>> I haven't had a chance to check my logic in my actual convert method because I haven't been able to print anything yet.  It only prints nonsense.
Maybe there is something wrong with your Data.txt file.

Did you write the posted code yourself? If so, then you probably know best which lines would be good to look at most closely. To do that, you can add cout statements to see at what point the "nonsense" begins to appear. An easier approach is to just step through the program with your debugger and check the values as they change from line to line.

If you have specific questions, just ask.

I did notice that getInfix() and your constructor are both setting ifx. Did you notice that?
Oh, I didn't see the first post. Sorry about any redundancies.
It's alright.  I wrote 95% of the code from scratch, the other 5% was given to me as a starting point, hence the arg in the constructor that I don't quite know what to do with, but I think I've taken care of that problem.

I did step through the program, that's why blocks are commented out because the cause the error given in my first and second post.  The showInfix() in my main for instance prints out this kind of stuff "content.xml¿VmO¿0¿¿_e¿¿R" and I don't know why, that's the part I'm stuck at and that's why I posted, because I'm completely lost.


SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
my input file nomally has about 5 infix ops, but right now it is only as follows until I can get this debugged:
A+B-C

Good catch on the item thing, it is set only when it sees one of the first 4 operands.  I changed all cases of "item" with "ifx[i]" when checking for parenthesis, does that look like it would help?
Not sure if I updated my code exactly as you did. (If doing changes, feel free to post again your latest code.)
For what you gave, A+B-C, the program prints out ABC, but I don't see all the garbage you were talking about. (nor are there operators). I don't see where you are printing out operators. Why not make changes to do this and re-post.
I'm leaving now for about 2 hours.
Ok thanks for the help so far, the debugging tip you gave me has helped a lot already.  I can now print out a correct postfix op!  I'll update after I get stuck again, but for now I can keep going on my own for a bit.
great!! do let us know in case you are stuck somewhere...
Hit a new obstacle.  Now that my program is working fine without parenthesis (had to find a few other bugs but those should be good now) I uncommented my part that deals with them.  Only problem is, when I try to run the program, it gives me a segmentation error.  Here's the code.  It is somewhere in that short segment.


else if(ifx[i] == '(')
	{
		optrStk.push(ifx[i]);		
	}
	else if(ifx[i] == ')')
	{
		while(optrStk.top() != '(')
		{
		item = optrStk.top();
		optrStk.pop();
		cout << item;
		}
	optrStk.pop();
	}

Open in new window

post your full code...
Since I don't have all your code changes or your test code, I'll just give you these suggestions. In precedence() cout the input variables and see if they make sense. Then add an else statement and if you get there, then cout an error message and either exit or return some value for higher that might make sense for you.
I mean if its possible.....and also the input your are passing.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
re: operator precedence
Another table driven approach is to define the attributes to include:
- number of operands (unary, binary, ternary)
- precedence (just an integer)
- associativity (LtoR or RtoL)
As you add more operators, the matrix becomes harder to maintain (works fine for the above 4x4 case).
You could use a multimap to hold the operator and its attributes.
I'm pretty sure my precedence method is working correctly now, if you input any infix without parenthesis (because that part is creating a segfault) it will output correctly.  In the commented part of the convert method, it is somewhere in the while loop i think.

Also, I still don't know why my file reader doesn't work, but I don't care about that as much right now.
// Specification file for InfixToPostfix.h

#ifndef H_InfixToPostfix
#define H_InfixToPostfix
#include <iostream>
#include <string>
#include <stack>

using namespace std;

class infixToPostfix
{
public:
	void convertToPostfix();
	bool precedence(char newop, char old);
	void getInfix(string);
	void showInfix();
	void showPostfix();
	infixToPostfix(string = ""); //Default constructor
		
private:
	string  ifx;
	string  pfx;
};

infixToPostfix::infixToPostfix(string rtIfx)
{
ifx = rtIfx;
}
void infixToPostfix::getInfix(string a)
{
ifx = a;
}
void infixToPostfix::showPostfix()
{
cout << pfx;
}
void infixToPostfix::showInfix()
{
cout << ifx;
}
void infixToPostfix::convertToPostfix()
{
string postfixString;
stack<char> optrStk;
char item;

for(int i = 0; i <= ifx.length(); i++)
{
	if(ifx[i] == '*' || ifx[i] == '/' || ifx[i] == '+' || ifx[i] == '-')
	{
		if(!optrStk.empty())
		{
			item = optrStk.top();
			if((precedence(ifx[i], item)) == true)
			{
			cout << item;
			optrStk.pop();
			optrStk.push(ifx[i]);
			}
			else if((precedence(ifx[i], item)) == false)
			optrStk.push(ifx[i]);
		}
		if(optrStk.empty())
		{
			optrStk.push(ifx[i]);
		}
	}	
// 	if(ifx[i] == '(')
// 	{
// 		optrStk.push(ifx[i]);		
// 	}
// 	if(ifx[i] == ')')
// 	{
// 		while(optrStk.top() != '(')
// 		{
// 		ifx[i] = optrStk.top();
// 		optrStk.pop();
// 		cout << item;
// 		}
// 	optrStk.pop();
// 	}			
	else
	{
		cout << ifx[i];
	}
	
}
while(!optrStk.empty())
{
item = optrStk.top();
cout << item;
optrStk.pop();
}
}
bool infixToPostfix::precedence(char newop, char old)
{
bool higher;
if((newop == '*' || newop == '/') && (old == '+' || old == '-'))
	higher = false;
else if((newop == '+' || newop == '-') && (old == '*' || old == '/'))
	higher = true;
else if((newop == '*' || newop== '/') && (old == '*' || old == '/'))
	higher = true;
else if((newop == '+' || newop == '-') && (old == '+' || old == '-'))
	higher = true;
return higher;
}
	


#endif

include <iostream>
#include <fstream>
#include <string>
#include "infixToPostfix.h"

using namespace std;

int main()
{

	
	string infix = "A*B+C";

	ifstream infile;

	infile.open("Data.txt");

	if(!infile)
	{
		cout<<"Cannot open input file. Program terminates!!!"<<endl;
		return 1;
	}
	else{
	//getline(infile,infix);
	infixToPostfix  InfixExp(infix); 
	InfixExp.showInfix();
	

	
	InfixExp.convertToPostfix();// perform conversion


	//InfixExp.showPostfix();


	infile.close();
	}

	return 0;
}

Open in new window

Oh, change the commented-out ifx[i] to item = optrStk.top(); otherwise it doesn't make sense.
Output from below test driver..
Why a space in postfix expression?
First result is XY+Z- (removed space)
Letting X=A,  Y=B*C, Z=D*E*F, why isn't 3rd result of the same form as 1st result?
i.e., ABC*+Z-
==================
X+Y-Z
XY+Z -

D*E*F
DE*F *

A+B*C-D*E*F
ABC*DE*F *-+

X*Y+Z
XY*Z +

A*B*C+D*E*F
AB*C*DE*F *+

A+B*C
ABC *+

Z+A*B-C/D*E+F*G
ZAB*CD/E*FG *+-+

A+(B-C)
A(B+C) -
==================
void test(string str) {
   infixToPostfix  InfixExp1(str);
   InfixExp1.showInfix();
   InfixExp1.convertToPostfix();// perform conversion
   cout << endl << endl;
}
int main()
{
   test("X+Y-Z");
   test("D*E*F");
   test("A+B*C-D*E*F"); // X=A,  Y=B*C, Z=D*E*F

   test("X*Y+Z");
   test("A*B*C+D*E*F");

   test("A+B*C");
   test("Z+A*B-C/D*E+F*G");
   test("A+(B-C)");  
   return 0;
}

Open in new window

>> Oh, change the commented-out ifx[i] to item = optrStk.top(); otherwise it doesn't make sense.
Maybe, never mind previous post. I didn't comment anything out.
What line should I comment out so that  we're in sync?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
From the interchange, it appears that I provided assistance that was used by the author.
I recommend "Accept one or more Expert posts as the answer".

split: 3/4th for phoffric (180 points); 1/4th for lucky_james (70 points)
Accept: http:#29750309 (lucky_james)

Accept: http:#29751296
"An easier approach is to just step through the program with your debugger and check the values as they change from line to line."
  -- to which author says (http:#29754124): "Ok thanks for the help so far, the debugging tip you gave me has helped a lot already."

Accept: http:#29752708
"line 71: else if(item == ')')
 Where is item set?"
  -- to which author says (http:#29753175 ): "Good catch on the item thing"

Accept: http:#29763660
   pfx is not being set
   but indexes start at 0
alright, i'll do that, i fixed it when i redid all of my logic, so i didn't know who to give it to, i'll do what you said though!
Ah, you started over for the better. That shows a lot of extra insight!