-2

I have written code for parenthesis checker using stack in c++ ,it is working perfectly fine for all test cases individually but when I perform test case simultaneously in one go then it is giving error of segmentation fault.

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

int main()
{
    int t;
    cin >> t;

    while (t--) {
        string str;
        cin >> str;

        stack<char> box;

        int len = str.size();
        box.push(str[0]);

        for (int i = 1; i < len; i++) {
            char temp = str[i];
            char tp = box.top();

            if (((tp == '{' && temp == '}') || (tp == '[' && temp == ']') || (tp == '(' && temp == ')')) && (!box.empty())) {
                box.pop();
            }
            else {
                box.push(temp);
            }
        }

        if (box.empty() == true)
            cout << "balanced" << endl;
        else
            cout << "not balanced" << endl;
    }

    return 0;
}
Tobias Tengler
  • 6,848
  • 4
  • 20
  • 34
  • show me a sample test case that you get seg fault. – moinmaroofi Jul 14 '19 at 09:32
  • Provide [mcve]. What do you think happens when the stack is empty and you call `box.top();`? – Quimby Jul 14 '19 at 09:47
  • 3 {([])} () ([] – Adity Singh Jul 14 '19 at 10:04
  • You should never `#include `. It is not proper C++. It ruins portability and fosters terrible habits. See [https://stackoverflow.com/q/31816095](https://stackoverflow.com/q/31816095). – L. F. Jul 14 '19 at 11:23
  • Also, please avoid `using namespace std;`. It is considered bad practice. See [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/q/1452721) – L. F. Jul 14 '19 at 11:23
  • Have you single-stepped your code in the debugger to see where it's failing? Don't know how to use your debugger? Now's the perfect time to learn. – Jim Mischel Jul 14 '19 at 13:17
  • 1
    It's kinda pointless to check for `!box.empty()` **after** you've already called `box.top()` – Igor Tandetnik Jul 14 '19 at 14:13
  • Can't reproduce: [the code as shown works](https://rextester.com/RUK38843) on the input `3 {([])} () ([]`. It could fail with other input, but it works with this one. – Igor Tandetnik Jul 14 '19 at 14:16

1 Answers1

0

Basically your approach is very good. This is also the method used by parsers to match opening and closing tokens: A stack.

There are some improvements that should be done. You are shifting everything on the stack. You should just put the braces on the stack. Then you can do exact matches. Then you should put your braces in some container, e.g. a std::vector or a std::map or a std::string as I do in the following example.

For your seg fault. This hapens, when you try to access elements from an empty stack. One solution for that could be, to take advantage from C++' so called boolean short cut evaluation. Meaning, the evaluation of a boolean expression (for example, in an if statement) stops, as soon as the result is known.

So if you write (!braceStack.empty() && (braceStack.top() == openingBraces[position])) and the stack would be empty, then the stack.top function would not be invoked. Nothing would happen. You would be on the save side.

In the real world, you would NEVER do that, because then you would rely on side effects. You would simply put an additional if.

In your code you are calling top before checking, if the stack is empty. This results in undefined behaviour (UB).

In addition to the improvments made before, I also added comments, better variable names, usage of the containers algorithms and so on.

Please see.

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

// We define 2 strings with braces
// With that, searching is easier
const std::string openingBraces("([{<");

// Closing brace position must match to openeing brace position
const std::string closingBraces(")]}>");

int main()
{
    // Get number of test rund from user
    int numberOfTestRuns{ 0 };
    std::cin >> numberOfTestRuns;

    // Perform as many as tests, as user wants
    while (numberOfTestRuns--) {

        // Get string to analyze from user
        std::string stringToAnalyze;
        std::cin >> stringToAnalyze;

        // Define a stack for braces
        std::stack<char> braceStack{};

        // Check all charcters in test string. From beginning to end
        for (char currentCharToCheck : stringToAnalyze) {

            // If there is an opening brace
            if(openingBraces.find(currentCharToCheck) != std::string::npos) {

                // Then put this on the stack. Do not push other element on the stack
                braceStack.push(currentCharToCheck);
            }
            else {

                // It was no opening brace
                // Now we check, if it was a closing brace
                if (size_t position = closingBraces.find(currentCharToCheck); position != std::string::npos) {

                    // CLosing brace found. First check, if there are elements on the stack
                    // And then check, if we have a fmatching brace on the stack top
                    if (!braceStack.empty() && (braceStack.top() == openingBraces[position])) {
                        // In this case we remove the stacke top. ELse not. Will lead to no match
                        braceStack.pop();
                    }
                }
                // Else Nothing: It was any other character, no brace
            }
        }

        // If the stack is empty, then we could find a match for everything
        if (braceStack.empty() == true)
            std::cout << "balanced" << '\n';
        else
            std::cout << "not balanced" << '\n';
    }
    return 0;
}
A M
  • 14,694
  • 5
  • 19
  • 44
  • Both your code and the OP's code make the mistake of scanning the entire string, even in the face of error. For example, given `(((((((]]]]]]]}`, your code will go ahead and keep on processing even after it sees that first `]`. That's kind of silly, because once you see the `]`, you know that there's no way the string can ever be balanced. You should bail right then. If the closing brace doesn't match the most recent open brace, then the braces will never match. – Jim Mischel Jul 15 '19 at 00:04
  • This is example code. Following OP's idea.. We can add an ````else break;```` to the inner if at any time. No issue. – A M Jul 15 '19 at 04:38
  • I forgot . . . And push something on the stack . . . – A M Jul 15 '19 at 04:45