I have little bit modified your code and it is working. The only drawback is that it cannot handle more than one digit nos. at any point of time during calculation.
I have commented the code and am sure that you will understand it.
Though, I will explain it completely in a short while.
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
//stringify just converts a int to string
inline string stringify(double x)
{
ostringstream o;
if (!(o << x))
cout<<"Stringify::Bad Conversion";
return o.str();
}
int postfix(string s)
{
cout<<"New Postfix:"<<s<<endl; // for debug
int a, b;
if (s.length() == 3 && !isdigit(s[s.length()-1] && isdigit(s[s.length()-2])))
{
cout<<"Inside If:"<<endl; // for debug
a = s[0]-48;
b = s[1]-48;
cout<<"eval "<<a<<" "<<s[2]<<" "<<b<<endl;
switch (s[2])
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
default :
cout<<"bad input\n";
}
}
else
{
cout<<"theElsepart:"<<s.substr(1,3)<<endl;//ForDebugging
//This needs explaination:
//Lets say the the expression was "262/3*+"
//Now, I am replacing the "62/" to its value by
//calling postfix() again on "62/"
return postfix(s.replace(1,3,stringify(postfix(s.substr(1,3)))));
}
return 0; // This return is for debug
}
int main()
{
cout<<postfix("263+*");
}
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140
Ignore the above post please.
Postfix notation is evaluated from left to right.
What your algo was: if say the expression is 22/2+1+, you were calculating 2/2+1 first. which ofcourse dont make any sense.
Rather you should calculate 22/ first and then replace it in the main expression by its value(which is 1).
So, here is your code with few modification. Comments has been added. If you need more explanation, reply here. The only draw back is that at no point of time, the value of any expression exceed one digit.
#include<iostream>
#include<string>
#include<sstream>
using namespace std;
//stringify just converts a int to string
inline string stringify(double x)
{
ostringstream o;
if (!(o << x))
cout<<"Stringify::Bad Conversion";
return o.str();
}
int postfix(string s)
{
cout<<"New Postfix:"<<s<<endl; // for debug
int a, b;
if ( !isdigit(s[2]) && isdigit(s[0]))//check if the first three charactrs can be evaluated
{
//now if the length is greater than three, replace the first three with the value
if (s.length() > 3 )
return postfix(s.replace(0,3,stringify(postfix(s.substr(0,3)))));
else if (s.length()==3)//elseif the length is 3
{
cout<<"Inside If:"<<endl; // for debug
a = s[0]-48;
b = s[1]-48;
cout<<"eval "<<a<<" "<<s[2]<<" "<<b<<endl;
switch (s[2])
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
default :
cout<<"bad input\n";
}
}
else //just a error check in case ;)
cout<<"Too short to evaluate(min is 3)";
}
else
{
cout<<"theElsepart:"<<s.substr(1,3)<<endl;//ForDebugging
//This needs explaination:
//Lets say the the expression was "262/3*+"
//Now, I am replacing the "62/" to its value by
//calling postfix() again on "62/"
return postfix(s.replace(1,3,stringify(postfix(s.substr(1,3)))));
}
return 0; // This return is for debug
}
int main()
{
cout<<postfix("22/2+1+");
}
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140
The only draw back is that at no point of time, the value of any expression exceed one digit.
unfortunately then it would fail to evaluate his original expression of
264+* ...right?
Agni
Practically a Master Poster
655 posts since Dec 2007
Reputation Points: 431
Solved Threads: 116
Yes, of course.
But I cannot help it. My job was to modify his code, not write it.
This catch is even in his original code so I cannot help. If he shows some efforts regarding multi-digits evaluation, I will surely help.
Using stack was a good idea to target such issue but then, he want it do recursively.:icon_smile:
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140
>I do not understand some of the things you guys are talking about
I was talking about stack, which is in a way, exactly what you have done.
Stacks can be thought of as an array in which the last item which goes in will be the last item which comes out. It is more or less the same thing which you have done.
Mind you, I have not read your code.
Regarding your error handling mechanism you have various method:
1.The very best is to use exeptions, They are error handling mechanism of C++. Research about them. Its good to start using them.
2. cout a error and quite the program by using exit(1)[defined under <cstdlib>]. This will cause termination of the program.
I prefer you opt choice 1. and learn about exceptions. After you know about exceptions, you can read the following article about Detecting and responding to division by zero http://www.deitel.com/articles/cplusplus_tutorials/20060325/
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140
Returning by string means that you will again have to convert each value you get to integers(although, you can always define a inline function for that like I did). But this was the best method provided exceptions were not invented. Returning by void will be a crime.
Doing things without exception handling will be like following the I-dont-want-to-learn-new-things-but-screw-the-old-one way.
But a slight caution: exceptions are also a good way to make your code unportable in a sense that not most of people(who will study your code) will not catch your exceptions; That bothers you if you were designing a library.
So be sure to issue a exit(1) just after you throw an exception. These thing would make sense when you read about exception handling
Wish you luck!!
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140
Hmm,
>For example in my function the part of my switch that handles division would look like.......
Well, it is not looking good!.
The try block should be in the code which runs your function i.e. the main()
The general layout should be like this
{
//inside your evaluative function
case '/':
if (b == 0)
{
throw 0;
exit(0);//in case someone don't catch your exception
}
return a / b;
....
...
....
....
//end of your evaluative function
}
int main()
{
while (1)
{
try
{
//do all the input output code here,
//
//
break;//this will get you out of the loop if no exception is thrown
}
catch (int i)
{
if (i==0)
cout<<"Error! div by zero";
}
//flow returns here when a exception is thrown
//thus get back to the start of the loop again
}//ending while(1)
}
>Does catch need to be a member of my class or would this be a global thing. (I don't exactly know where to put this in my code.)
catch{} is a global thing, should be put just after the try{} block
>Do I still need exit(1) somewhere? Ideally I would like it to deliver my error message then return to the menu instead of exiting the program if possible.
Useexit(1) just after you throw the exception. This will ensure that your program at least terminates(rather than screwing your machine resources) if the exception has not been handled. Although, my compiler (g++)r print a error message if the exceptions are thrown but not catched. But then, it is implementation dependent. So it is better to put a exit(1);
>also is returning by void a crime because it is bad practice or because it would >not work?
I exclaimed that it is a crime in your case as it would imply that you will have to cout everything in the evaluative function, which is bad.
>Ideally I would like it to deliver my error message then return to the menu instead of exiting the program if possible.
Yes, the code segment I gave will do exactly the same thing. Lets see how:
If the exception is not encountered any function inside the try block, the program will eventually meet the break; statement and thus the outer while loop will terminate. If the exception is catched, the program flow returns to the end of the catch{} block hence the Loop starts again.
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140
>It does use an exception though.
But it is not using the way it should. I guess my last post was of no use.
Do you know why exceptions were invented? To avoid checking the return value of each function for errors. And look what you are doing. You are still checking if(eval.get_bad_divisor()) in you main().So what is the point in using exceptions. And moreover, you are using the try-catch block inside the definition of a function that throws the exception.
I think you should read my last post again.
Well, I don't mind if you use the old return-value check approach, but then, please don't use (flawed) exception handling mechanism for just the sake of using it.
Another point: dont use #define MAX_SIZE 50
use const int MAX_SIZE=50; instead. Here is why: http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.7
I hope you understand my point about exceptions. Here is a good tut for you: http://www.ozzu.com/cpp-tutorials/tutorial-exceptions-t86515.html
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140
>>I don't understand your complaint about using it inside the function
Ok, I am rather guilty, fine?
So, I think I would need to explain it further.
Look, You should throw an exception whenever you encounter a error in any piece of your code by using throw anumber whenever you encounter a error. But, use the try-catch block in the calling code of the function. Not when throwing exception. Getting it?
In short, you should write the try-catch block in main() and not in postfix(). Got it?
You should issue a throw 0 in postfix but catch it in main()
Phew!
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140
>That makes some sense but I thought the catch needed to be placed just after the >try in the code.
Yes you are right. So that what I said:
.
.
.
{//in post fix
if (somecondition)
throw 0;//look, i hv not used any try{}
.
.
.
}//end of postfix
int main()
{
while (1)
{
try//here i use try
{
//somecode
postfix();
break;
}
catch (int i)//and catch just after try{}
{
if (i==0)
cout<<"Erorror";
}
}
}
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140
Better, but Still not got it!
No problem. I will try to explain again:
See, the whole story of exception is to eradicate the need for checking anything in main() as you are doing
try{
if (eval.get_bad_divisor()){ //<<<to eradicate this
throw 1;
} else {
cout<<pf_eq<<" = "<<answer<<".\n";
}
So now, you have already thrown a exception while dealing with postfix(), right?
I mean, you have already thrown the exception in the postfix() function, so you don't need to throw it again in main()[and neither there is need to check if (eval.get_bad_divisor()) ]
First of all, try{} block should contain all those function call which can potentially throw an exception. In your case it is postfix(). So you should include the postfix() in the try block. Now the code should appear like this:
case 1: // evaluate a postfix eq
cout<<"Enter postfix expression: ";
cin.clear();
cin>>pf_eq;
try{
answer = eval.postfix(pf_eq);
}
catch (int q){
if (q == 1){
cout<<"Invalid division by !\n";
}
}
break;
//rest of your code..........
}
Lets see what will happen in the above code:
You are calling postfix() in a try block, right? So, either two things can happen:
1.The postfix() don't encounter any div-zero error: In this case, no exception will be thrown by postfix() hence the try block will be executed fully and the control will return directly to Line13 (overlooking the catch{})
2.If postfix() emits a exception, the control will be (no matter where it was earlier) directly passed to the catch block at Line9 and will issue a error and continue from Line13
After Line13, your program will run as usual. So no need of the ugly eval.get_bad_divisor()
Got it?
siddhant3s
Practically a Posting Shark
816 posts since Oct 2007
Reputation Points: 1,486
Solved Threads: 140