Stack Question (Balanced Expression problem set) - c++

I have solved a problem set for a CPSC class where we have to implement a stack to check if an expression is balanced. For example, when a user enters {a}, the program would check if it has been properly closed and return true or false. My program is running accordingly, but only for char values such as. {, ( & and [. When I enter an input of (2(1+2)) it returns false. The algorithm makes sense and works, but I cannot seem to find the issue with my isBalanced function.
I could really use some help
#ifndef BALANCED_H
#define BALANCED_H
#include<string>
class Balanced {
public:
Balanced(std::string);
bool isBalanced();
bool isMatch(char c, char d);
private:
std::string expression;
};
#endif // BALANCED_H
#include "Balanced.h"
#include <string>
#include<iostream>
#include <stack>
Balanced::Balanced(std::string s) : expression(s)
{
}
bool Balanced::isBalanced()
{
std::stack<char> b;
for(unsigned int i=0; i < expression.size(); i++)
{
if(expression[i]=='{'|| expression[i] == '[' || expression[i] == '(')
{
b.push(expression[i]);
continue;
}
if(b.empty() || !isMatch(b.top(), expression[i]))
{
return false;
}
else{
b.pop();
}
}
return b.empty();
}
bool Balanced::isMatch(char c, char d)
{
if(c == '{' && d == '}')
{
return true;
}
else if(c == '[' && d == ']')
{
return true;
}
else if(c == '(' && d == ')')
{
return true;
}
else
{
return false;
}
}
int main()
{
std::string s;
std::string expression;
std::cout<<"Welcome to balance expression program" <<std::endl;
do{
std::cout<<"Enter any key to continue or type 'Help' to display a help menu ";
std::cout<<"You may also type 'Exit' to exit the program: ";
std::cin>>s;
if(s=="Help")
{
displayHelp();
continue;
}
else if(s=="Exit")
{
break;
}
else{
std::cout<<"Enter an expression: ";
std::cin>>expression;
}
Balanced d(expression);
if(d.isBalanced()!=true){
std::cout<<"The expressions is not balanced";
std::cout<<std::endl;
}
else{
std::cout<<"The expression is balanced";
std::cout<<std::endl;
}
}while(s!="Exit");
return 0;
}
void displayHelp()
{
std::cout<<std::endl;
std::cout<<"The purpose of this program is to check ";
std::cout<<"if an expression is balanced ";
std::cout<<"You will enter an expression and it will check to see if there is
closing ";
std::cout<<"brackets. If the expression is balanced, then it will return true if
not ";
std::cout<<"then the program will return false ";
std::cout<<"You can enter as many expression as you like. If you like to exit
the program, ";
std::cout<<"type 'Exit'"<<std::endl;
std::cout<<std::endl;
}

It would seem that your isMatch function will return false if the current character is not an open or close bracket, thus causing the whole thing to return false.

Related

C++ Stack Implementation, checking parenthesis correctness

I want to give the expression in the form of parenthesis through CIN, like: ()). then, through push & pop operation of the stack, I want the program to print me weather the given expression is BALANCED or NOT. The program works perfectly but only one issue has been found & that is when I enter like ()(, so it tells me that this expression is IMBALANCED which is fine but when I enter like () (, so then it tell me that this expression is BALANCED which is actually not balanced.
#include <iostream>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
char Stack[10];
int top=-1;
void push(char ch)
{
if(top<10)
{
top++;
Stack[top] = ch;
}
else
cout<<"Stack Overflow";
}
void pop()
{
if(top > -1)
{
top--;
}
else
cout<<"Stack Underflow";
}
int show(){
cout<<"It is imbalanced.";
}
int main(int argc, char** argv)
{
int a=0,b=0;
string exp;
cout << "Write down the parenthesis:" ;
cin >> exp;
bool check = true;
for(int i=0; i<exp.length(); i++)
{
if(exp[i]== '(')
{
push(exp[i]);
}
else if(exp[i]== ')')
{
if(top == -1)
{
check = false;
break;
}
else
{
pop();
}
}
}
for(int i=0; i<exp.length(); i++)
{
if(exp[i]=='('){
++a;
}
else if (exp[i]==')')
{
b++;
}
}
if(a>b){
cout<<"\n\nGiven Combination is IMBALANCED";
return 0;
}
if(check == true)
cout<<"\n\nGiven Combination is BALANCED";
else
cout<<"\n\nGiven Combination is IMBALANCED";
return 0;
}
The main comments boil down to:
Don’t use a stack when no stack is needed.
And if you do use one, don’t limit it to an arbitrary fixed depth.
Handle errors and report malformed expressions.
Make sure you get the right input; std::getline() may be less error-prone than input tokenized using the >> operators. Just skip spaces (or whatever insignificant characters are allowed in the input).
using namespace std; is an antipattern and a bad habit.
The basic idea: Calculate the nesting depth as you iterate over the string. It must be zero, ultimately. It must not drop below zero at any point.
#include <cstdlib>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string_view>
using std::size_t;
bool correctly_parenthesized(std::string_view expression) {
size_t depth{0};
for (const auto character : expression) {
switch (character) {
case '(': ++depth; break;
case ')': if (depth) { --depth; break; } else { return false; }
case ' ': break;
default: throw std::invalid_argument("invalid character");
}
}
return depth == 0;
}
int main() {
std::cout << "Write down the parentheses: ";
std::string exp;
std::getline(std::cin, exp);
try {
std::cout << (correctly_parenthesized(exp) ? "YES" : "NO") << std::endl;
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
return EXIT_FAILURE;
}
}

I have written this program for infix to postfix conversion

#include<iostream>
#include<stdio.h>
#define MAX 20
using namespace std;
char stk[MAX];
int top=-1;
void push(char c)
{
if(top==MAX-1)
cout<<"Overflow";
else
{
stk[++top]=c;
}
}
char pop()
{
if(top==-1)
{
return '\0';
}
else
return stk[top--];
}
int priority(char ch)
{
if(ch=='(')
return 1;
if(ch=='+'||ch=='-')
return 2;
if(ch=='*'||ch=='/')
return 3;
if(ch=='^')
return 4;
}
int main()
{
char exp[35],*t,x;
cout<<"Enter expression: ";
fgets(exp,35,stdin);
t=exp;
while(*t)
{
if(isalnum(*t))
cout<<*t;
else if(*t=='(')
push(*t);
else if(*t==')')
{
while((x=pop())!='(')
cout<<x;
}
else
{
if(priority(stk[top])>=priority(*t))
cout<<pop();
push(*t);
}
t++;
}
while(top!=-1)
cout<<pop();
return 0;
}
The output for input:
a+b-(c+d/e)
is
ab+cde/+
-
I don't understand why - is on a newline.
I have just started learning c++ and I am trying to implement some programs I did in c using c++. The same code in c works fine. I think there are some holes in my basic c++ knowledge and I would like to fill them up.
std::fgets does not discard the newline in the input stream like getline would. That means exp contains "a+b-(c+d/e)\n" and not "a+b-(c+d/e)". You either need to remove the newline from exp, switch to cin.getline(), or stop your processing loop when it hits the newline.
Try to change fgets to std::cin. And use std::string instead of char*:
#include <iostream>
#include <string>
int main()
{
string exp;
cout << "Enter expression: ";
std::cin >> exp;
auto t = exp.data();
char x;
for(auto &ch: exp)
{
if(isalnum(ch))
cout << ch;
else if(ch == '(')
push(ch);
else if(ch == ')')
{
while((x = pop()) != '(')
cout << x;
}
else
{
if(priority(stk[top]) >= priority(ch))
cout << pop();
push(ch);
}
}
while(top != -1)
cout << pop();
return 0;
}
In addition to the processing of '\n' as mentioned by NathanOliver, your function priority() doesn't return a value when the user entered any other character not checked in the if statements, so the behavior might be undefined.

Online judge runtime error when checking for balanced grouping characters

This is my code for checking if a string of grouping characters is properly balanced.
It works fine on my local machine, but the online judge gives me a run-time error.
#include <iostream>
#include <string>
#include <stack>
using namespace std;
bool balanced(string exp)
{
stack<char> st;
int i;
for(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;
}
int main() {
string exp;int n;
cin >> n;
cin.ignore();
while(n--)
{
getline(cin,exp);
bool balance = balanced(exp);
if(balance == true)cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}
if(st.top() == '{' && !st.empty())
You should check for stack emptiness before taking the top.
if(!st.empty() && st.top() == '{')
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.

most effective & easiest solution for expression evaluation c++

many programs needs to evaluate expressions like:
input: (T(TF)) ---> output: false (T as true, and F as false)
OR
input (a (b c 2) 3)$ ---> output: abcbcabcbcabcbc
in other words,how to deal with expressions that contain braces?
I used to push to stack until I reach ')'.
then, pop until I reach '(', and so on.
but that would take a long execution time and missy code!
and if I tried to take good of #Henrik code to solve arithmetic expression, I end up with a wrong answer
#include <iostream>
using namespace std;
const char * expressionToParse = "(T(TT))";
char peek()
{
return *expressionToParse;
}
char get()
{
return *expressionToParse++;
}
bool expression();
bool number()
{
bool result = get() - '0';
//even if I remove -'0'
cout<<"number() result:"<<result<<endl;
while (peek() == 'T' || peek() == 'F')
{
if (peek()=='T' && get()=='T') {
result=true;
}
else{
result=false;
}
}
return result;
}
bool factor()
{
if (peek() == 'T' && peek() <= 'F')
return number();
else if (peek() == '(')
{
get(); // '('
bool result = expression();
get(); // ')'
return result;
}
return 0; // error
}
bool expression()
{
bool result = factor();
return result;
}
int main()
{
bool result = expression();
if(result){
cout<<"true";
}
else{
cout<<"false";
}
return 0;
}
Thanks in Advance
This is an expression in postfix form. The easiest way to evaluate a postfix expression can be done using a stack. Search for "postfix expression evaluation" tutorials.

a code for infix to postfix conversion

I have written a code for infix to postfix conversion,This piece of code is not encountering any kind of compile time error but after taking the input infix expression it is giving some runtime errors which i am unable to understand these errors are something related to string as the message says.
#include<iostream>
#include<string>
#define N 50
using namespace std;
class stack
{
private:
char arr[N];
int tos;
public:
void push(char p)
{
if (tos != N)
arr[++tos] = p;
else
cout << "stack full";
}
char pop()
{
if (tos == -1)
cout << "stack Empty";
else
return (arr[tos--]);
}
bool isempty()
{
if (tos == -1)
return (true);
else
return (false);
}
char top()
{
return arr[tos];
}
stack()
{
tos = -1;
}
};
int pres(char sym)
{
if (sym == '^')
return 3;
else if (sym == '*' || '/')
return 2;
else if (sym == '+' || '-')
return 1;
else if (sym == '(')
return 0;
}
bool isoperator(char op)
{
if (op=='+' || op=='-' || op=='/' || op=='*' || op=='^')
return true;
else
return false;
}
int main()
{
string infix, postfix;
stack s;
int in=0;
int post=0;
cout << "Enter an infix expression: ";
cin >> infix;
s.push('(');
infix.append(")");
char temp;
while (!(s.isempty()))
{
if (isdigit(infix[in]))
postfix[post++] = infix[in];
else if (infix[in] == '(')
s.push(infix[in]);
else if (infix[in] == ')')
{
while (1)
{
temp = s.pop();
if (temp == '(')
break;
else
postfix[post] = infix[in];
}
}
else if (isoperator(infix[in]))
{
while (pres(s.top()) >= pres(infix[in]))
postfix[post++] = s.pop();
s.push(infix[in]);
}
in++;
}
cout << "Postfix expression is: " << postfix;
system("pause");
}
I m unable to get what's wrong with it. Can any one help??
I found the following logical errors in your code:
the result string postfix is empty at the beginning, but you're writing to single character positions using postfix[post++]=. This is not valid and is propably causing the "string related" errors. You should only use postfix.push_back() to add characters to the output string.
In the first inner while loop (while(1)) the last statement should read
postfix.push_back(temp);
since you want to append the operators from the stack to the output.
Your code falsely accept input with unbalanced additional closing parents like "1+4)". Personally, I would put the input position as outer loop condition and verify that the stack is empty after the loop (and check for empty stack in the pop() function) for detecting input errors.
The biggest error is in his pres() function, it should be:
else if (sym == '*' || sym == '/')
else if (sym == '+' || sym == '-')
I have noticed some of the errors mentioned by MartinStettner.