-3

I am solving a question in which I have to check if the input string of parentheses are balanced or not, and if not, code is expected to return the 1-based index of unmatched closing parenthesis, and if not found, return the 1-based index of the opening parenthesis. My code runs fine if I implement only the parenthesis checking part, but as I try to implement the returning index part, the code starts giving 'success' output for all the input. Here is the code:

#include<iostream>
#include<string>
#include<algorithm>
#include<stack>

using namespace std;

int process_input( string value );
bool closing_bracket_match(char opening_bracket, char closing_bracket);

bool closing_bracket_match(char opening_bracket , char closing_bracket){ 
    if( (opening_bracket == '{' && closing_bracket == '}') || (opening_bracket == '(' && closing_bracket == ')') || (opening_bracket == '[' &&
     closing_bracket == ']') ){
       
        return true;
    }
    else{
        return false;
    }
}

int process_input( string value ){
    stack<char> processed_input{};
    int unmatched_index{};

    for( size_t i{}; i< value.size() ; ++i ){
        
        if( value.at(i) == '{' || value.at(i) == '(' || value.at(i) == '[' ){ // check for opening brackets
            
            processed_input.push(value.at(i)); // Appending opening bracket into the stack
        
        }
        
        else if( (value.at(i) == '}' || value.at(i) == ')' || value.at(i) == ']') && (processed_input.empty() == false) &&
         closing_bracket_match(processed_input.top(),value.at(i)) ){ // the bracket in stack would be popped
            
            processed_input.pop(); // matching brackets ar removed

        }
    }
    if( processed_input.empty()==true ){
        return 0;
    }//This part is causing the bug
    if(processed_input.empty() == false){
        auto it = find( value.begin(), value.end(), processed_input.top() );
        if( it!= value.end() ){
            unmatched_index = distance(value.begin() , it)+1;  //returning the 1 -based index of unmatched bracket
        }
    return unmatched_index;
    }
}

int main(){
    string input{};
    cout<<"Please enter the code here: "; // debug line
    cin>> input;

    int result{};
    result = process_input(input);

    if( result == 0 ){
        cout<<"Success";
    }
    else{
        cout<<result;
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
  • [What is a debugger, and how will it help me diagnose problems?](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems). – PaulMcKenzie May 07 '21 at 18:27
  • dont ignore warnings: https://godbolt.org/z/xEGb5Enoa – 463035818_is_not_an_ai May 07 '21 at 18:27
  • `string input{};` -- Also, why not put a sample of the input that fails directly into the variable instead of `cin >> input;`? That way it is easier to run your program, and not have to type in the input every time the program runs. – PaulMcKenzie May 07 '21 at 18:31
  • Unrelated hint: an expression like `(expr == false)` is shorter written as `! expr`. – CiaPan May 07 '21 at 19:31
  • Unrelated hint: once you tested `processed_input.empty()` and handled it wit `return`, there is no need to test whether `!processed_input.empty()`. – CiaPan May 07 '21 at 19:43
  • I used expr == false just in an attempt to fix the issue, was using ! expr only. – Sudhanshu Shekhar May 08 '21 at 04:19
  • Yeah, you are right, thanks for that, I would sure refactor my code. – Sudhanshu Shekhar May 08 '21 at 04:20
  • This part: _'My code runs fine if I implement only the parenthesis checking part'_ means in fact _'a part of the code runs without a crash, but I can't tell if it does anything useful'_. If you want to learn if your code does anything useful, please analyse what steps it performs when you feed it with a one-character string containing just a single closing bracket. – CiaPan May 09 '21 at 23:17
  • My code returns the right index then, infact, making some small tweaks made the code perfect, I started getting the required output, but those tweaks were not big ones, idk how it helped! – Sudhanshu Shekhar May 11 '21 at 02:48
  • @SudhanshuShekhar Your last comment looks like _'I swapped some bolts with some nuts and some cables with some screws and my car started to go.'_ This is simply not true. And even if it seems to work, it works just by coincidence and it will most probably stop working if you port it to another OS (let alone another hardware platform) or just build it with another compiler. – CiaPan Jun 05 '21 at 21:50

1 Answers1

0

If you want to return a position of the last (innermost) unmatched paren, you need to store it together with its position on the stack. Seeking for it leads to errors.

Which of potentially several items equal to the one you seek will find() find?

For example, in "(((" there are three unmatched opening parentheses, and all of them are equal to '('. Which one do you want to return as a result? Which one do you actually return?

And how about this input: "()("...?


Added

Here is a possible solution. Please note how it does not find() anything, but it stores on a stack all information necessary to produce the desired output.

#include<iostream>
#include<string>
#include<stack>

using std::string;
using std::stack;

bool is_opening(char c) {
    return c == '(' || c == '[' || c == '{';
}

bool is_closing(char c) {
    return c == ')' || c == ']' || c == '}';
}

bool is_matching(char opn, char cls) {
    switch(opn) {
        case '(':  return cls == ')';
        case '[':  return cls == ']';
        case '{':  return cls == '}';
    }
    return false;
}

int process_input( string value )
{
    stack<char> opn_parens{};
    stack<size_t> positions{};

    for( size_t i{}; i < value.size() ; ++i )
    {        
        const char ch = value.at(i);

        if( is_opening(ch) )
        {            
            opn_parens.push(ch);
            positions.push(i);
        }
        else if( is_closing(ch) )
        {
            if( opn_parens.empty() ) // a closing paren with no unmatched opening one
                return i + 1;

            const char opn_ch = opn_parens.top();
            const size_t opn_pos = positions.top();
            
            if( ! is_matching(opn_ch, ch) ) // unmatched closing paren
                return opn_pos + 1;

            opn_parens.pop(); // remove a matched paren
            positions.pop();
        }
    }

    if( ! positions.empty() ) // some unmatched parens remain
        return positions.top() + 1;

    return 0;
}

int main(){
    std::cout << process_input("hello(mum[]{(dad()[bro!])})") << std::endl;
    std::cout << process_input("))") << std::endl;
    std::cout << process_input("([") << std::endl;
    std::cout << process_input("([)") << std::endl;
    std::cout << process_input("([{") << std::endl;
}

You can see it working at https://godbolt.org/z/e8fYW5fKz

CiaPan
  • 9,381
  • 2
  • 21
  • 35
  • The problem is, I want to check bracket at the top of the stack, but find() seems to return the front bracket. Ig I would have to make a separate function for the purpose! – Sudhanshu Shekhar May 08 '21 at 04:22
  • @SudhanshuShekhar Of course `find()` finds the first occurence of the character, not the last one! That's how `find()` is defined, hence it should work this way. As I already said in my answer, you should not use `find()` but instead remember positions of all unmatched opening brackets on a stack. Please see an example code I added above. – CiaPan Jun 05 '21 at 22:19