Spacing
I have a few issues with your spacing and brace usage. First, your logic in your loop is WAY too indented. A single indent is fine. Second, do not write logic on the same line as if
unless it's a trivial condition and has no else
- and never write logic on the same line as else
. It's impossible to read. Strongly prefer writing braces throughout. Also add a space after if
Here's balanced rewritten with better spacing:
bool balanced(string exp)
{
stack<char> st;
for(int i=0; i<exp.length(); i++)
{
if (exp[i]== '{' || exp[i]=='[' || exp[i]== '(') {
st.push(exp[i]);
}
else if (exp[i]=='}') {
if (st.top() == '{' && !st.empty()) {
st.pop();
}
else {
return false;
}
else if (exp[i]==')') {
if(st.top() == '(' && !st.empty()) {
st.pop();
}
else {
return false;
}
}
else if(exp[i]==']') {
if(st.top()=='[' && !st.empty()) {
st.pop();
}
else {
return false;
}
}
}
if (st.empty()) {
return true;
}
else {
return false;
}
}
Now that I can read your code, we can get to the logic issues.
Dealing with bools
You end with if (expr) return true; else return false;
. That's exactly equivalent to just:
return st.empty();
Similarly, you have:
bool balanced = balanced(exp);
if (balance == true) ...
else ...
Never write == true
, and you don't even need the variable here:
if (balanced(exp)) {
...
}
else {
...
}
Which can even be a ternary:
cout << (balanced(exp) ? "Yes" : "No") << endl;
Repetition
Your logic is extremely repetitive. We have three types of opens and three types of closed - we treat the opens identically, and we treat the closes the same way - check if the stack is non-empty and the top element is the equivalent open. For any char other than those 6 - we don't care.
So we can collapse our logic to be more explicitly equivalent with the three closes. Also a switch helps a lot here:
switch (exp[i]) {
case '{':
case '[':
case '(':
st.push(exp[i]);
break;
case '}':
case ']':
case ')':
if (!st.empty() && st.top() == open_brace(exp[i])) {
st.pop();
}
else {
return false;
}
break;
default:
break;
}
Where you just have to implement open_brace
to do the right thing. This saves a bunch of code, which in turn makes it less error prone. Also note the reordering of the conditions - you need to check for non-emptiness first.
Arguments
balanced
doesn't modify it's argument, or really need to do anything with it other than iterate over it. So take it by reference-to-const:
bool balanced(std::string const& expression)
And lastly...
using namespace std;
Avoid it.