so I've working on an assignment converting infix format to postfix format using a stack for the operators, for the digits of the infix notation, the code worked fine, but for the operators, it doesn't work, because the stack is initially empty when I start it, so it can't go into the while loop, but I don't know how to fix this logical error.
void calculator::convertInputIntoPostfix(){
stack S;
for(int i=0;i<mInfixInput.length();i++){
if(mInfixInput[i]>='0' && mInfixInput[i]<='9'){
mPostfixOutput+=mInfixInput[i];
}
else if(isOperator(mInfixInput[i])){
while
(!S.isEmpty()
&&hasHigherPrecedenceThan(S.top(),mInfixInput[i])==true){
mPostfixOutput += S.top();
S.pop();
}
S.push(mInfixInput[i]);
}
}
while(!S.isEmpty()){
mPostfixOutput += S.top();
S.pop();
}
}
bool calculator::isOperator(int c) const
{
return ((c == '+') ||
(c == '-') ||
(c == '*') ||
(c == '/') ||
(c == '^'));
}
bool calculator::hasHigherPrecedenceThan(int aLHS, int aRHS) const
{
if ((aRHS == '+' || aRHS == '-') &&
(aLHS == '*' || aLHS == '/' || aLHS == '^')) {
return true;
}
if ((aRHS == '+' || aRHS == '-' || aRHS == '*' || aRHS == '/') &&
(aLHS == '^')) {
return true;
}
if (aLHS == '^' && aRHS == '^') {
return true;
}
return false;
}
The cases not given above(like () spaces and commas) can be ignored, and the infix is taken by input in the main. the stack is a linked list stack. with the value being an integer.
the outputs for 2+3*3*3(desired answer:233*3*+) I've been getting is 2333**+, as it is not even entering the while loop I've written, it is just storing the values into the stack and at the end outputing it.
2333**+ might be unexpected, but it isn't actually wrong, just wrongly associative.
The way you're computing precedence, you're telling the algorithm that the case where aRHS == '*' && aLHS == '*' is false, i.e. that the operator isn't left-associative. It is. Ditto for all other cases where the operators are equal, except ^, which you are wrongly making left-associative when it is right-associative.
It is customary to use a table rather than an if-else chain when determining predence in this algorithm, and to test for >=, not >, in terms of precedence.
The version of the Dijkstra Shunting-yard algorithm given in Wikipedia has this instead of your condition:
while ((there is a function at the top of the operator stack)
or (there is an operator at the top of the operator stack with greater precedence)
or (the operator at the top of the operator stack has equal precedence and is left associative))
and (the operator at the top of the operator stack is not a left bracket):
pop operators from the operator stack onto the output queue.
Related
I was trying to convert to an infix expression to postfix in c++. I have done coding with simple operators /,*,+,- but I am confused about the logic for assignment operator(=). I know it must be given the lowest precedence but for input like A=B=4 or A=(B=2)*2, how can I decide the precedence. My code is written below. (without implementation for assignment operator).
#include <iostream>
#include <stack>
#include <string>
using namespace std;
// Simply determine if character is one of the four standard operators.
bool isOperator(char character) {
if (character == '+' || character == '-' || character == '*' || character == '/' || character=='=') {
return true;
}
return false;
}
// If the character is not an operator or a parenthesis, then it is assumed to be an operand.
bool isOperand(char character) {
if (!isOperator(character) && character != '(' && character != ')') {
return true;
}
return false;
}
// Compare operator precedence of main operators.
// Return 0 if equal, -1 if op2 is less than op1, and 1 if op2 is greater than op1.
int compareOperators(char op1, char op2) {
if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-')) { return -1; }
else if ((op1 == '+' || op1 == '-') && (op2 == '*' || op2 == '/')) { return 1; }
return 0;
}
int main()
{
// Empty character stack and blank postfix string.
stack<char> opStack;
string postFixString = "";
char input[100];
// Collect input
cout << "Enter an expression: ";
cin >> input;
// Get a pointer to our character array.
char *cPtr = input;
// Loop through the array (one character at a time) until we reach the end of the string.
while (*cPtr != '\0') {
// If operand, simply add it to our postfix string.
// If it is an operator, pop operators off our stack until it is empty, an open parenthesis or an operator with less than or equal precedence.
if (isOperand(*cPtr)) { postFixString += *cPtr; }
else if (isOperator(*cPtr)) {
while (!opStack.empty() && opStack.top() != '(' && compareOperators(opStack.top(), *cPtr) <= 0) {
postFixString += opStack.top();
opStack.pop();
}
opStack.push(*cPtr);
}
// Simply push all open parenthesis onto our stack
// When we reach a closing one, start popping off operators until we run into the opening parenthesis.
else if (*cPtr == '(') { opStack.push(*cPtr); }
else if (*cPtr == ')') {
while (!opStack.empty()) {
if (opStack.top() == '(') { opStack.pop(); break; }
postFixString += opStack.top();
opStack.pop();
}
}
// Advance our pointer to next character in string.
cPtr++;
}
// After the input expression has been ran through, if there is any remaining operators left on the stack
// pop them off and put them onto the postfix string.
while (!opStack.empty()) {
postFixString += opStack.top();
opStack.pop();
}
// Show the postfix string at the end.
cout << "Postfix is: " << postFixString << endl;
return 0;
}
Try giving it the same precedence as the operands, and see what you get:
// Simply determine if character is one of the four standard operators.
bool isOperator(char character) {
if (character == '+' || character == '-' || character == '*' || character == '/') {
//|| character=='='
return true;
}
return false;
}
// If the character is not an operator or a parenthesis, then it is assumed to be an operand.
bool isOperand(char character) {
//for =, treat it wth the same rules as the operands; push to output
if (character == '='){
return true;
}
if (!isOperator(character) && character != '(' && character != ')') {
return true;
}
return false;
}
I am currently writing a Infix to Prefix transfer of a Ternary logic string. In specific, there are only three operands T,F,U and three operators AND, NOT, OR and brackets in the string. Not has higher precedence than AND, OR and AND OR have same precedence. Here's my code changing from original shunting yard algorithm but the translation is not correct for some input
string Infix_To_Prefix(string expression){
string prefix_expression = "";
stack<char> char_stack;
unordered_map<char,int> Precendence;
Precendence['~'] = 2;
Precendence['|'] = 1;
Precendence['&'] = 1;
for(int i=0;i<expression.size();i++)
{
char token = expression[i];
if(isOperator(token))
{
while(!char_stack.empty() and isOperator(char_stack.top()))
{
if(Precendence[token] < Precendence[char_stack.top()])
{
prefix_expression+=char_stack.top();
char_stack.pop();
continue;
}
break;
}
char_stack.push(token);
}
else if(token == '(')
{
char_stack.push(token);
}
else if(token == ')')
{
while(!char_stack.empty() and char_stack.top() != '(')
{
prefix_expression+=char_stack.top();
char_stack.pop();
}
char_stack.pop();
}
else if(isOperand(token))
{
prefix_expression+=token;
}
}
while(!char_stack.empty())
{
prefix_expression+=char_stack.top();;
char_stack.pop();
}
return prefix_expression;
}
In your code, you check the precedence:
if(Precendence[token] < Precendence[char_stack.top()])
{
prefix_expression+=char_stack.top();
char_stack.pop();
continue;
}
In the program you cited in a comment, which is certainly not the original Shunting Yard implementation, the code is
if ((isAssociative(token, LEFT_ASSOC) &&
cmpPrecedence(token, stack.peek()) <= 0) ||
(isAssociative(token, RIGHT_ASSOC) &&
cmpPrecedence(token, stack.peek()) < 0))
{
out.add(stack.pop());
continue;
}
So your test is the same as what the provided code does in the case of right-associative operators, and that is what your code does. If you want your operators to be left-associative, you would need to change the < to <=, as in the code you are adapting.
However, that won't work in the case of unary operators, because unary operators need to be right-associative, at least in the simplistic view normally shown in implementations of the shunting yard algorithm.
It would be more accurate to say that a unary operator should always be pushed onto the stack regardless of the precedence of the operator which precedes it; since it does not take a right-hand operator, it is not competing with the preceding operator, only with the following one. So a unary operator as an incoming token must have higher precedence than any operator on the stack, although a unary operator on the stack may or may not have higher precedence than incoming operator tokens. If the unary operator is the highest-precedence operator, then making it right-associative will have that effect. So I think it is cleaner to special-case unary operators, as you already do with parentheses:
for (char token: expression) {
if (token == '(' || token == '~')
char_stack.push(token);
else if (isOperator(token)) {
while (!char_stack.empty()
and isOperator(char_stack.top())
and Precendence[token] < Precendence[char_stack.top()]) {
prefix_expression+=char_stack.top();
char_stack.pop();
}
char_stack.push(token);
}
else if(token == ')') {
while(!char_stack.empty() and char_stack.top() != '(') {
prefix_expression+=char_stack.top();
char_stack.pop();
}
char_stack.pop();
}
else if(isOperand(token))
prefix_expression+=token;
}
The similarity between the various loops which pop the stacks should suggest a simplification, which is usually implemented in operator-precedence parsers (of which the Shunting Yard is an example).
im studying c++, and im stuck on understanding certain line of code.
bool IsOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/' || C== '$')
return true;
return false;
}
The program im trying to understand scans if the char in string is operator. If yes, get him a number. Inflix to postflix is the problem here.
int IsRightAssociative(char op)
{
if(op == '$') return true;
return false;
}
Here is what i cant understand, where the program finds the '$' char if i write ((3+2)*3-5)*2??
I will attach the whole code for better understanding
#include<iostream>
#include<stack>
#include<string>
using namespace std;
// Function to convert Infix expression to postfix
string InfixToPostfix(string expression);
// Function to verify whether an operator has higher precedence over other
int HasHigherPrecedence(char operator1, char operator2);
// Function to verify whether a character is operator symbol or not.
bool IsOperator(char C);
// Function to verify whether a character is alphanumeric chanaract (letter or numeric digit) or not.
bool IsOperand(char C);
int main()
{
string expression;
cout<<"Enter Infix Expression \n";
getline(cin,expression);
string postfix = InfixToPostfix(expression);
cout<<"Output = "<<postfix<<"\n";
}
// Function to evaluate Postfix expression and return output
string InfixToPostfix(string expression)
{
// Declaring a Stack from Standard template library in C++.
stack<char> S;
string postfix = ""; // Initialize postfix as empty string.
for(int i = 0;i< expression.length();i++) {
// Scanning each character from left.
// If character is a delimitter, move on.
if(expression[i] == ' ' || expression[i] == ',') continue;
// If character is operator, pop two elements from stack, perform operation and push the result back.
else if(IsOperator(expression[i]))
{
while(!S.empty() && S.top() != '(' && HasHigherPrecedence(S.top(),expression[i]))
{
postfix+= S.top();
S.pop();
}
S.push(expression[i]);
}
// Else if character is an operand
else if(IsOperand(expression[i]))
{
postfix +=expression[i];
}
else if (expression[i] == '(')
{
S.push(expression[i]);
}
else if(expression[i] == ')')
{
while(!S.empty() && S.top() != '(') {
postfix += S.top();
S.pop();
}
S.pop();
}
}
while(!S.empty()) {
postfix += S.top();
S.pop();
}
return postfix;
}
// Function to verify whether a character is english letter or numeric digit.
// We are assuming in this solution that operand will be a single character
bool IsOperand(char C)
{
if(C >= '0' && C <= '9') return true;
if(C >= 'a' && C <= 'z') return true;
if(C >= 'A' && C <= 'Z') return true;
return false;
}
// Function to verify whether a character is operator symbol or not.
bool IsOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/' || C== '$')
return true;
return false;
}
// Function to verify whether an operator is right associative or not.
int IsRightAssociative(char op)
{
if(op == '$') return true;
return false;
}
// Function to get weight of an operator. An operator with higher weight will have higher precedence.
int GetOperatorWeight(char op)
{
int weight = -1;
switch(op)
{
case '+':
case '-':
weight = 1;
case '*':
case '/':
weight = 2;
case '$':
weight = 3;
}
return weight;
}
// Function to perform an operation and return output.
int HasHigherPrecedence(char op1, char op2)
{
int op1Weight = GetOperatorWeight(op1);
int op2Weight = GetOperatorWeight(op2);
// If operators have equal precedence, return true if they are left associative.
// return false, if right associative.
// if operator is left-associative, left one should be given priority.
if(op1Weight == op2Weight)
{
if(IsRightAssociative(op1)) return false;
else return true;
}
return op1Weight > op2Weight ? true: false;
}
So if anyone can help i will be very glad :(.
i m trying to Write a function string InfixToPostfix(string infixExpr) that takes as input an expression string in infix notation, and returns a string containing the postfix notation for that expression. The infix notation can have
parenthesis. The program needs to handle these operators ∗,/, %, +, − , <, <=, >=, >, ==, ! =,&&,|| (binary operators only)
Here is the code i am trying.. its running perfect with parenthsis but gives slight wrong output without parenthesis. e.g if input is A+B/C the output should be ABC/+, but instead it gives AB+C/ . please help me spot the error. Thanks
#include<iostream>
#include<stack>
#include<string>
using namespace std;
// Function to convert Infix expression to postfix
string InfixToPostfix(string expression);
// Function to verify whether an operator has higher precedence over other
int HasHigherPrecedence(string operator1, string operator2);
// Function to verify whether a character is operator symbol or not.
bool IsOperator(string C);
// Function to verify whether a character is alphanumeric character (letter) or not.
bool IsOperand(string C);
int GetOperatorWeight(string opt);
bool IsDoubleOperator(char c1, char c2);
int main()
{
string expression;
cout<<"Enter Infix Expression \n";
getline(cin,expression);
string postfix = InfixToPostfix(expression);
cout<<"Output = "<<postfix<<"\n";
return 0;
}
// Function to evaluate Postfix expression and return output
string InfixToPostfix(string expression)
{
// Declaring a Stack from Standard template library in C++.
stack<string> S;
string postfix = ""; // Initialize postfix as empty string.
for(int i = 0;i< expression.length();i++) {
string ex="";
ex+=expression[i];
// Scanning each character from left.
// If character is a delimitter, move on.
if(ex == " " || ex == ",") continue;
// If character is operator, pop two elements from stack, perform operation and push the result back.
else if(IsOperator(ex))
{
while(!S.empty() && S.top() != "(" && HasHigherPrecedence(S.top(),ex))
{
postfix+= S.top();
S.pop();
}
S.push(ex);
}
// Else if character is an operand
else if(IsOperand(ex))
{
postfix +=ex;
}
else if (ex == "(")
{
S.push(ex);
}
else if(ex == ")")
{
while(!S.empty() && S.top() != "(") {
postfix += S.top();
S.pop();
}
S.pop();
}
else if (IsDoubleOperator(expression[i], expression[i+1]))
{
string db="";
string f="";
db=+expression[i];
f=+expression[i+1];
db=db+f;
while(!S.empty() && S.top() != "(" && HasHigherPrecedence(S.top(),db))
{
postfix+= S.top();
S.pop();
}
S.push(db);
i++;
}
}
while(!S.empty()) {
postfix += S.top();
S.pop();
}
return postfix;
}
// Function to verify whether a character is english letter or numeric digit.
// We are assuming in this solution that operand will be a single character
bool IsOperand(string C)
{
if(C >= "A" && C <= "Z") return true;
return false;
}
// Function to verify whether a character is operator symbol or not.
bool IsOperator(string C)
{
if(C == "+" || C == "-" || C == "*" || C == "/" || C== "%")
return true;
return false;
}
// Function to get weight of an operator. An operator with higher weight will have higher precedence.
int GetOperatorWeight(string op)
{
int weight = -1;
if(op=="&&"|| op=="||")
weight = 1;
if(op=="=="|| op=="!=")
weight = 2;
if(op=="<"|| op==">"|| op=="<="|| op==">=")
weight = 3;
if(op=="+"|| op=="-")
weight = 4;
if(op=="/"|| op=="%"|| op=="/")
weight = 5;
return weight;
}
// Function to perform an operation and return output.
int HasHigherPrecedence(string op1, string op2)
{
int op1Weight = GetOperatorWeight(op1);
int op2Weight = GetOperatorWeight(op2);
// If operators have equal precedence, return true if they are left associative.
// return false, if right associative.
// if operator is left-associative, left one should be given priority.
if (op1Weight > op2Weight)
return op1Weight;
else
return op2Weight;
}
bool IsDoubleOperator( char c1, char c2)
{
string db="";
string f="";
db=+c1;
f=+c2;
db=db+f;
if (db=="&&" ||db=="||" || db==">=" || db=="<=" || db=="!=" ||db=="==")
{
//cout<<db;
return true;
}
return false;
}
HasHigherPrecedence(op1, op2) is expected to return non-zero when op1 has a higher precedence (A.K.A. weight) than op2 and zero otherwise. However it returns the maximum of the two ops' weights, which is usually nonzero. You just need to change the function so it returns:
return op1Weight > op2Weight;
Which will be 1 when true and zero when false. This should fix your operator shunting.
I am having some troubles with my if loop.
First off I have I assigned char sign.
void evaluate_ps(istream& input)
{
char sign;
input >> sign;
cout << sign << endl;
check(sign);
}
That prints / so my sign has the value '/'
Then I go to my void check(char operation) function
void check(char operation)
{
if(operation != '-' || operation != '+' ||
operation != '*' || operation != '/')
{
return false;
}
else return true;
}
and it's returning false... WHY!!!! I can't seem to figure this out.
Thanks everyone.
This happens because you are using the || (OR) operator. When operation is / the check operation != '-' returns true. Since || is short circuited, the entire expression returns true.
Change it to && (AND):
if (operation != '-' && operation != '+' &&
operation != '*' && operation != '/')
Another way to write this is:
if (!(operation == '-' || operation == '+' ||
operation == '*' || operation == '/'))
You probably meant all your || to be &&:
if(operation != '-' && operation != '+' &&
operation != '*' && operation != '/')
Otherwise, it will always enter the if-statement since a character will always not equal one of 4 different things.
The if statement is responding to the / not equaling one of the other values
Think about "or" even in a general sense
if blue is not green or is not red or is not blue say nope
you would need to do something like the following:
if (operation != '+' && operation != '-' && operation != '/' && operation != '*') {
return false;
}
return true;
this way its like this
if blue is not green and is not red and is not blue say nope