-1
#include<bits/stdc++.h>
using namespace std;

int prec(char c){
    if(c=='^'){
        return 3;
    }else if(c=='*' || c=='/'){
        return 2;
    }else if(c=='+' || c=='-'){
        return 1;
    }

    return -1;
}

string infixToPostfix(string );

int main(){
    string s = "(a-b/c)*(a/k-l)";

    cout<<infixToPostfix(s);

    return 0;
}

string infixToPostfix(string s){
    stack<char> st;
    string res = "";

    for(int i=0;i<s.length();i++){
        if((s[i]>='a' && s[i]<='z') || (s[i]>='A' && s[i]<='Z')){
            res+=s[i];
        }else if(s[i]=='('){
            st.push(s[i]);
        }else if(s[i]==')'){
            while((!st.empty()) && st.top()!='('){
                res+=st.top();
                st.pop();
            }
            if(!st.empty()){
                st.pop();
            }
        }else{
            while((!st.empty()) && prec(st.top())>prec(s[i])){
                res+=st.top();
                st.pop();
            }
            st.push(s[i]);
        }

        while(!st.empty()){
            res+=st.top();
            st.pop();
        }

    }
        return res;
}

As you can see I'm trying to convert infix notation to postfix notation but the output is not coming as expected. I couldn't even find any syntax error so there's a high chance that there is some logical error.

Expected Output:

abc/-ak/l-*

Actual Output:

(a-b/c*(a/k-l

I have blown my brain off trying to find the error and I still haven't. Please help me solve the issue.

  • Recommendation: Step through the code line by line with the debugger that came with your development tools and keep an eye out for where the program does something unexpected like string the wrong value or taking the wrong path. The unexpected is a bug in the program or your expectations and either one needs to be fixed. – user4581301 Sep 15 '22 at 17:48
  • 1
    Side note: Don't mix `#include` and `using namespace std;`. It's recommended that you use neither ([why](https://stackoverflow.com/q/31816095/4581301) and [why](https://stackoverflow.com/q/1452721/4581301)), but when you use them together thing can get really messy very quickly. If you don't already know what to look for, you'll waste hours debugging nigh-inscrutable diagnostics and behaviours. – user4581301 Sep 15 '22 at 17:51
  • Note `+, -, *, /` are left to right associative and `^` is right to left. You need to consider this also during postfix conversion. – Aamir Sep 15 '22 at 18:00
  • `#include` -- Stop using online coding websites to learn C++. A good C++ book would *never* show usage of this header. – PaulMcKenzie Sep 15 '22 at 18:03
  • 1
    *I couldn't even find any syntax error* -- You wasted your time doing this to find a logical error -- if there were syntax errors, the compiler and linker would not have produced a program for you to run. – PaulMcKenzie Sep 15 '22 at 18:06

1 Answers1

0

Define two precedence tables, called outstack for operator when they are outside the stack and instack for operator when they are inside the stack.

If any operator is left to right assosiative increase the precedence from outstack to instack. If it is right to left decrease the precedence.

Op outstack pre instack pre
+ - 1 2
* / 3 4
^ 6 5
( 7 0
) 0 x

The program below uses this logic to convert an infix expression to postfix expression.

#include <iostream>
#include <string>
#include <stack>
#include <map>
#include <vector>

// For left to right associative operator, precedence increase from out to in
// For right to left associative operator (like ^), precedence decrease from out to in

// Outside stack precedence
std::map<char, int> precedenceOutStack {
    {'(', 7}, 
    {')', 0},
    {'*', 3}, 
    {'/', 3},
    {'+', 1}, 
    {'-', 1},
    {'^', 6},
};

// Inside stack precedence
std::map<char, int> precedenceInStack {
    {'(', 0}, 
    {'*', 4}, 
    {'/', 4},
    {'+', 2}, 
    {'-', 2},
    {'^', 5},
};

int getOutPrecedence(char c) {
    if(precedenceOutStack.count(c) > 0) {
        return precedenceOutStack[c];
    } else {
        return 0;
    }
}

int getInPrecedence(char c) {
    if(precedenceInStack.count(c) > 0) {
        return precedenceInStack[c];
    } else {
        return 0;
    }
}

std::string infixToPostfix(std::string infix) {
    std::string postfix {};
    std::stack<char> stk;

    size_t i {};
    // loop through the input string
    while(infix[i]) {
        // if its an operand add it to postfix
        if(std::isalpha(infix[i])) {
            postfix.push_back(infix[i++]);
        } else {
            if(!stk.empty()) {
                auto outPrec = getOutPrecedence(infix[i]);
                auto inPrec = getInPrecedence(stk.top());

                // check the out precedence of input char with in precedence of stack top
                // if its greater push the operator to stack
                if( outPrec > inPrec ) {
                    stk.push(infix[i++]);
                }
                // else if it is less, append the operator from top of stack to postfix
                else if(outPrec < inPrec ) {
                    postfix.push_back(stk.top());
                    stk.pop();    
                }
                // only '(' and ')' has equal out and in precedence, ignore them 
                else if(outPrec == inPrec) {
                    stk.pop();
                    ++i;
                }
            } else {
                stk.push(infix[i++]);
            }
        }
    }

    // pop out remaining opreator from the stack and append them to postfix
    while(!stk.empty()) {
        postfix.push_back(stk.top());
        stk.pop();
    }
    return postfix;
}

int main()
{
    std::vector<std::string> inputs {
        "(a-b/c)*(a/k-l)"  // abc/-ak/l-*
    };

    for(const auto& s : inputs) {
        std::cout << "Infix: " << s << " -- ";
        std::cout << infixToPostfix(s) << std::endl;
    }
}
Aamir
  • 1,974
  • 1
  • 14
  • 18
  • If you are satisfied with the answer, please accept it so that we know it is working for you. – Aamir Sep 17 '22 at 08:25