>i dont know which one to follow
Try them all, starting with the simplest.
>i dont know if that's the correct way to do it
Why? It sounds reasonable enough to me when that's one of the two established ways to find the canonical form of a boolean expression.
>I was looking for some advice as how to construct the truth-table
>efficiently from the postfix expression.
My advice is to get it working first, then make it fast.
>How do I go about defining a function to get the truth-table?
How would you do it on paper? Before you start writing code, make sure that you understand both the problem you're trying to solve, and the solution you came up with. It's important to understand your own solution before you write it, or you'll just end up debugging a broken program into existence.
Narue
Bad Cop
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
>i assumed that in the infix expression a ! or ' character will always be followed by a variable.
It has to be followed by a value, yes, not necessarily a variable though. The problem you have is that you aren't treating ! as an operator like you should. You're treating it as a first class token rather than a subset of the operators. Consider this:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>
#include <stack>
#include <sstream>
#include <string>
using namespace std;
int priority(const string& token)
{
if (token == "(")
return 3;
else if (token == "!")
return 2;
else if (token == "+")
return 1;
else
return 0;
}
list<string> infix_to_postfix(const list<string>& infix)
{
list<string> result;
stack<string> save;
for (list<string>::const_iterator it = infix.begin(); it != infix.end(); ++it) {
if (isdigit((*it)[0]) || isalpha((*it)[0])) { // Operand
result.push_back(*it);
} else if (*it == ")") { // Nested expression
while (true) {
string item = save.top(); save.pop();
if (item == "(")
break;
result.push_back(item);
}
} else { // Operator
while (!save.empty() && priority(save.top()) > priority(*it)) {
if (save.top() == "(" && *it != ")") // Don't pop paren unless handling paren
break;
result.push_back(save.top()); save.pop();
}
save.push(*it);
}
}
while (!save.empty()) { // Finish up
result.push_back(save.top()); save.pop();
}
return result;
}
void process(const string& expr)
{
list<string> infix;
istringstream in(expr);
copy(istream_iterator<string>(in), istream_iterator<string>(), back_inserter(infix));
list<string> postfix = infix_to_postfix(infix);
copy(postfix.begin(), postfix.end(), ostream_iterator<string>(cout, " "));
cout<<endl;
}
int main()
{
process("! ( A + B )");
process("! A + ! B");
}
Narue
Bad Cop
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401
>I think it involves complex parsing techniques
Eeeeehhh, kind of. If you want, you could set up rules for each operator, but that would require more than simple push/pop access to the stack, and the validation still wouldn't be complete. Your best bet would be a recursive descent parser if you want true validation on the original expression.
A nice, simple alternative is to perform strong error handling while evaluating the expression, but that has a detrimental effect on how well you can report the error.
Narue
Bad Cop
15,460 posts since Sep 2004
Reputation Points: 6,464
Solved Threads: 1,401