below is the code of infix to postfix conversion using stack.The code executes an infinite loop printing stack underflow in one of the pop function ,i have tried commenting pop function call in right paranthesis loop but then there is no output, i am unable to find which pop function creates this problem . if anyone could help me find what the problem is it would be appreciated.
P.S. - The code works fine if i remove parenthesis from the infix equation that i am passing.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stack{
int size;
int top;
char *arr;
};
void display(struct stack *ptr)
{
if(ptr->top == -1)
{
printf("Stack is Empty");
}
else
{
for(int i = ptr->top ; i>=0 ; i--)
{
printf("Element: %d\n",ptr->arr[i]);
}
}
}
int isEmpty(struct stack *ptr)
{
if(ptr->top == -1)
{
return 1;
}
else
{
return 0;
}
}
int isFull(struct stack *ptr)
{
if(ptr->top == ptr->size - 1)
{
return 1;
}
else
{
return 0;
}
}
void push(struct stack *ptr,int data)
{
if(isFull(ptr))
{
printf("Stack Overflow");
}
else
{
ptr->top = ptr->top + 1;
ptr->arr[ptr->top] = data;
}
}
char pop(struct stack *ptr)
{
if(isEmpty(ptr))
{
printf("Stack Underflow");
return 0;
}
else
{
char ch = ptr->arr[ptr->top];
ptr->top = ptr->top - 1;
return ch;
}
}
char stackTop(struct stack *ptr)
{
return ptr->arr[ptr->top];
}
int isOperator(char a)
{
if(a == '+'|| a == '-'|| a == '*'|| a == '/')
{
return 1;
}
else
{
return 0;
}
}
int precedence(char a)
{
if(a == '*' || a == '/')
{
return 3;
}
else if(a == '+' || a == '-')
{
return 2;
}
else
{
return -1;
}
}
char* infix_postfix(char *infix)
{
struct stack *sp = (struct stack *) malloc(sizeof(struct stack));
sp->size = 100;
sp->top = -1;
sp->arr = (char *) malloc(sp->size * sizeof(char));
char *postfix = (char *) malloc((strlen(infix+1)) * sizeof(char));
int i=0;
int j=0;
while(infix[i] != '\0')
{
if(infix[i] == '(')
{
push(sp,infix[i]);
i++;
}
else if(infix[i] == ')')
{
while(!(isEmpty(sp)) && stackTop(sp) != '(')
{
postfix[j] = pop(sp);
j++;
}
pop(sp);
}
else if(!isOperator(infix[i]))
{
postfix[j] = infix[i];
i++;
j++;
}
else
{
while(!(isEmpty(sp)) && precedence(infix[i])<=precedence(stackTop(sp)))
{
postfix[j] = pop(sp);
j++;
}
push(sp,infix[i]);
i++;
}
}
while(!isEmpty(sp))
{
postfix[j] = pop(sp);
j++;
}
postfix[j] = '\0';
return postfix;
}
int main(void)
{
char *infix = "(x-y/z-k*d)";
printf("postfix is %s",infix_postfix(infix));
return 0;
}
Code stuck on ')'.
Adding a i++; somewhere in the else if(infix[i] == ')') { .... } block resulted in below. Else code continues to parse ')'.
postfix is xyz/-kd*-
How bug was found:
Added a debug print.
while (infix[i] != '\0') {
printf("Infix: %d %c\n", infix[i], infix[i]); // added
That led to see code stuck when ')' was parsed.
Related
while (!isEmpty(s))
{
*c = pop(s);
strcat(postfix, c);
strcat(postfix, " ");
}
This is where the crash happens specifically at the *c line. When i display the stack it has a value of 43.00000 which means it contains the '+' in ASCI code.
I also used these 3 lines above this specific one in two loops which gave no error.
float pop(stack *s)
{
float x = s->top->data;
node *temp = s->top;
s->top = s->top->next;
free(temp);
return x;
}
Here is the pop function.
Also this works in vscode and the crashes happen in codeblocks only
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
typedef struct node
{
float data;
struct node *next;
} node;
typedef struct
{
node *top;
} stack;
node *newNode(float x)
{
node *n = malloc(sizeof(node));
n->data = x;
n->next = NULL;
return n;
}
stack *init()
{
stack *s = malloc(sizeof(stack));
s->top = NULL;
return s;
}
float pop(stack *s)
{
float x = s->top->data;
node *temp = s->top;
s->top = s->top->next;
free(temp);
return x;
}
void push(stack *s, float x)
{
node *n = newNode(x);
if (s->top == NULL)
s->top = n;
else
{
n->next = s->top;
s->top = n;
}
}
float peek(stack *s)
{
float x = s->top->data;
return x;
}
int isEmpty(stack *s)
{
return (s->top == NULL);
}
void display(stack *s)
{
stack *temp = init();
while (!isEmpty(s))
push(temp, pop(s));
while (!isEmpty(temp))
{
printf("%f ", peek(temp));
push(s, pop(temp));
}
printf("\n");
}
int priority(char op)
{
if (op == '+' || op == '-')
return 1;
if (op == '*' || op == '/')
return 2;
if (op == '^')
return 3;
else
return 0;
}
int isOperator(char op[5])
{
if (!strcmp(op, "+") || !strcmp(op, "-") || !strcmp(op, "*") || !strcmp(op, "/") || !strcmp(op, "^") || !strcmp(op, "(") || !strcmp(op, ")"))
return 1;
else
return 0;
}
int isDigit(char digit[20])
{
int i = 0;
if (digit[0] == '-')
i++;
for (i; digit[i] != '\0'; i++)
if (!isdigit(digit[i]) && digit[i] != '.')
return 0;
return 1;
}
char *infixToPostfix(char *infix)
{
char postfix[100] = "", tokens[20][2000], *temptok, *c;
int i = 0;
temptok = strtok(infix, " ");
strcpy(tokens[i++], temptok);
while (temptok != NULL)
{
temptok = strtok(NULL, " ");
if (temptok != NULL)
strcpy(tokens[i++], temptok);
}
int ntok = i;
stack *s = init();
for (i = 0; i < ntok; i++)
{
if (isDigit(tokens[i]) && strcmp(tokens[i], "-"))
{
strcat(postfix, tokens[i]);
strcat(postfix, " ");
}
else if (isOperator(tokens[i]))
{
if (isEmpty(s))
push(s, tokens[i][0]);
else if (tokens[i][0] == '(')
push(s, tokens[i][0]);
else if (tokens[i][0] == ')')
{
while (peek(s) != '(')
{
*c = pop(s);
strcat(postfix, c);
strcat(postfix, " ");
}
pop(s);
}
else
{
while (!isEmpty(s) && priority(peek(s)) >= priority(tokens[i][0]) && tokens[i][0] != '(')
{
*c = pop(s);
strcat(postfix, c);
strcat(postfix, " ");
}
push(s, tokens[i][0]);
}
}
}
display(s);
system("pause");
while (!isEmpty(s))
{
*c = pop(s);
strcat(postfix, c);
strcat(postfix, " ");
}
strcpy(infix, postfix);
return infix;
}
int main()
{
char infixExpr[256] = "";
printf("Enter an expression you want to evaluate or Ctrl+Z to exit: ");
while (fgets(infixExpr, 255, stdin) != NULL)
{
replaceNewLineBySpace(infixExpr);
char *postfix = infixToPostfix(infixExpr);
printf("Postfix : %s\n", postfix);
float result = evaluatePostfix(postfix);
printf("Result: %f\n", result);
system("pause");
// exit(1);
}
return 0;
}
Below is the code for infix to prefix conversion. My code works fine until the use of reverse function where it does not print any string after copying. I have tried using a for loop to copy the reversed string but the outcome remains the same and the program terminates without giving proper output. Print statements in the reverse function work before copying but not after that. Could anyone let me know where the problem is?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stack{
int size;
int top;
char *arr;
};
void display(struct stack *ptr)
{
if(ptr->top == -1)
{
printf("Stack is Empty");
}
else
{
for(int i = ptr->top ; i>=0 ; i--)
{
printf("Element: %d\n",ptr->arr[i]);
}
}
}
int isEmpty(struct stack *ptr)
{
if(ptr->top == -1)
{
return 1;
}
else
{
return 0;
}
}
int isFull(struct stack *ptr)
{
if(ptr->top == ptr->size - 1)
{
return 1;
}
else
{
return 0;
}
}
void push(struct stack *ptr,int data)
{
if(isFull(ptr))
{
printf("Stack Overflow");
}
else
{
ptr->top = ptr->top + 1;
ptr->arr[ptr->top] = data;
}
}
char pop(struct stack *ptr)
{
if(isEmpty(ptr))
{
printf("Stack Underflow");
return 0;
}
else
{
char ch = ptr->arr[ptr->top];
ptr->top = ptr->top - 1;
return ch;
}
}
char stackTop(struct stack *ptr)
{
return ptr->arr[ptr->top];
}
int isOperator(char a)
{
if(a == '+'|| a == '-'|| a == '*'|| a == '/')
{
return 1;
}
else
{
return 0;
}
}
int precedence(char a)
{
if(a == '*' || a == '/')
{
return 3;
}
else if(a == '+' || a == '-')
{
return 2;
}
else
{
return -1;
}
}
char * reverse(char exp[])
{
int l = strlen(exp);
int j = 0;
char temp[l];
for(int i=l-1;i>=0;i--,j++)
{
temp[j] = exp[i];
}
temp[j] = '\0';
printf("prefix is %s",temp);
strcpy(exp,temp);
// for(int i=0;i<=l;i++)
// {
// exp[i] = temp[i];
// }
printf("prefix is %s",exp);
return exp;
}
char * infix_prefix(char *infix)
{
struct stack *sp = (struct stack *) malloc(sizeof(struct stack));
sp->size = 100;
sp->top = -1;
sp->arr = (char *) malloc(sp->size * sizeof(char));
char *prefix = (char *) malloc((strlen(infix+1)) * sizeof(char));
infix = reverse(infix);
int i=0;
int j=0;
while(infix[i] != '\0')
{
if(infix[i] == ')')
{
push(sp,infix[i]);
i++;
}
else if(infix[i] == '(')
{
while(!isEmpty(sp) && stackTop(sp) != ')')
{
prefix[j] = pop(sp);
j++;
}
if(!isEmpty(sp))
{
pop(sp);
i++;
}
else
{
printf("Incorrect Expression");
exit(0);
}
}
else if(!isOperator(infix[i]))
{
prefix[j] = infix[i];
i++;
j++;
}
else if(isOperator(infix[i]))
{
while(!isEmpty(sp) && precedence(infix[i])<=precedence(stackTop(sp)))
{
prefix[j] = pop(sp);
j++;
}
push(sp,infix[i]);
i++;
}
else
{
printf("Incorrect expression");
exit(0);
}
}
while(!isEmpty(sp) && stackTop(sp) != '(')
{
prefix[j] = pop(sp);
j++;
}
if(stackTop(sp) == ')')
{
printf("Incorrect expression");
exit(0);
}
prefix = reverse(prefix);
prefix[j] = '\0';
return prefix;
}
int main(void)
{
char *infix = "(x-y/z-k*d)";
printf("prefix is %s",infix_prefix(infix));
return 0;
}
The reverse indeed has a problem: the temp array is defined with a length of l: that's not long enough to store the null terminator at temp[j] after the loop, causing undefined behavior.
There are more problems:
char *prefix = (char *) malloc((strlen(infix+1)) * sizeof(char)); does not allocate enough space for a copy of infix. You should write char *prefix = malloc(strlen(infix) + 1);
infix = reverse(infix); will crash because the argument to infix_prefix is a string literal which must not be modified. You should declare the argument as const char *infix and make a modifiable copy with strdup() if reversing is really needed, which I doubt very much.
Here is a modified version of reverse that performs the reverse operation in place:
char *reverse(char exp[]) {
int i = 0;
int j = strlen(exp);
while (j-- > i) {
char c = exp[j];
exp[j] = exp[i];
exp[i++] = c;
}
return exp;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stack {
int size;
int top;
char *arr;
};
int isEmpty(struct stack *ptr) {
if (ptr->top == -1)
{
return 1;
}
else
{
return 0;
}
}
int isFull(struct stack *ptr) {
if (ptr->top == ptr->size - 1)
{
return 1;
}
else
{
return 0;
}
}
int push(struct stack *ptr, int val) {
if (isFull(ptr))
{
return -1;
}
else
{
ptr->top++;
ptr->arr[ptr->top] = val;
}
return 1;
}
int pop(struct stack *ptr) {
if (isEmpty(ptr))
{
return -1;
}
else
{
ptr->top--;
int val = ptr->arr[ptr->top];
return val;
}
}
int stackTop(struct stack *ptr) {
return ptr->arr[ptr->top];
}
int precedence(char ch) {
if (ch == '/' || ch == '*')
{
return 3;
}
else if (ch == '+' || ch == '-')
{
return 2;
}
else
{
return 0;
}
}
int isOperand(char ch) {
if (ch == '+' || ch == '-' || ch == '/' || ch == '*')
{
return 1;
}
else
{
return 0;
}
}
char IntoPostFix(char *Infix) {
struct stack *s = (struct stack *)malloc(sizeof(struct stack));
s->top = -1;
s->size = 100;
s->arr = (char *)malloc(s->size * sizeof(char));
char *postfix = (char *)malloc(strlen(Infix + 1) * sizeof(char));
int i = 0; //value at intfix;
int j = 0; //store into post fix
while (Infix[i] != '\0')
{
if (!isOperand(Infix[i]))
{
postfix[j] = Infix[i];
i++;
j++;
}
else
{
if (precedence(Infix[i]) > precedence(stackTop(s)))
{
push(s, Infix[i]);
i++;
}
else
{
postfix[j] = pop(s);
j++;
}
}
}
while (!isEmpty(s))
{
postfix[j] = pop(s);
j++;
}
postfix[j] = '\0';
return postfix[j];
}
int main() {
char *Infix = "a-b";
printf("PostFix is : %s\n ", IntoPostFix(Infix));
return 0;
}
You format string expects a string but you give it a char:
printf("PostFix is : %s\n ", IntoPostFix(Infix));
Change the signature and return postfix instead of the '\0':
char *IntoPostFix(char *Infix) {
...
return postfix;
}
It now prints "ab\n ", that is, we correctly process 'a', 'b', and '-' is pushed on the stack. pop(s) return 0 you decrement top before you return the value:
ptr->top--;
int val = ptr->arr[ptr->top];
return val;
instead do:
return ptr->arr[ptr->top--];
and voila:
PostFix is : ab-
Bonus round:
In IntoPostFix you call malloc() 3 times and don't call free() so your program leaks memory.
Instead of strlen(Infix + 1) which evaluates to strlen(Infix) - 1 you want strlen(Infix) + 1.
Instead of while (Infix[i] != '\0') consider using a for() loop to reduce the scope of the variable i. Avoid negation and use continue for less branching noise. If you use this style of compressing newlines you get about twice as much code on the screen at a time:
for(int i = 0; Infix[i]; ) {
if(isOperand(Infix[i])) {
if(precedence(Infix[i]) > precedence(stackTop(s))) {
push(s, Infix[i++]);
} else {
postfix[j++] = pop(s);
}
continue;
}
postfix[j++] = Infix[i++];
}
I've been trying implementing Infix to Postfix using Stack(using LL) in C Language. When I first executed the code with input like(e.g: a+b/c*d-e) it's showing the correct notation from infix to postfix. So I think Everything is working fine but after modifying the code to accept input consisting brackets when I'm trying to input expressions having brackets its gets stuck mid way of execution. I don't know why?
Please help me.
Thanks in Advance
Below is the Code
#include <stdlib.h>
struct stackPara
{
char data;
struct stackPara *next;
};
int isEmpty(struct stackPara *top)
{
if (top == NULL)
return 1;
else
return 0;
}
int isFull(struct stackPara *top)
{
struct stackPara *p = (struct stackPara *)malloc(sizeof(struct stackPara));
if (p == NULL)
return 1;
else
return 0;
}
struct stackPara *pushStack(struct stackPara *top, char n)
{
struct stackPara *ptr = (struct stackPara *)malloc(sizeof(struct stackPara));
ptr->data = n;
if (!isFull(top))
{
ptr->next = top;
top = ptr;
//printf("Insert %c\n", top->data);
}
else
{
printf("Stack is FULL");
}
return top;
}
char popStack(struct stackPara **top)
{
char x = '\0';
struct stackPara *p = (*top);
if (!isEmpty((*top)))
{
x = (*top)->data;
(*top) = (*top)->next;
free(p);
}
else
{
printf("Stack is Empty");
}
return x;
}
void displayLL(struct stackPara *ptr)
{
// struct stackPara *ptr=top;
printf("Elements of Stack are:\n");
while (ptr != NULL)
{
printf("Data:%d\n", ptr->data);
ptr = ptr->next;
}
}
int isOperand(char ch)
{
return (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '1' && ch <= '9');
}
int isOperator(char ch)
{
if (ch == '+' || ch == '-')
return 1;
if (ch == '*' || ch == '/')
return 2;
if (ch == '^')
return 3;
return 0;
}
void infixToPostfix(char *exp)
{
struct stackPara *top = NULL;
for (int i = 0; exp[i] != '\0'; i++)
{
if (isOperator(exp[i]))
{
if (isEmpty(top))
{
top = pushStack(top, exp[i]);
// printf("%c",exp[i]);
// displayLL(top);
}
else
{
if (isOperator(exp[i]) > isOperator(top->data))
{
top = pushStack(top, exp[i]);
}
else
{
while (!isEmpty(top))
{
if (isOperator(exp[i]) <= isOperator(top->data))
{
printf("%c", popStack(&top));
}
}
top = pushStack(top, exp[i]);
}
}
}
if (isOperand(exp[i]))
{
printf("%c", exp[i]);
}
if (exp[i] == '(')
top = pushStack(top, exp[i]);
else if (exp[i] == ')')
{
while (top->data != '(')
{
printf("%c", popStack(&top));
}
if (top->data == '(')
{
popStack(&top);
}
else
{
printf("INVALID EXPRESSION");
break;
}
}
}
while (!isEmpty(top))
{
printf("%c", popStack(&top));
}
}
int main()
{
char *exp = "a+b*(c^d-e)^(f+g*h)-i\0";
infixToPostfix(exp);
return 0;
}```
> Output of Above Code:
>
> **abcd^**
It's a program for checking balance of parenthesis in C using a stack but it is not working as expected.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char data;
struct node *next;
};
struct node *top = NULL; //top stores address of top element of stack
void push(char data) { //inserting element
struct node *temp = (node *)malloc(sizeof(struct node));
temp->data = data;
temp->next = NULL;
if (top == NULL) {
top = temp;
return;
}
temp->next = top;
top = temp;
}
void pop() { //removing element
struct node *temp = top;
if (top == NULL) {
printf("No element to delete");
return;
}
top = top->next;
free(temp);
}
char Top() { //fn tht return top element of stack
return top->data;
}
int isEmpty() {
if (top != NULL) {
return 1;
} else
return 0;
}
int ArePair(char opening, char closing) {
if (opening == '(' && closing == ')')
return 1;
else if (opening == '{' && closing == '}')
return 1;
else if (opening == '[' && closing == ']')
return 1;
return 0;
}
int Arebalanced(char exp[]) {
int i;
for (i = 0; i < strlen(exp); i++) {
if (exp[i] == '(' || exp[i] == '{' || exp[i] == '[')
push(exp[i]);
else if (exp[i] == ')' || exp[i] == '}' || exp[i] == ']') {
if (isEmpty() || !ArePair(Top(), exp[i]))
return 0;
else
pop();
}
}
return isEmpty() ? 1 : 0;
}
int main() {
int i;
char a[50];
printf("Enter expession: ");
gets(a);
if (Arebalanced(a)) {
printf("balanced \n");
} else
printf("not balanced\n");
}
Function isEmpty() seems incorrect: it returns 1 if the stack is not empty?
Try this version:
int isEmpty() { return top == NULL; }
And do not use gets():
int main(void) {
char a[50];
printf("Enter expression: ");
if (fgets(a, sizeof a, stdin)) {
if (Arebalanced(a)) {
printf("balanced \n");
} else {
printf("not balanced\n");
}
}
return 0;
}