Why can't i loop through this stack? - c

I'm trying to make a parentheses checker with implementing stack. The program will print valid if the input have a correct parentheses pattern
input: {[()]}
output: valid
input: {()[()]}
output: valid
input: (()))
output: unvalid
continuously
But what happen after i input the data is :
()
the program prints this unlimited loop
valid
valid
valid
valid
valid
. . . and so on
same with
(()))
It works normally if put break; on here, but it won't be continuous and would instantly ends the program, and wont ask for the input again.
if(isempty(stack)){
printf("Valid parenthesis expression\n");
break;
} else{
printf("Invalid parenthesis expression\n");
break;
}
I can't seem to find the reason why this happened,
can anyone help me or give me some advice about what's going on? So that I can loop to ask for input and print the valid/invalid just only one time?
#include<stdio.h>
#include<malloc.h>
#include<string.h>
typedef struct data{
char parent;
struct data *next;
}DATA;
void push(DATA **stack, char parentheses);
int isempty(DATA *stack);
void pop(DATA **stack);
int top(DATA *stack);
int main(int argc, char const *argv[]){
DATA *stack;
char parentheses[100];
int i, flag = 1;
do{
//PUSH
stack = NULL;
printf("Enter parentheses: ");
scanf("%[^\n]", &parentheses);
if(strcmp(parentheses, "-1") == 0){
break;
}
for(i = 0; i < strlen(parentheses); i++){
if(parentheses[i] == '{' || parentheses[i] == '[' || parentheses[i] == '('){
push(&stack, parentheses[i]);
} else if (stack == NULL){
printf("Invalid parenthesis expression\n");
break;
} else if(parentheses[i] == '}' && top(stack) == '{'){
pop(&stack);
} else if (parentheses[i] == ']' && top(stack) == '['){
pop(&stack);
} else if (parentheses[i] == ')' && top(stack) == '('){
pop(&stack);
} else if(parentheses[i] != '{' || parentheses[i] != '[' || parentheses[i] != '(' || parentheses[i] != '}' || parentheses[i] != ']' || parentheses[i] != ']') {
printf("Invalid parenthesis expression\n");
break;
}
}
//POP
if(isempty(stack)){
printf("Valid parenthesis expression\n");
} else{
printf("Invalid parenthesis expression\n");
}
}while(1);
return 0;
}
void push(DATA **stack, char parentheses){
DATA *node = (DATA*) malloc(sizeof(DATA));
node -> parent = parentheses;
node -> next = NULL;
if(!isempty(*stack)) node->next = *stack;
*stack = node;
}
int isempty(DATA *stack){
if(stack == NULL) return 1;
else return 0;
}
void pop(DATA **stack){
DATA *temp = *stack;
*stack = (*stack)->next;
free(temp);
}
int top(DATA *stack){
return stack -> parent; //STACK !ISEMPTY
}

scanf("%[^\n]", &parentheses);
must be
scanf(" %[^\n]", parentheses);
notice the space before the '%' to bypass the newline coming from a previous input, without it on the second turn scanf does nothing. To detect that case and also any invalid input I encourage you to always check the value scanf returns.
In case the input has at least 100 characters you write out of parentheses, do
if (scanf(" %99[^\n]", parentheses) != 1) {
/* EOF */
return -1;
}
parentheses is an array, if you want to use "&" it is specifying the index 0 so &parentheses[0]
Note flag is unused
When you detect an invalid case you can indicate "Valid parenthesis expression" :
pi#raspberrypi:/tmp $ ./a.out
Enter parentheses: (
Invalid parenthesis expression
Enter parentheses: )
Invalid parenthesis expression
Valid parenthesis expression
When the stack is not empty after the for you do not free the still present allocated elements, you have memory leaks.
Because you just save characters in the stack it is much more simple and cheaper in memory to just use an array of char. Because the input is limited to 99 (without the final null character) the stack needs to save 99 characters too, and in fact parentheses can be used for the stack
A proposal still using your stack, fixing problems and also reducing the number tests and simplifying stack functions :
#include<stdio.h>
#include<malloc.h>
#include<string.h>
typedef struct data{
char parent;
struct data *next;
} DATA;
void push(DATA **stack, char parentheses);
int isempty(DATA *stack);
void pop(DATA **stack);
int top(DATA *stack);
int main(int argc, char const *argv[]){
DATA *stack = NULL;
char parentheses[100];
char * p;
while (fputs("Enter parentheses: ", stdout),
(scanf(" %99[^\n]", parentheses) == 1) && strcmp(parentheses, "-1")) {
for (p = parentheses; *p; ++p) {
if ((*p == '{') || (*p == '[') || (*p == '('))
push(&stack, *p);
else {
char o;
if (*p == '}')
o = '{';
else if (*p == ')')
o = '(';
else if (*p == ']')
o = '[';
else
o = 0;
if (isempty(stack) || (top(stack) != o))
break;
pop(&stack);
}
}
if (!isempty(stack) || *p) {
puts("Invalid parenthesis expression");
while (! isempty(stack))
pop(&stack);
}
else if (!*p)
puts("Valid parenthesis expression");
}
return 0;
}
void push(DATA **stack, char parentheses) {
DATA *node = malloc(sizeof(DATA));
node->parent = parentheses;
node->next = *stack;
*stack = node;
}
int isempty(DATA *stack) {
return (stack == NULL);
}
void pop(DATA **stack) {
DATA *temp = *stack;
*stack = (*stack)->next;
free(temp);
}
int top(DATA *stack) {
return stack->parent;
}
Compilation and execution:
pi#raspberrypi:/tmp $ gcc -g -Wall s.c
pi#raspberrypi:/tmp $ ./a.out
Enter parentheses: ({[]}())
Valid parenthesis expression
Enter parentheses: (
Invalid parenthesis expression
Enter parentheses: )
Invalid parenthesis expression
Enter parentheses: (]
Invalid parenthesis expression
Enter parentheses: -1
pi#raspberrypi:/tmp $

Related

This code don't run on other compiler except vscode

The giver code is for converting infix to postfix using stack. I tried it everywhere no errors or warning were shown except for one time there was a segmentation fault on my school's computer. If anyone can explain the correct way to write the code it'll be very helpful as I'm unable to find.
In code we scan the infix expression and check if it's an operator and then if it is an operator we push it to stack and character or digit go to an array. We then pop the operator from the stack if we find another operator of more precedence than the previous pushed operator and we keep popping till we get less precedence operator in stack and append it to the array that is also our output.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<ctype.h>
struct stack
{
int size;
int top;
char *arr;
};
int stacktop(struct stack *sp)
{
return sp->arr[sp->top];
}
void push(struct stack *ptr, char val)
{
if (ptr->top == ptr->size - 1)
{
printf("Stack is full\n");
}
else
{
ptr->top++;
ptr->arr[ptr->top] = val;
}
}
char pop(struct stack *ptr)
{
int a;
if (ptr->top == -1)
{
printf("\n");
}
else
{
a = ptr->arr[ptr->top];
ptr->top--;
return a;
}
}
int isoperator(char symbol)
{
if (symbol == '^' || symbol == '*' || symbol == '/' || symbol == '+' || symbol == '-')
{
return 1;
}
else
{
return 0;
}
}
int precedence(char symbol)
{
if (symbol == '^')
{
return (3);
}
else if (symbol == '*' || symbol == '/')
{
return (2);
}
else if (symbol == '-' || symbol == '+')
{
return (1);
}
else
{
return (0);
}
}
char *infix_to_postfix(char *infix)
{
struct stack *sp = (struct stack *)malloc(sizeof(struct stack));
sp->size = 50;
sp->top = -1;
sp->arr = (char *)malloc(sp->size * sizeof(char));
char *postfix = (char *)malloc(strlen((infix) + 1) * sizeof(char));
int i = 0, j = 0, x = 0;
while (infix[i] != '\0')
{
if (infix[i] == '(')
{
push(sp, infix[i]);
}
else if( isdigit(infix[i]) || isalpha(infix[i])){
postfix[j]=infix[i];
j++;
}
else if (isoperator(infix[i])==1)
{
x=pop(sp);
while(isoperator(x)==1 && precedence(x)>=precedence(infix[i])){
postfix[j]=x;
j++;
x=pop(sp);
}
push(sp, x);
push(sp, infix[i]);
}
else if (infix[i] == ')')
{
x = pop(sp);
while (x != '(')
{
postfix[j] = x;
j++;
x = pop(sp);
}
}
i++;
}
while (!(sp->top == -1))
{
postfix[j] = pop(sp);
j++;
}
postfix[j] = '\0';
return postfix;
}
int main()
{
char *infix;
printf("Enter your expression\n");
scanf("%s",infix);
printf("Postfix is %s", infix_to_postfix(infix));
return 0;
}
The pointer variable char *infix doesn't point to anything so it's not about VSCode and other compilers. It's complete luck that it's working on VSCode.
You should allocate some memory either statically char infix[100] or dynamically char *infix = (char *)malloc(100).
Also, you have a problem with pop function. You shouöd always return a char from this function not only under certain conditions.

Is there a way to make my if statement more efficient with an enum?

I am working on a simple parser which takes a string as input and parses a string to see if the opening and closing parentheses/brackets/braces are correctly placed. One step in this involves me skipping every character that is not a valid token (a parenthesis, bracket, or brace), because at this point I don't care whether the expression inside the parentheses are valid or not–I'm only interested in whether the parentheses are syntactically correct. I wrote an if statement which tells the loop to skip to the next iteration when it encounters anything that's not an opening or closing brace, but the code looks ugly and is repetitive. I was wondering if there was a better way to do it–perhaps with an enum. Directly below is the function in question, (parse), and below that, I've pasted the code for the entire program so far. If you answer or attempt to answer this, thank you for your time.
void parse(char *string) {
for (int i = 0; i < strlen(string); i++) {
if (string[0] == ')' || string[0] == ']' || string[0] == '}') {
printf("ParseError: Statement begins with invalid token '%c'", string[0]);
return;
}
if (string[i] != '(' || string[i] != '[' || string[i] != '{' ||
string[i] != ')' || string[i] != ']' || string[i] != '}') {
continue;
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
char character;
struct Node *link;
} * top;
struct Node *getNewNode(char);
void push(char);
void pop(void);
void parse(char *);
void print(void);
int main() {
top = NULL;
char string[100];
char *string_ptr = string;
printf("Enter an expression to parse: ");
fgets(string, sizeof(string), stdin);
parse(string_ptr);
print();
}
struct Node *getNewNode(char character) {
struct Node *newNode = (struct Node *)(malloc(sizeof(struct Node)));
newNode->character = character;
newNode->link = top;
return newNode;
}
void push(char character) {
struct Node *newNode = getNewNode(character);
top = newNode;
}
void pop(void) {
struct Node *temp;
if (top == NULL) {
printf("Stack is empty!");
return;
}
temp = top;
top = top->link;
free(temp);
temp = NULL;
}
void print(void) {
struct Node *temp = top;
while (temp != NULL) {
printf("%c", temp->character);
temp = temp->link;
}
}
void parse(char *string) {
for (int i = 0; i < strlen(string); i++) {
if (string[0] == ')' || string[0] == ']' || string[0] == '}') {
printf("ParseError: Statement begins with invalid token '%c'", string[0]);
return;
}
if (string[i] != '(' || string[i] != '[' || string[i] != '{' ||
string[i] != ')' || string[i] != ']' || string[i] != '}' ||) {
continue;
}
}
}
There are college courses on parsing theory. We construct software “machines” of various kinds to parse strings, so good solutions for issues like this involve incorporating them into an overall parsing scheme, not solving each one individually.
However, given that, a typical way to handle something like this is to prepare an array with information about the characters:
#include <limits.h>
// Define bit flags for character properties.
enum { IsOpener = 1, IsCloser = 2, };
// Initialize array with flags for characters.
static unsigned CharacterProperties[UCHAR_MAX+1] =
{
['('] = IsOpener,
['['] = IsOpener,
['{'] = IsOpener,
[')'] = IsCloser,
[']'] = IsCloser,
['}'] = IsCloser,
};
…
if (CharacterProperties[string[0]] & IsOpener)
… // Here string[0] is one of the “open parentheses” type of characters.
Note there are some sign issues to watch out for: The subscript to CharacterProperties should be nonnegative, so string should be unsigned char * or you should cast it with (unsigned char) in the subscript or you should ensure char is unsigned. And, if any of the characters in the initialization could be negative (are not in C’s basic execution character set), they should be cast too.
This may be a good use case for a switch:
void parse( char *string )
{
/**
* Make sure string[0] is valid first
*/
switch( string[0] )
{
case ')':
case ']':
case '}':
fprintf( stderr, "parse error..." );
return;
break;
default:
break;
}
/**
* Compute the length of the string once rather
* than every time through the loop.
*/
size_t len = strlen( string );
for ( size_t i = 0; i < len; i ++ )
{
/**
* Is the current character a delimiter?
*/
switch( string[i] )
{
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
// we'll process the delimiter character following
// the end of the switch statement
break;
default:
// this is not a delimiter, go back to the beginning of
// the loop
continue;
break;
}
// process delimiter character
}
}
but that heavily depends on how you're going to process other characters once you beef up your parser. Switches can get ugly and unmaintainable in a hurry. I've written this such that the switches act only as filters; they simply decide whether to proceed with the current operation or not, there's no processing logic in either one.

Newline-terminating input loop not exiting in C

I'll preface this with the fact that this is for a homework assignment, so I'm just trying to understand what's going wrong not necessarily exactly how to fix it. I'm working in C, taking a name and grade from the user to create/manipulate structs and use a stack. This while loop won't exit and it isn't reaching the testing print statement at the bottom. line, name, cGrade, and fullData are all character arrays, maxGrade and numGrade are both double variables, s is a stack and item is a void*:
while ((fgets(line, SIZE, stdin)) != NULL && line[0] != '\n') {
if (sscanf(line, "%s %s", name, cGrade) == 2) {
numGrade = atoi(cGrade);
fullData[0] = 0;
if (numGrade >= 0 && numGrade <= 100) {
strcat(fullData, name);
strcat(fullData, " ");
strcat(fullData, cGrade);
printf("Added %s\n", fullData);
item = name;
push(s, item);
if (numGrade > maxGrade) {
maxGrade = numGrade;
}
i++;
} else {
printf("ERROR: Grade must be between 0 and 100\n");
}
}
printf("Outside if: line[0] = %c", line[0]);
}
Edit: adding a screenshot of the output
Screenshot of output
Edit: Adding push code
void push(stack s, void* item){
stackelement* e = malloc(sizeof(stackelement*));
e->contents = malloc(sizeof(void*));
e->next = malloc(sizeof(stackelement*));
e->contents = item;
e->next = s->top;
s->top = e;
}
Here's the struct definition as well. I was given this for the assignment so I'm not allowed to change it.
struck stackelementS {
void* contents;
struct stackelementS* next;
}
typedef struct stackelementS stackelement;
struct stackS {
stackelement* top;
}
typedef struct stackS* stack;
It ended up being the simple fact that using sscanf doesn't include the escape character \0 in the returned string which I assume was messing up some of the string functions. I added a char *end; *end = '\0'; and used strcat() to append it to the name and cGrade. I fixed some of the errors suggested in the comments and it cleaned up the code a lot.
Here's the fixed code:
while(fgets(line, SIZE, stdin) != NULL && line[0] != '\n'){
if(sscanf(line, "%s %s", name, cGrade) == 2){
strcat(name, end);
strcat(cGrade, end);
numGrade = strtod(cGrade, &ptr);
if(numGrade >=0 && numGrade<= 100){
push(s, line);
printf("Added student %s with grade %s to the stack\n", name, cGrade);
if(numGrade > maxGrade){
maxGrade = numGrade;
}
i++;
}
else{
printf("ERROR: Grade must be between 0 and 100, please re-enter the information\n"); }
}
}

Trouble with popping stack in c RPN calculator

I've been working on this assignment for the past week or so and have been stuck trying to work out what is wrong with my pop() function.
The push() function works fine and is able to store input tokens into the stack; however, as soon as I try to pop them, as per the shunting yard algorithm, the code is unable to compile.
Hopefully someone can help me out here!
I apologize if I've used the wrong terminology / caused confusion in my question it is my first programming subject!
Here is the incomplete code so far including the pop function at the bottom:
#include <stdio.h>
#include <string.h>
#include <conio.h>
#define MAX_LENGTH 400
#define MAX_STACK_SIZE 40
void NoWhitespace(char *string);
int IsNumber(char token);
int IsOperator(char token);
int Push(char *stack, int *top, char token);
int Pop(char *stack, int *top, char token);
int Top(char *stack);
int OrderOfOps(char token);
int main()
{
int top = -1;
char input[MAX_LENGTH];
char token;
char output[MAX_LENGTH];
char stack[MAX_STACK_SIZE];
char popped;
//* Greeting Message *//
printf("Simple Calculator\n");
//* While this statement is true, continue with program *//
while(1)
{
//* Display Prompt *//
printf(">>> ");
fflush(stdout);
//* Get the user input *//
gets(input);
//* Check for help *//
if (input[0] == ('h') && input[1] == '\0')
{
printf("Simple Calculator understands the following arithmetic operations:\n^ exponentiation\n+ addition\n- subtraction\n* multiplication\n/ division\n");
}
//* Check for quit *//
else if (input[0] == ('q') && input[1] == '\0')
{
printf("Goodbye!");
return 0;
}
//* Get rid of all the whitespace in the input before looping through it *//
NoWhitespace(input);
//* Initialize value j before the for loop begins so that after breaking, it will reset to zero *//
int j = 0;
//* Go through every component of the string *//
for (int i = 0; input[i] != '\0' ; i++)
{
//* Let variable 'token' be equal to the component that the for loop is up to in the input string *//
token = input[i];
//* Check if the token is a number *//
if (IsNumber(token))
{
//* Add it to the output array and increment j by one *//
output[j++] = token;
}
//* Check if the token is an operator *//
else if (IsOperator(token))
{
if (stack[0] == '\0')
{
Push(stack, &top, token);
}
while (stack[0] != '\0')
{
if ((OrderOfOps(token) <= OrderOfOps(Top(stack))))
{
popped = Pop(stack, &top, Top(stack));
output[j++] = popped;
}
else
{
Push(stack, &top, token);
}
}
}
else if (token == '(')
{
Push(stack, &top, token);
}
}
printf(output);
printf("\n");
printf(stack);
printf('\n');
}
return 0;
}
int Pop(char *stack, int *top, char token)
{
if( *top == -1 )
{
return(-1);
}
else
{
stack[*top] = token;
*top = *top - 1;
return(1);
}
}

Balanced Expression

Below is the code to determine balancing of symbol.
If the expression is balanced then it should print appropriate message. E.g:
((A+B))+(C+D)) --> Balanced
((A+B)+(C+D) ---> Unbalanced
((A+B)+(C+D}) --> Unbalanced
Here is the code
#include <stdio.h>
#include <stdlib.h>
struct Stack {
char data;
struct Stack *next;
};
void push(struct Stack **top, char data) {
struct Stack *new_node;
if (*top == NULL) {
new_node = malloc(sizeof(struct Stack));
new_node->data = data;
new_node->next = *top;
*top = new_node;
} else {
new_node = malloc(sizeof(struct Stack));
new_node->data = data;
new_node->next = *top;
*top = new_node;
}
}
char pop(struct Stack **top, int flag) {
if (*top != NULL && flag == 0) {
printf("\n Expression is In-Valid :) \n");
return '\0';
}
if (*top == NULL && flag == 1) {
printf("\n Unbalanced Expression \n");
return '\0';
}
if (*top != NULL && flag == 1) {
struct Stack *temp = *top;
char op;
op = (*top)->data;
*top = (*top)->next;
free(temp);
return op;
}
}
/*
void display(struct Stack *top) {
struct Stack *temp = top;
while (temp) {
printf("\n %c", temp->data);
temp = temp->next;
}
}
*/
int main(void) {
struct Stack *top = NULL;
int i = 0;
char str[] = "((A+B)+[C+D])", op;
printf("\n Running the programe to check if the string is balanced or not ");
for (i = 0; str[i] != '\0'; ++i) {
if (str[i] == '(' || str[i] == '[' || str[i] == '{' || str[i] == '<')
push(&top, str[i]);
else
if (str[i] == ')' || str[i] == ']' || str[i] == '}' || str[i] == '>') {
op = pop(&top, 1);
if ((op == '(' && str[i] == ')') ||
(op == '[' && str[i] == ']') ||
(op == '{' && str[i] == '}') ||
(op == '<' && str[i] == '>')) {
continue;
} else {
printf("\n The expression is un-balanced \n");
break;
}
}
}
pop(&top, 0);
return 0;
}
But it does not give the desired output. I have debugged the code but was not able to find the issue.
How can I have it print the appropriate message ?
You should immediately clean the stack and stop processing as soon as you detect something unbalanced, and print "Balanced" when you reach return 0. And you should print "Unbalanced" from one single place in your code.
And it is bad that one branch of pop does not return a value when it is declared to return one.
So, pop could become:
char pop(struct Stack **top,int flag)
{
if(*top!=NULL && flag==0)
{
return '\0';
}
if(*top==NULL && flag ==1)
{
return '\0';
}
if(*top!=NULL && flag==1)
{
struct Stack *temp=*top;
char op;
op=(*top)->data;
*top=(*top)->next;
free(temp);
return op;
}
// *top == null && flag == 0
return 'O'; // for OK
}
I would add a clean method - not required because program exit cleans the stack, but I do prefer that:
void clean(struct Stack *top) {
struct Stack *next;
while (top != NULL) {
next = top->next;
free(top);
top = next;
}
}
And some changes in main:
int main(void)
{
struct Stack *top=NULL;
int i=0, err=0;
...
else
{
err = 1;
break;
}
}
}
if (err || (pop(&top,0) == '\0')) {
printf("\n The expression is un-balanced \n");
clean(top);
// return 1; optionally if you want to return a different value to environment
}
else {
printf("\n The expression is balanced \n");
}
return 0;
}
Your pop function is wrong.
You have not handled if top is null and flag is 0. It might also be a case.
Secondly, why do you **top in your push\pop signature when you should be passing top in it. I think it should have *top in its signature.
Also, why you use if in push. Its not needed. You are essentially doing same thing.
You can do this simply by simple modification in this code. I take it from Find maximum depth of nested parenthesis in a string this. It's also help for knowing details. I think it's helpful to you
#include <iostream>
using namespace std;
// function takes a string and returns the
// maximum depth nested parenthesis
int maxDepth(string S)
{
int current_max = 0; // current count
int max = 0; // overall maximum count
int n = S.length();
// Traverse the input string
for (int i = 0; i< n; i++)
{
if (S[i] == '(')
{
current_max++;
// update max if required
if (current_max> max)
max = current_max;
}
else if (S[i] == ')')
{
if (current_max>0)
current_max--;
else
return -1;
}
}
// finally check for unbalanced string
if (current_max != 0)
return -1;
return max;
}
// Driver program
int main()
{
string s = "( ((X)) (((Y))) )";
if (maxDepth(s) == -1)
cout << "Unbalance";
else
cout << "Balance";
return 0;
}
Time Complexity : O(n)
Auxiliary Space : O(1)
Thanks for the suggestions. Here is my below working code of the same problem
#include<stdio.h>
#include<stdlib.h>
struct Stack{
char data;
struct Stack *next;
};
void push(struct Stack **top,char data)
{
struct Stack *new_node;
new_node=malloc(sizeof(struct Stack));
new_node->data=data;
new_node->next=*top;
*top=new_node;
}
int compare(char str,char op)
{
if( (op == '(' && str == ')') || (op == '{' && str == '}') || (op == '[' && str == ']') || (op == '<' && str == '>') )
return 1;
else
return 0;
}
int pop(struct Stack **top,char str)
{
char op,ret;
struct Stack *temp=*top;
if(*top==NULL)
return 0;
else if(*top!=NULL)
{
// Pop the element and then call comapre function
op=(*top)->data;
free(temp);
*top=(*top)->next;
return(ret=compare(str,op));
}
}
void display(struct Stack *top)
{
struct Stack *temp=top;
while(temp!=NULL)
{
printf("%c ",temp->data);
temp=temp->next;
}
printf("\n");
}
int isNotEmpty(struct Stack *top)
{
if(top!=NULL)
return 1;
else
return 0;
}
int main(void)
{
struct Stack *top=NULL;
int i=0,y,flag=0;
char str[]="((A+B)+(C+D)>",op;
printf("\n Running the programe to check if the string is balanced or not ");
for(i=0;str[i]!='\0';++i)
{
if( str[i] == '(' || str[i] == '[' || str[i] == '{' || str[i] == '<' )
push(&top,str[i]);
else if( str[i] == ')' || str[i] == ']' || str[i] == '}' || str[i] == '>')
{
y=pop(&top,str[i]);
if(!y)
{
printf("\n Unbalanced Expression ");
flag=1;
}
}
}
if(!flag)
{
if(isNotEmpty(top))
printf(" \nUnbalanced Expression ");
else
printf(" \n Balanced Expression ");
}
printf("\n");
return 0;
}
Check this code it is super easy and easy to understand
package com.codewithsouma.stack;
import java.util.Arrays;
import java.util.List;
import java.util.Stack;
public class Expression {
private final List<Character> leftBrackets = Arrays.asList('(','{','[','<');
private final List<Character> rightBrackets = Arrays.asList(')','}',']','>');
public boolean isBalanced(String input) {
Stack<Character> stack = new Stack<>();
for (char ch : input.toCharArray()) {
if (isLeftBracket(ch))
stack.push(ch);
if (isRightBracket(ch)) {
if (stack.isEmpty()) return false;
char top = stack.pop();
if (!bracketsMatch(top,ch)) return false;
}
}
return stack.isEmpty();
}
private boolean isRightBracket(char ch) {
return rightBrackets.contains(ch);
}
private boolean isLeftBracket(char ch) {
return leftBrackets.contains(ch);
}
public boolean bracketsMatch(char left, char right){
return leftBrackets.indexOf(left) == rightBrackets.indexOf(right);
}
}
At first, we create a hash table and store all brackets, left brackets are key and the value is its corresponding right brackets. Then we take an expression string from the user and create a character array. then we iterate the array and take a character then we check is this character left brackets or not if it is left bracket then we put into the stack (leftBracketContainer) otherwise we check is it the right bracket if right bracket then we pop the left bracket from the stack and find the closing bracket/ opposite bracket from the hash table and matching the current character/bracket if not matched ( for example our stack contain { this bracket so its closing bracket is } we find from the hash map and our current character = ] current character != opposite bracket ) return false otherwise we continue. At last when loop over then stack should empty. (if stack contain one more left bracket that means our expression needs another right bracket) if stack empty that means our expression is balanced otherwise not.
N:B when we check left bracket or not using isItLeftBracket(ch) then we check is our map contains the keys because all keys are left brackets like the ways we cheak right bracket by using isItRightBracket(ch) here we chake our map contains the value because all the value of the map are right bracket
package com.codewithsouma.stack;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
public class BalancedExpressionUsingMap {
private final Map<Character,Character> map;
public BalancedExpressionUsingMap() {
this.map = new HashMap<>();
map.put('(',')');
map.put('[',']');
map.put('<','>');
map.put('{','}');
}
public boolean isBalanced(String expression){
Stack<Character> leftBracketContainer = new Stack<>();
char [] arrayOfCharacter = expression.toCharArray();
for (char ch : arrayOfCharacter) {
if(isItLeftBracket(ch))
leftBracketContainer.push(ch);
else if(isItRightBracket(ch)){
if(leftBracketContainer.isEmpty()) return false;
char leftBracket = leftBracketContainer.pop();
char oppositeBracket = getOppositeBracket(leftBracket);
if (oppositeBracket != ch) return false;
}
}
return leftBracketContainer.isEmpty();
}
private char getOppositeBracket(char leftBracket) {
return map.get(leftBracket);
}
private boolean isItRightBracket(char ch) {
return map.containsValue(ch);
}
private boolean isItLeftBracket(char ch) {
return map.containsKey(ch);
}
}
Instead of allocating a stack for the delimiters, you can use a recursive function that skips balanced subexpressions and returns NULL upon mismatches:
#include <stdio.h>
const char *check(const char *s, char open) {
while (*s) {
switch (*s++) {
case ')': return (open == '(') ? s : NULL;
case ']': return (open == '[') ? s : NULL;
case '}': return (open == '{') ? s : NULL;
case '>': return (open == '<') ? s : NULL;
case '(':
case '[':
case '{':
case '<':
s = check(s, s[-1]);
if (s == NULL)
return NULL;
break;
}
}
if (open) {
/* closing delimiter not found */
return NULL;
}
return s;
}
void test(const char *s) {
printf("%s -> %s\n", s, check(s, 0) ? "Balanced" : "Unbalanced");
}
int main() {
test("((A+B)+(C+D))");
test("((A+B))+(C+D))");
test("((A+B)+(C+D)");
test("((A+B)+(C+D})");
return 0;
}
Output:
((A+B)+(C+D)) -> Balanced
((A+B))+(C+D)) -> Unbalanced
((A+B)+(C+D) -> Unbalanced
((A+B)+(C+D}) -> Unbalanced
Note that contrary to your assertion, ((A+B))+(C+D)) is unbalanced.

Resources