Strange behaviour of do while - c

I was trying to implement a stack. I came up with this. All the other functions work as expected except when is try to push. When i try to push 4 some thing strange happens.
#include <stdio.h>
#include <stdlib.h>
#define MAX 10
typedef struct
{
int a[MAX];
int top;
}stack;
void init(stack *p)
{
p->top=-1;
}
int full(stack *p)
{
if(p->top==MAX)
return 1;
else
return 0;
}
int empty(stack *p)
{
if(p->top==-1)
{
init(p);
return 1;
}
else
return 0;
}
void display(stack *p)
{
if(!empty(p))
{
printf("Stack is::\n");
for(int i=0;i<=p->top;++i)
printf("%d\t",p->a[i]);
printf("\n");
}
else
{
printf("Stack is empty.\n");
init(p);
}
}
void push(stack *p, int x)
{
if(!full(p)) /*full() returns 1 is top==max, 0 otherwise*/
{
p->a[p->top++]=x;
printf("%d pushed.\n",x);
}
else
printf("Stack is full.\n");
}
void pop(stack *p)
{
if(!empty(p))
printf("%d popped.\n",p->a[p->top--]);
else
{
printf("Stack is empty.\n");
init(p);
}
}
int main()
{
stack p;
int ch,x;
printf("Hello world!\n");
init(&p);
printf("*****MENU*****\n");
do{
printf("1.Push\n2.Pop\n3.Display\n4.Exit\n");
printf("Enter your choice:: ");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("Enter element to push:: ");
scanf("%d",&x);
push(&p,x);
break;
case 2:
pop(&p);
break;
case 3:
display(&p);
break;
case 4:
exit(1);
}
}while(ch!=4);
return 0;
}
The program terminates.
I am testing the while loop with ch(=1) and not x(=4). So why is this happening??

This function
void push(stack *p, int x)
{
if(!full(p)) /*full() returns 1 is top==max, 0 otherwise*/
{
p->a[p->top++]=x;
printf("%d pushed.\n",x);
}
else
printf("Stack is full.\n");
}
is wrong. The initial value of top is -1 so in this statement
p->a[p->top++]=x;
you are trying to store the value in the element of the array with the index equal to -1.
Thus the program has undefined behaviour.
The function could look like
void push( stack *p, int x )
{
if ( !full( p ) ) /*full() returns 1 if top + 1 == max, 0 otherwise*/
{
p->a[++p->top]=x;
^^^^^^^^
printf("%d pushed.\n",x);
}
else
{
printf("Stack is full.\n");
}
}
Take into account that in this case function full should look like
int full( const stack *p )
{
return p->top + 1 == MAX;
^^^^^^^^^^
}
Function empty also can be written simpler
int empty( const stack *p )
{
return p->top == -1;
}
And a stack usually is printed in the reverse order relative to the order of entering elements
void display( const stack *p )
{
if ( !empty( p ) )
{
printf( "Stack is::\n" );
for ( int i = p->top; i != -1; --i )
printf( "%d\t", p->a[i] );
printf( "\n" );
}
else
{
printf( "Stack is empty.\n" );
}
}

Related

How can i find error in my code for the question for parenthesis matching? (C language)

Question is to to check in the character array if the parenthesis is matched or not using stack.
In my code i am not getting any output nor any error so i am unable to find my mistake.
At first i have made a structure for stack.
Then i have made functions to check whether the stack is empty or full to prevent conditions such as stack overflow or underflow.
Then i have made function for parenthesis checker
HERE IS MY CODE:
#include <stdio.h>
#include <stdlib.h>
//Initializing the stack with structures
struct stack
{
int size;
int top;
char *arr;
};
//function to check whether stack is empty
int isEmpty(struct stack *ptr)
{
if (ptr->top == -1)
{
return 1;
}
else
{
return 0;
}
}
//function to check whether stack is full
int isFull(struct stack *ptr)
{
if (ptr->top == (ptr->size - 1))
{
return 1;
}
else
{
return 0;
}
}
//Function for push
void push(struct stack *ptr, char val)
{
if (isFull(ptr))
{
printf("Stack Overflow, Cannot push more elements\n");
}
else
{
ptr->top++;
ptr->arr[ptr->top] = val;
}
}
//Function for pop
char pop(struct stack *ptr)
{
if (isEmpty(ptr))
{
printf("Stack Underflow, Unable to pop elements\n");
return -1;
}
else
{
char val;
val = ptr->arr[ptr->top];
ptr->top--;
return val;
}
}
//Function for parenthesis matching
int parenthesisChecker(char *exp)
{
struct stack *st;
st->size = 100;
//stack is empty for now
st->top = -1;
st->arr = (char *)malloc(st->size * sizeof(char));
int n_push = 0, n_pop = 0;
for (int i = 0; exp[i] != '\0'; i++)
{
//for open bracket push
if (exp[i] == '(')
{
push(st, '(');
n_push++;
}
//for closed bracket pop
else if (exp[i] == ')')
{
if (isEmpty(st))
{
return 0;
}
else
{
pop(st);
n_pop++;
}
}
}
printf("%d times push\n", n_push);
printf("%d times pop\n", n_pop);
if (isEmpty(st))
{
return 1;
}
else
{
return 0;
}
}
int main()
{
char *c = "akajvd)(()";
if (parenthesisChecker(c))
{
printf("Parenthesis is matched");
}
else
{
printf("Parenthesis is not matched");
}
return 0;
}
The pointer st within the function parenthesisChecker is not initialized and has an indeterminate value
struct stack *st;
So dereferencing the pointer like for example in this statement
st->size = 100;
invokes undefined behavior.
Also the function produces a memory leak because it does not free the memory allocated for the data member arr of the structure struct stack.
The function parameter should have the qualifier const because the passed string is not being changed within the function.
int parenthesisChecker( const char *exp );
And such functions as pop and push should not output any message. It is the caller of the functions that decides whether to output a message.
I would write the program the following way.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stack
{
size_t size;
size_t top;
char *arr;
};
struct stack make_stack( size_t size )
{
struct stack st = { .size = size, .top = 0, .arr = malloc( size ) };
if ( st.arr == NULL ) st.size = 0;
return st;
}
void free_stack( struct stack *st )
{
free( st->arr );
st->size = 0;
st->top = 0;
}
int isEmpty( const struct stack *st )
{
return st->top == 0;
}
int isFull( const struct stack *st )
{
return st->top == st->size;
}
int push( struct stack *st, char val )
{
int success = !isFull( st );
if ( success )
{
st->arr[st->top++] = val;
}
return success;
}
int pop( struct stack *st, char *val )
{
int success = !isEmpty( st );
if ( success )
{
*val = st->arr[--st->top];
}
return success;
}
int parenthesisChecker( const char *s )
{
int success = 1;
if ( *s != '\0' )
{
struct stack st = make_stack( strlen( s ) );
success = st.size != 0;
for ( ; success && *s; ++s )
{
if ( *s == '(' )
{
success = push( &st, *s );
}
else if ( *s == ')' )
{
char c;
success = pop( &st, &c );
}
}
success = success && isEmpty( &st );
free_stack( &st );
}
return success;
}
int main(void)
{
const char *s = "akajvd)(()";
if ( parenthesisChecker( s ) )
{
puts( "Parentheses are matched" );
}
else
{
puts( "Parentheses are not matched" );
}
return 0;
}
The program output is
Parentheses are not matched

Infix to Postfix program doesn't work as intended

This is my attempt to write a program that can convert any expression in infix to postfix format. I assign -1 to the top to indicate the stack is empty. When push, the top is incremented, when pop, the top is decremented. However, when I type in a+b, the output only gives me ab without the + operator, while when I type (a+b), it says segmentation fault. I reckon there's something wrong with my stack, but couldn't figure out what went wrong.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define SIZE 30
typedef struct Stack
{
int top;
int capacity;
char* storage;
} stack;
int isEmpty(stack* a);
char topelement(stack* a);
char pop(stack* a);
void push(stack* a,char b);
bool isOperand(char a);
int Precedence(char a);
stack* NewStack(char* a);
void InfixPostfix(char* a);
int main(void)
{
char expression[SIZE];
printf("Please enter an expression:");
scanf("%s",expression);
InfixPostfix(expression);
printf("\n");
}
int isEmpty(stack* a)
{
if(a->top==-1)
{
return 1;
}
else
return 0;
}
char topelement(stack* a)
{
return a->storage[a->top];
}
char pop(stack* a)
{
if(isEmpty(a)==1)
{
printf("Stack is Empty\n");
return '$';
}
else
return a->storage[a->top];
--(a->top);
}
void push(stack* a,char b)
{
++(a->top);
a->storage[a->top]=b;
}
bool isOperand(char a)
{
if ( (a >= 'a' && a<= 'z') ||(a>='A' && a<='Z'))
{
return 1;
}
else
return 0;
}
int Precedence(char a)
{
if(a=='+' || a=='-')
{
return 1;
}
if(a=='*' || a=='/')
{
return 2;
}
if(a=='^')
{
return 3;
}
else
return -1;
}
stack* NewStack(char* a)
{
stack* b= malloc(sizeof(stack));
if(b!=NULL)
{
b->top=-1;
b->storage=malloc((strlen(a))*sizeof(char));
return b;
}
else
return NULL;
}
void InfixPostfix(char* a)
{
int i; int j=-1;
stack* b=NewStack(a);
if(b!=NULL)
{
for(i=0; i<strlen(a) ;i++)
{
if(isOperand(a[i]))
{
a[++j]=a[i];
}
if(a[i]=='(')
{
push(b, a[i]);
}
if(a[i]==')')
{
while(isEmpty(b)==0 && topelement(b)!= '(')
{
a[++j]= pop(b);
}
}
else
{
while(isEmpty(b)==0 && Precedence(a[i]) <= Precedence(topelement(b)))
{
a[++j]=pop(b);
push(b,a[i]);
}
}
}
while(isEmpty(b)==0)
{
a[++j]=pop(b);
}
a[++j]='\0';
printf("%s",a);
}
}
Besides the already suggested malloc correction, there are a few more to make.
In pop() there's
return a->storage[a->top];
--(a->top);
where the last code line isn't reached; change that to return a->storage[a->top--];
In InfixPostfix(), else are missing before if(a[i]=='(') and if(a[i]==')').
In InfixPostfix(), after the loop
while(isEmpty(b)==0 && topelement(b)!= '(')
{
a[++j]= pop(b);
}
a pop(b); is missing - the element '(' must as well be removed from the stack.
In InfixPostfix(), the push(b,a[i]); must be removed from the loop
while(isEmpty(b)==0 && Precedence(a[i]) <= Precedence(topelement(b)))
{
a[++j]=pop(b);
push(b,a[i]);
}
and placed after that loop - the operator in a[i] has to be put onto the stack only once.

Circular Queue Operations Using Array

Code shows basic operations on Circular Queue.
#define maxsize 10
typedef struct queue
{
int data[maxsize];
int f,r;
}myQueue;
myQueue q;
void init(myQueue *q);
int full(myQueue *q);
int empty(myQueue *q);
void enqueue(myQueue *q,int num);
void dequeue(myQueue *q);
void print(myQueue *q);
void main()
{
init(&q);
int op;
do
{
printf("\nCircular queue operations: Press:\n");
printf("1 for enqueue\n");
printf("2 for dequeue\n");
printf("3 to print Circular Queue\n");
int num,choice;
printf("\nEnter choice:\n");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Enter number to insert :\n");
scanf("%d",&num);
if(full(&q))
{
printf("\nQueue is full\n");
exit(0);
}
enqueue(&q,num);
break;
case 2: if(empty(&q))
{
printf("\nQueue is empty\n");
exit(0);
}
dequeue(&q);
break;
case 3: printf("Printing current queue: \n");
print(&q);
break;
default:break;
}
printf("Press 1 to continue or 0 to exit:\n");
scanf("%d",&op);
}
while(op);
}
void init(myQueue *q)
{
q->f=-1;
q->r=-1;
}
int full(myQueue *q)
{
if((q->r+1)%maxsize==q->f)
{
return 1;
}
else
return 0;
}
int empty(myQueue *q)
{
if(q->r==-1)
{
return 1;
}
else
return 0;
}
enqueue function is used to add the elements into queue.
void enqueue(myQueue *q,int num)
{
if(empty(&q))
{
q->f=0;
q->r=0;
}
else
{
q->r=(q->r+1)%maxsize;
}
q->data[q->r]=num;
printf("\n%d is enqueued\n",q->data[q->r]);
}
Dequeue function is used to delete elements from the stack.
void dequeue(myQueue *q)
{
int del_num;
del_num=q->data[q->f];
if(q->f==q->r)
{
init(&q);
}
else
{ //To move front to the next position in the circular array.
q->f=(q->f+1)%maxsize;
}
printf("\n%d is dequeued\n",del_num);
}
void print(myQueue *q)
{
int i;
for(i=q->f;i!=q->r;i=(i+1)%maxsize)
{
printf("%d\n",q->data[i]);
}
printf("%d\n",q->data[q->r]);
}
Issue: Circular queue is automatically enqueuing the 0 element in it initially.
However, rest of the operations are working just fine.
I am not able to identify, why it is automatically inserting 0 in the circular queue, without me enqueuing it.
Your print() function always prints q->data[q->r] as its last operation. This makes no sense when your queue is empty. Maybe you can avoid it like this:
void print(myQueue *q)
{
if (empty(q))
return;
int i;
for(i=q->f;i!=q->r;i=(i+1)%maxsize)
{
printf("%d\n",q->data[i]);
}
printf("%d\n",q->data[q->r]);
}
Anyway there are many more problems with your code, which I doubt it is compiling correctly. Just as an example, the function enqueue() receives a parameter of type myQueue*. Then it provides function empty with the address of it, but this is wrong. you have to pass the function the pointer itself, so q instead of &q. The same mistake is repeated over and over again.
1st Code Snippet requiring change:
void enqueue(myQueue *q,int num)
{
The below line is changed.
if(empty(q)==1)
{
q->f=0;
q->r=0;
}
else
{
q->r=(q->r+1)%maxsize;
}
q->data[q->r]=num;
printf("\n%d is enqueued\n",q->data[q->r]);
}
2nd code snippet requiring changed:
void dequeue(myQueue *q)
{
int del_num;
del_num=q->data[q->f];
if(q->f==q->r)
{
Line below is changed.
init(q);
}
else
{ //To move front to the next position in the circular array.
q->f=(q->f+1)%maxsize;
}
printf("\n%d is dequeued\n",del_num);
}
3rd snippet requiring change:
void print(myQueue *q)
{
int i;
Line below is changed.
if(empty(q))
{
printf("Queue empty");
exit(0);
}
else
{
printf("Printing current queue: \n");
for(i=q->f;i!=q->r;i=(i+1)%maxsize)
{
printf("%d\n",q->data[i]);
}
printf("%d\n",q->data[q->r]);
}
}
That makes it perfectly alright. :)
#include <stdio.h>
#define SIZE 5
int items[SIZE];
int front = -1, rear = -1;
int isFull() {
if ((front == rear + 1) || (front == 0 && rear == SIZE - 1)) return 1;
return 0;
}
int isEmpty() {
if (front == -1) return 1;
return 0;
}
void enQueue(int element) {
if (isFull())
printf("\n Queue is full!! \n");
else {
if (front == -1) front = 0;
rear = (rear + 1) % SIZE;
items[rear] = element;
printf("\n Inserted -> %d", element);
}
}
int deQueue() {
int element;
if (isEmpty()) {
printf("\n Queue is empty !! \n");
return (-1);
} else {
element = items[front];
if (front == rear) {
front = -1;
rear = -1;
}
else {
front = (front + 1) % SIZE;
}
printf("\n Deleted element -> %d \n", element);
return (element);
}
}
void display() {
int i;
if (isEmpty())
printf(" \n Empty Queue\n");
else {
printf("\n Front -> %d ", front);
printf("\n Items -> ");
for (i = front; i != rear; i = (i + 1) % SIZE) {
printf("%d ", items[i]);
}
printf("%d ", items[i]);
printf("\n Rear -> %d \n", rear);
}
}
int main() {
deQueue();
enQueue(1);
enQueue(2);
enQueue(3);
enQueue(4);
enQueue(5);
enQueue(6);
display();
deQueue();
display();
enQueue(7);
display();
enQueue(8);
return 0;
}

Why is the following code showing segmentation fault whenever I input parantheses in the expression?

The code:
#include<stdio.h>
#include<ctype.h>
#define MAX 100
typedef struct stack
{
char data[MAX];
int top;
}stack;
void push(stack *s, char c)
{
s->top++;
if(s->top>MAX)
{
printf("Stack Overflow\n");
return;
}
s->data[s->top]=c;
}
int isEmpty(stack *s)
{
if(s->top==-1)
return 0;
else
return 1;
}
int priority(char c)
{
if(c=='(' || c==')')
return 0;
else if(c=='+' || c=='-')
return 1;
else if(c=='*' || c=='/')
return 2;
else if(c=='^')
return 3;
}
void pop(stack *s)
{
printf("%c ", s->data[s->top]);
s->top--;
}
void infixToPostfix(stack *s)
{
int c;
printf("Enter an expression\n");
while((c=getchar()) != '\n')
{
if(isalnum(c))
printf("%c ", c);
else
{
if(c=='(')
push(s, c);
else if(c==')')
{
while(c != '(')
pop(s);
pop(s);
}
else
{
while((priority(c) <= priority(s->data[s->top])) && isEmpty(s))
{
pop(s);
}
push(s, c);
}
}
}
while(s->top)
{
pop(s);
}
pop(s);
}
int main(void)
{
stack s;
s.top=-1;
infixToPostfix(&s);
return 0;
}
For some odd reason, whenever there is a parantheses in the input expression, I get a segmentation fault.
My aim was to convert an infix expression to a postfix expression. I was trying to implement it using a stack.
Is it because I am passing the stack from a called function to other functions?
else if(c==')')
{
while(c != '(')
pop(s);
pop(s);
}
If c is a ), it can't be a ( until you change its value. Inside that while loop, you don't change its value. So that will keep calling pop forever.
void pop(stack *s)
{
printf("%c ", s->data[s->top]);
s->top--;
}
This function has no safeties. If you pop when the stack is empty, it will read outside the bounds of s->data. So calling pop in an endless loop is a disaster.

Stack of strings

Hi i have program here that accept int as value. i wanted to translate it to accept strings in array then. i have read about using struct but i couldnt get into it. i hope someone can help me getting into that without using struct i dont know where to start i want to keep this lines of code.
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
int top = 0;
int *stack = NULL;
int size = 0;
main()
{
int opt, num;
char cont[] = { 'y' };
clrscr();
/* <start Declaring Stack Size { */
printf("Stacking Program");
printf("\n\nData Size: ");
scanf("%d", &size);
printf("\n");
/* } end> */
/* <start Allocates size of stack { */
if(size > 0)
{
stack = malloc(size * sizeof(int));
if(stack == NULL)
{
printf("ERROR: malloc() failed\n");
exit(2);
}
}
else
{
printf("ERROR: size should be positive integer\n");
exit(1);
}
/* } end> */
while((cont[0] == 'y') || (cont[0] == 'Y'))
{
clrscr();
/* <start Main Menu { */
printf("Stacking Program");
printf("\n\nData Size: %d\n\n", size);
printf("MAIN MENU\n1. Pop\n2. Push\n3. Pick\n4. View\nChoose: ");
scanf("%d", &opt);
printf("\n");
switch(opt) {
case 1:
pop();
break;
case 2:
if(top==size)
{
printf("You can't push more data");
}
else
{
printf("Enter data for Stack[%d]: ", top+1);
scanf("%d", &num);
push(num);
}
break;
case 3:
pick();
break;
case 4:
view();
break;
default:
printf("Your choice is not on the list.");
break;
}
/* } end> */
printf("\n\nDo you want continue\(Y\/N\)?");
scanf("%s", &cont[0]);
}
free(stack);
}
pop()
{
int a;
loading();
if(top <= 0)
{
printf("Stack empty.");
return 0;
}
else
{
top--;
a=stack[top];
printf("\(Stack[%d] = %d\) removed.", top+1, a);
}
}
push(int a)
{
stack[top]=a;
top++;
loading();
}
pick()
{
loading();
if(top <= 0)
{
printf("Nothing to display.");
return 0;
}
else
{
printf("\(Stack[%d] = %d\) is the last data.", top, stack[top-1]);
}
}
view()
{
int i;
loading();
if(top <= 0)
{
printf("Nothing to display.");
return 0;
}
else
{
for(i=0;i<top;i++)
{
printf("Stack[%d] = %d\n", i+1, stack[i]);
}
}
}
loading()
{
float i, x;
float load;
int loadarea[] = { 5000, 10000, 15000, 20000, 25000, 30000 };
int percentLoad;
x=0;
load=0;
percentLoad = loadarea[random(5)];
gotoxy(26,11);
printf("[");
for(i=0;i<25;i++)
{
x = i+27;
gotoxy(x, 11);
printf("=");
delay(percentLoad);
gotoxy(51,11);
printf("]");
gotoxy(53,11);
load=(i/25)*104.5;
if(load>100)
load = 100.00;
printf("%.2f\%",load);
}
delay(60000);
for(i=0;i<60;i++) {
printf("\b \b");
}
printf("\n");
}
Easiest way is to convert your stack to store char* instead of int.
char **stack;
stack = malloc( size * sizeof(char*) );
Now, your push operation will accept a char* from some buffer that is storing the string that was just input, duplicate it with strdup, and store that new pointer in the stack.
typedef enum {
STACK_MEM_ERROR = -1,
STACK_FULL = 0,
STACK_OK = 1
} StackStatus;
StackStatus push(const char *str)
{
char *newstr;
if( top >= size ) return STACK_FULL;
newstr = strdup(str);
if( newstr == NULL ) return STACK_MEM_ERROR;
stack[top++] = newstr;
return STACK_OK;
}
When you pop a string, you just get a pointer.
char *pop()
{
if( top == 0 ) return NULL;
return stack[--top];
}
You are responsible for freeing that memory when you are finished with the pointer (by calling free).
char * val;
while( NULL != (val = pop()) )
{
printf( "I popped: %s\n", val );
free(val);
}

Resources