I am trying to write a program to check if a string of brackets is balanced or not. If balanced, I do not want any output. But if it is not balanced then I want it to return the brackets needed to balance it. For example '([])' should be balanced and '({}' should be unbalanced and should return "open: )". The code seems to work fine until I have two or more brackets left open. So if I input '({' my code works but when I add a few more characters like '([])([' it fails because of a stack overflow. I do not understand what the error could be or how to fix it.
Here is my code:
void push(struct sNode** top_ref, int new_data){
struct sNode* new_node = (struct sNode*)malloc(sizeof(struct sNode));
if (new_node == NULL) {
printf("Stack overflow \n");
getchar();
exit(0);
}
new_node->data = new_data;
new_node->next = (*top_ref);
(*top_ref) = new_node;
}
int pop(struct sNode** top_ref){
char res;
struct sNode* top;
if (*top_ref == NULL) {
printf("Stack overflow \n");
getchar();
exit(0);
}else {
top = *top_ref;
res = top->data;
*top_ref = top->next;
free(top);
return res;
}
}
// Returns 1 if character1 and character2 are matching left and right Brackets
bool isMatchingPair(char character1, char character2)
{
if (character1 == '(' && character2 == ')')
return 1;
else if (character1 == '{' && character2 == '}')
return 1;
else if (character1 == '[' && character2 == ']')
return 1;
else
return 0;
}
// Return 1 if expression is balanced
int areBracketsBalanced(char exp[]){
int i = 0;
struct sNode* stack = NULL;
while (exp[i]){
if (exp[i] == '{' || exp[i] == '(' || exp[i] == '[')
push(&stack, exp[i]);
if (exp[i] == '}' || exp[i] == ')' || exp[i] == ']') {
if (stack == NULL){
printf("%d:%c\n",i,exp[i]);
return 0;
}else if (!isMatchingPair(pop(&stack), exp[i])){
printf("%d:%c\n",i,exp[i]);
return 0;
}
}
i++;
}
if (stack != NULL){
printf("open: ");
while(stack!=NULL){
if(pop(&stack)=='('){
printf("%c",')');
}else if(pop(&stack)=='['){
printf("%c",']');
}else if(pop(&stack)=='{'){
printf("%c",'}');
}
}
printf("\n");
return 0;
}
return 0;
}
int main(int argc, char* argv[])
{
char *exp = (char *)malloc(strlen(argv[1]) * sizeof(char));
for(int i = 0; i<strlen(argv[1]); i++){
exp[i] = argv[1][i];
}
//char exp[] = "([])([";
areBracketsBalanced(exp);
return 0;
}
As it has been pointed out in comments, your exp in main is wrong as it end up without a zero termination. Actually there is no need for it... just pass argv[1] to the function.
int main(int argc, char* argv[])
{
if (argc > 1)
{
areBracketsBalanced(argv[1]);
}
else
{
puts("Missing argument");
}
return 0;
}
Besides that, you have a problem here:
while(stack!=NULL){
if(pop(&stack)=='('){
printf("%c",')');
}else if(pop(&stack)=='['){
printf("%c",']');
}else if(pop(&stack)=='{'){
printf("%c",'}');
}
}
Each of these pop(&stack) will change stack and maybe cause it to be NULL. At worst you do 3 pop-operations before checking for NULL. That's not good.
Change the code so that you have one pop operation before the if statements. Save the result in a local variable that you use for the if statement. Like:
while(stack!=NULL){
int value = pop(&stack);
if(value == '('){
printf("%c",')');
}else if(value == '['){
printf("%c",']');
}else if(value == '{'){
printf("%c",'}');
}
}
Related
I'm trying to implement a stack in C to convert infix to postfix. But after several days of trying, im still not sure whats wrong with my code! can someone help? I made sure the line of logic is right and did on paper a lot of times, I'm new to stack, please assist!
I'm not sure exactly where is going wrong, and after a few submissions, suddenly the same code would produce segmentation error (core dumped) without much explanation.
Examples of inputs like : (A+B)+(C-D) produces (AB)+(C+D)- As for debuggers, im sticking to simple print statements at various parts of the program, I find that theres a problem with popping the '(' at the else if (infix == ')')
Running the code in online IDEs like replit and codechef. replit produces segmentation fault(core dumped) while codechef is able to produce and run an output. <- abit confused here
EDIT: My parenthesis Else if statements arent working, but I dont see why so, I tried adding simple print statements in that else if segments but they are not showing too
#include <stdio.h>
#include <stdlib.h>
#define SIZE 1000 //The limit of expression length
typedef struct _stackNode{
char item;
struct _stackNode *next;
}StackNode;
typedef struct _stack{
int size;
StackNode *head;
}Stack;
void push(Stack *sPtr, char item);
int pop(Stack *sPtr);
char peek(Stack s);
int isEmptyStack(Stack s);
void in2Post(char*, char*);
int main()
{
char infix[SIZE];
char postfix[SIZE];
printf("Enter an infix expression:\n");
scanf("%[^\n]%*c",infix);
printf("This");
in2Post(infix,postfix);
printf("The postfix expression is \n");
printf("%s\n",postfix);
return 0;
}
void push(Stack *sPtr, char item){
StackNode *newNode;
newNode = (StackNode *) malloc(sizeof(StackNode));
newNode->item = item;
newNode->next = sPtr->head;
sPtr->head = newNode;
sPtr->size++;
}
int pop(Stack *sPtr){
if(sPtr == NULL || sPtr->head == NULL){
return 0;
}
else{
StackNode *temp = sPtr->head;
sPtr->head = sPtr->head->next;
free(temp);
sPtr->size--;
return 1;
}
}
char peek(Stack s){
return s.head->item;
}
int isEmptyStack(Stack s){
if(s.size == 0) return 1;
else return 0;
}
int precedence(char item)
{
if (item == '*' || item == '/')
{
return 2;
}
else if (item == '+' || item == '-')
{
return 1;
}
else
{
return 0; // if it is brackets return 0
}
}
int isOperand(char ch)
{
if (ch == '%' || ch == '/' || ch == '*' || ch == '+' || ch == '-')
{
return 0;
}
else
{
return 1;
}
}
int is_operator(char item)
{
if (item == '+' || item == '-' || item == '*' || item == '/')
{
return 1;
}
else
{
return 0;
}
}
void in2Post(char* infix, char* postfix)
{
//Write your code here
Stack* stack = (Stack*)malloc(sizeof(Stack));
stack->head = NULL;
if (!stack)
return;
int i = 0;
int j = 0;
while (infix[i] != '\0')
{
if (isOperand(infix[i]) && infix[i] != ')' && infix[i] != '(') //NEED TO MAKE SURE HERE ISNT A PARENTHESIS
{
postfix[j]=infix[i];
j++;
}
else if (infix[i] == '(')
{
push(stack, infix[i]);
}
else if (infix[i] == ')')
{
while (!isEmptyStack(*stack) && peek(*stack) != '(')
{
postfix[j] = peek(*stack);
j++;
pop(stack);
if (!isEmptyStack(*stack) && peek(*stack) !='(' )
{
return; // POPPING TILL REACH '(' IF IT IS NOT '(', RETURN
}
else
{
pop(stack); // removing the ()
}
}
}
else // an OPERATOR IS ENCOUNTERED
{
while (!isEmptyStack(*stack) && precedence(infix[i])<=precedence(peek(*stack)))
{
postfix[j] = peek(*stack);
pop(stack);
j++;
}
push(stack, infix[i]);
}
i++;
}
while (!isEmptyStack(*stack))
{
postfix[j] = peek(*stack);
pop(stack);
j++;
}
postfix[j] = '\0';
printf("THIS IS POSTFIX %s\n", postfix);
}
The first IF statement did not take into account the character might be a parenthesis. Also, the size of the stack is not initialized.
I am trying to code Balanced brackets using Stack as Linked List in C. The problem I am facing is that when the test case value is 3 , the first two test cases are working fine but the last one is showing NO always as output.
for eg:
if the input is:
3
{[()]}
{[(])}
{{[[(())]]}}
The expected output is:
YES
NO
YES
The actual output is:
YES
NO
NO
#include <stdio.h>
#include <stdlib.h>
struct Node
{
char data;
struct Node *next;
}*top = NULL;
void push(char x)
{
struct Node *t;
t = (struct Node *)malloc(sizeof(struct Node));
if(t == NULL)
printf("Stack is Overflow\n");
else
{
t->data = x;
t->next = top;
top=t;
}
}
char pop()
{
char x = -1;
struct Node *p;
if(top == NULL)
printf("Stack is Underflow\n");
else
{
p=top;
top=top->next;
x=p->data;
free(p);
}
return x;
}
int isEmpty()
{
return top?0:1;
}
char stackTop()
{
if(!isEmpty())
return top->data;
return '0';
}
int isBalanced(char *exp)
{
int i;
for(i=0;exp[i]!='\0';i++)
{
if(exp[i] == '(' || exp[i] == '{' || exp[i] == '[')
push(exp[i]);
else if(exp[i] == ')' || exp[i] == '}' || exp[i] == ']')
{
if(isEmpty())
return 0;
if(stackTop() == '(' && exp[i] == ')')
pop();
else if(stackTop() == '{' && exp[i] == '}')
pop();
else if(stackTop() == '[' && exp[i] == ']')
pop();
else
return 0;
}
}
if(isEmpty())
return 1;
else
return 0;
}
int main()
{
char *exp;
int t;
scanf("%d",&t);
while(t--)
{
exp = (char*)malloc(10000*sizeof(char));
scanf("%s",exp);
if(isBalanced(exp))
printf("YES\n");
else
printf("NO\n");
free(exp);
}
return 0;
}
You forgot to reset the stack after dealing with each cases.
while(t--)
{
exp = (char*)malloc(10000*sizeof(char));
scanf("%s",exp);
if(isBalanced(exp))
printf("YES\n");
else
printf("NO\n");
free(exp);
while (!isEmpty()) pop(); /* add this */
}
I'm writing code to convert Infix expression into Postfix and Prefix at the same time.
My problem is I haven't been able to convert into the prefix expression. In my intoprefix() I tried everything, but still the output will same as to the postfix.
Where if i input this expression
A+B
The expected output would be
Postfix expression is: AB+
Prefix expression is: +AB
but my output is
Postfix expression is: AB+
Prefix expression is: AB+AB+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stack{
char data;
struct Stack *next;
}*top = NULL, *pstart = NULL;
char str[50];
int main(int argc, char **argv){
printf("Enter infix expression: ");
gets(str);
printf("\n\nEquivalent postfix expression is: ");
intopostfix(str);
printf("\n\nEquivalent prefix expression is: ");
intoprefix(str);
printf("\n");
return 0;
}
/* function for insert operation */
void insert(char ch){
struct Stack *ptr,*newNode;
newNode = (struct Stack *)malloc(sizeof(struct Stack));
newNode->next = NULL;
newNode->data = ch;
ptr = pstart;
if(pstart == NULL){
pstart = newNode;
}
else{
while(ptr->next != NULL)
ptr = ptr->next;
ptr->next = newNode;
}
}
/* function for push operation */
void push(char symbol){
struct Stack *ptr;
ptr = (struct Stack *)malloc(sizeof(struct Stack));
ptr->data = symbol;
if(top == NULL){
top = ptr;
ptr->next = NULL;
}
else{
ptr->next = top;
top = ptr;
}
}
char pop(){
struct Stack *ptr1;
char ch1;
if(top == NULL){
printf("Stack underflow\n");
return 0;
}
else{
ptr1 = top;
top = top->next;
ch1 = ptr1->data;
free(ptr1);
ptr1 = NULL;
return ch1;
}
}
/* function for display display operation */
void displaypost(){
struct Stack *temp;
if(pstart == NULL)
printf("");
else{
temp = pstart;
while(temp != NULL){
printf("%c",temp->data);
temp = temp->next;
}
}
}
/*function for precedence */
int precedence(char ch){
if(ch == '^'){
return (5);
}
else if(ch == '*' || ch == '/'){
return (4);
}
else if(ch == '+' || ch == '-'){
return (3);
}
else{
return (2);
}
}
/*function for converting infix to postfix */
void intopostfix(char str[]){
int length;
int index = 0;
char symbol, temp;
length = strlen(str);
while(length > index)
{
symbol = str[index];
switch(symbol){
case '(':
push(symbol);
break;
case ')':
temp = pop();
while(temp != '('){
insert(temp);
temp = pop();
}
break;
case '^':
case '+':
case '-':
case '*':
case '/':
if(top == NULL){
push(symbol);
}
else{
while(top != NULL && (precedence(top->data) >= precedence(symbol))){
temp = pop();
insert(temp);
}
push(symbol);
}
break;
default:
insert(symbol);
}
index = index + 1;
}
while(top != NULL){
temp = pop();
insert(temp);
}
displaypost();
return;
}
/*function to convert infix to prefix */
void intoprefix(char str[]){
int length;
int index = 0;
char symbol, temp;
length = strlen(str);
while(length > index)
{
symbol = str[index];
switch(symbol){
case ')':
temp = pop();
break;
case '(':
push(symbol);
while(temp != ')'){
insert(temp);
temp = pop();
}
break;
case '+':
case '-':
case '*':
case '/':
case '^':
if(top == NULL){
push(symbol);
}
else{
while(top != NULL && (precedence(top->data) <= precedence(symbol))){
temp = pop();
insert(temp);
}
push(symbol);
}
break;
default:
insert(symbol);
}
index = index + 1;
}
while(top != NULL){
temp = pop();
insert(temp);
}
displaypost();
return;
}
The program converts infix to postfix and prefix using linked lists (stacks)
Here are my observations and amendments:
Received a warning about gets. Have used fgets instead.gets is
dangerous as it may cause a buffer overflow.
Freed the storages allocated in the insert function.The presence of
these locations were causing the duplication of results,when
intoprefix was called.
Since you already have an intopostfix function, I utilized the same
to convert infix to prefix using the following algorithm. Please
refer.
Step 1:Reverse the infix expression. Note while reversing each ‘(‘ will
become ‘)’ and each ‘)’ becomes ‘(‘.
Step 2:Obtain the postfix expression of the modified expression.
Step 3:Reverse the postfix expression.
Made main the owner of the arrays that store the input and results, thus avoiding the use of "global variables" and requiring me to pass these variables explicitly.
Removed the displaypost function from within intopostfix and am
calling it from main.
void insert(char ch);//no changes made
void push(char symbol); //no changes made
char pop(); //no changes made
void displaypost(char * s);
int precedence(char ch); //no changes made
void intopostfix(char str[]); //removed the call to displaypost
int main(int argc, char **argv){
char str[50];
char prefix_str[50];//store postfix str
char postfix_str[50];//store prefix str
printf("Enter infix expression: ");
fgets(str,50,stdin);
str[strlen(str)-1] = '\0';//overwrite newline char with NULL
//reverse the original string and store in prefix_str
int i,j;
for(i = strlen(str)-1,j = 0;i >= 0;i--,j++){
if(str[i] == '(')
prefix_str[j] = ')';
else if(str[i] == ')')
prefix_str[j] = '(';
else
prefix_str[j] = str[i];
}
prefix_str[j] = '\0';
//Print Post Fix
printf("\n\nEquivalent postfix expression is: ");
intopostfix(str);
displaypost(postfix_str);
printf("%s",postfix_str);
//Print Prefix
intopostfix(prefix_str);
displaypost(prefix_str);
//reverse prefix_str
int temp;
for(i = 0,j = strlen(prefix_str)-1;i < j;i++,j--){
temp = prefix_str[i];
prefix_str[i] = prefix_str[j];
prefix_str[j] = temp;
}
printf("\n\nEquivalent prefix expression is: ");
printf("%s\n",prefix_str);
printf("\n");
return 0;
}
//changes in displaypost
void displaypost(char * s){
struct Stack *temp,*p;
if(pstart == NULL)
printf("");
else{
temp = pstart;
int i = 0;
while(temp != NULL){
p = temp;
s[i] = temp->data;//store character in array
temp = temp->next;
free(p);//free storage
i++;
}
s[i] = '\0';
}
pstart = NULL;
}
I'm need to verify if ()[]{} of a mathematical expression are all closed.
Such {4 + 9} − (9 − 8) << are correct and ((()) aren't correct.
Using a stack builded using linked list.
Like if the actual index of the string have "{" or "[" or "(" push it to stack and if the index have ")" or "]" or "}" pop the top of stack and verify if are matching with the actual element. If stack are empty in the end, expression are correct, or if during execution loop the closing symbol don't match or stack isn't empty, the expression aren't correct.
structs
struct stack{char string[1];int index;struct stack *next;};
struct retpop{char string[1];struct stack *top;};
functions pop/push
struct stack *push(struct stack *topo, char *se){
struct stack *temp;
if (top == NULL)
{
top =(struct stack *)malloc(sizeof(struct stack ));
top->next= NULL;
top->index = 0;
top->string[0] = 0;
snprintf(top->string, 1, "%c", se[0]);
}
else
{
temp =(struct stack *)malloc(sizeof(struct stack ));
temp->next = top;
temp->index = top->index + 1;
temp->string[0] = 0;
snprintf(temp->string, 1, "%c", se);
top = temp;
}
return top;
}
struct retpop pop(struct stack *top){
struct retpop return1;
if (top == NULL)
{
printf("EMPTY STACK\n");
return;
}
else{
struct stack *top1;
top1 = top;
snprintf(return1.string, 1, "%c", top1->string[0]);
top1 = top1->next;
free(top);
top = top1;
}
retorno.top = top;
return return1;
}
functions to analisis
void process_string(char string[100]){
struct stack *top;
top = NULL;
int i = 0;
struct stack *temp;
int nullifier = 0;
char *temp;
struct retpop temppop;
while(i < (strlen(string)-1)){
snprintf(temp, 1, "%c", string[i]);
if(temp[0] == '}'){
temppop = pop(top);
top = temppop.top;
if((char)temppop.string[0] != '{'){
nullifier = 1;
}
}
if(temp[0] == ']'){
temppop = pop(top);
top = temppop.top;
if((char)temppop.string[0] != '['){
nullifier = 1;
}
}
if(temp[0] == ')'){
temppop = pop(top);
top = temppop.top;
if((char)temppop.string[0] != '('){
nullifier = 1;
}
}
if(temp[0] == '{'){
top = push(top,"{");
}
if(temp[0] == '['){
top = push(top,"[");
}
if(temp[0] == '('){
top = push(top,"(");
}
i++;
}
if((topo != NULL) || (anulador == 1)){
printf("\nNOT VALID\n");
}
else{
printf("\nVALID\n");
}
}
The problem are, the code correctly analise things like []{}()or [][][][][] but when i use {}{}{}{}{} or ()()()()() or {[()()()][()()()]} the stack return buggy values and the expression became false :/ What can I do? The problem are on my code?
(please ignore the use of stack inside the code, on my code i'm using the other word from my language, but to display in a better way i placed "stack" on code)
For a component of an assignment for college we have to implement a stack, which I think I've done well enough for it to be functional. When I'm testing the stack by itself it seems to work fine, however when I'm using it as part of my solution it behaves differently, and I can't figure out why. Can someone please point out my mistake? Thanks.
Edit: I can feel a lot of "how does it behave differently?" comments are on the way, so here's what I've noticed. When running the Testing stack section of main, all the operations execute and print perfectly fine, but when I'm running the second part of main and comment out the testing part instead, the program crashes when I'm trying to push onto the stack - something that didn't fail previously.
main.c
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
struct stackNode {
char data;
struct stackNode *nextPtr;
};
typedef struct stackNode StackNode;
typedef StackNode *StackNodePtr;
typedef enum {
false, true
} t_bool;
void* emalloc(size_t s) {
void* p = malloc(s);
if (NULL == p) {
fprintf(stderr, "Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
return p;
}
void print_array(char* array, size_t n){
int i;
printf("[");
for(i = 0; i < n - 1; i++){
printf("%c, ", array[i]);
}
printf("%c]\n", array[i]);
}
// Determine if c is an operator.
int isOperator(char c) {
char ops [6] = {'+', '-', '*', '/', '%', '^'};
int i;
for (i = 0; i < 6; i++)
if (ops[i] == c) return true;
return false;
}
int op_priority(char c) {
if (c == '+' || c == '-') return 0;
else if (c == '*' || c == '/') return 1;
else if (c == '^' || c == '%') return 2;
return -1;
}
// Determine if the precedence of operator1 is less than, equal to, or greater than
// the precedence of operator2. The function returns -1, 0 and 1, respectively.
int precedence(char op1, char op2) {
int op1_p = op_priority(op1);
int op2_p = op_priority(op2);
if (op1_p < op2_p) return -1;
else if (op1_p > op2_p) return 1;
else return 0;
}
// Push a value on the stack.
void push(StackNodePtr *topPtr, char value) {
StackNodePtr temp = (StackNodePtr) emalloc(sizeof (StackNode));
temp->data = value;
temp->nextPtr = *topPtr;
*topPtr = temp;
}
// Pop a value off the stack.
char pop(StackNodePtr *topPtr) {
StackNodePtr t = *topPtr;
if (NULL != *topPtr) {
char c = t->data;
*topPtr = t->nextPtr;
free(t);
return c;
} else {
printf("Stack is empty.\n");
return '\0';
}
}
// Return the top value of the stack without popping the stack.
char peek(StackNodePtr topPtr) {
if (NULL != topPtr) {
return topPtr->data;
} else {
printf("Stack is empty.\n");
}
}
// Determine if the stack is empty.
int isEmpty(StackNodePtr topPtr) {
if (NULL == topPtr) return true;
return false;
}
// Prints the stack
void printStack(StackNodePtr topPtr) {
if (!isEmpty(topPtr)){
StackNodePtr t = topPtr;
while (NULL != t) {
printf("%c\t", t->data);
t = t->nextPtr;
}
printf("NULL\n");
} else {
printf("Stack is empty.\n");
}
}
// Convert the infix expression to postfix notation.
void convertToPostfix(char infix [], char postfix [], int expression_length) {
printf("At top of cnvToPostfix\n");
int infix_count = 0;
int postfix_count = 0;
////////////////////////////////////////////
StackNodePtr *stack;
push(stack, '(');
printStack(*stack);
////////////////////////////////////////////
infix[expression_length] = ')';
while (isEmpty(*stack)) {
char current = infix[infix_count++];
if (isdigit(current)) {
postfix[postfix_count++] = current;
} else if (current == '(') {
push(stack, current);
} else if (isOperator(current)) {
while (true) {
char top = peek(*stack);
if (isOperator(top) && precedence(current, top) >= 0) {
postfix[postfix_count++] = pop(stack);
} else {
break;
}
}
push(stack, current);
}
else if (current == ')') {
while (true) {
char top = peek(*stack);
if (top == '(') {
pop(stack);
break;
} else {
postfix[postfix_count++] = pop(stack);
}
}
}
}
}
int main() {
printf("Testing stack\n");
printf("Pushing 1, 2, and 3 onto stack, peeking and popping.\n");
StackNodePtr *stack;
push(stack, '1');
push(stack, '2');
push(stack, '3');
printf("Printing stack\n\n");
printStack(*stack);
printf("Peek: %c\n", peek(*stack));
printf("Pop: %c\n", pop(stack));
printf("Printing stack\n");
printStack(*stack);
/*
printf("Enter the infix expression.\n");
char c;
char infix [1024];
int count = 0;
while ((scanf("%c", &c)) == 1) {
if ((int) c == 10) break;
infix[count++] = c;
}
printf("The original infix expression is:\n");
print_array(infix, count);
char postfix [count];
convertToPostfix(infix, postfix, count);
printf("The expression in postfix notation is:\n");
print_array(postfix, count);
*/
return 0;
}
I see at least one immediate problem:
StackNodePtr *stack;
push(stack, '1');
Where is the initialisation for your stack? Use of uninitialised pointers is instant "undefined behaviour" territory.
If you look closely at your push code, you'll see it inserts the new item before the current one but set the new item's nextPtr pointer to the previous (uninitialised) value.
That means, the last item in the stack won't actually point to NULL.
You're not really initialising your stacks:
StackNodePtr *stack;
push(stack, '(');
It's also potentially confusing having StackNodePtr being a pointer type, and stack being a pointer to that type. You need to be clear in every possible usage how many levels of indirection should be applied.
To start with, imagine passing the new stack firstly to isEmpty:
StackNodePtr *stack;
printf("%d\n", isEmptypush(*stack));
What's isEmpty going to do on the value it is passed?
I think what you want instead is:
StackNodePtr stack = NULL;
push(&stack, '(');
Other uses of stack in that function should similarly be changed from *stack to stack, or stack to &stack.