Why queue using two stacks not functioning? - c

I'm trying to implement a queue using 2 stacks but my code isn't functioning.
Can you spot the error?
#include <stdio.h>
#include<stdlib.h>
#define MAX 5
typedef struct stack {
int top;
int arr[MAX];
} stack;
void enque(stack*s1, int ele) {
printf("entering");
push(&s1, ele);
printf("what a pain");
}
void push(stack*s, int ele) {
if (s->top == MAX - 1) {
printf("OVERFLOW");
} else {
s->arr[++s->top] = ele;
}
}
int deq(stack*s1, stack*s2) {
int x;
if (s1->top == -1 && s2->top == -1) {
printf("empty");
} else {
if (s2->top == -1) {
while (s1->top != -1) {
push(&s2, pop(&s1));
}
}
x = pop(&s2);
return x;
}
}
int pop(stack *s) {
if (s->top == -1) {
printf("UNDERFLOW");
} else {
return s->arr[s->top--];
}
}
void display(stack*s) {
printf("entered display");
int i;
for (i = 0; i <= s->top; i++) {
printf(" %d", s->arr[i]);
}
}
int main() {
int ch, ele, c;
stack s1, s2;
s1.top = -1, s2.top = -1;
do {
printf("1 - Enqueue2-deq3-display4-exit\n");
printf("Enter choice");
scanf("%d", &ch);
switch (ch) {
case 1:
printf("enter ele of ur choice");
scanf("%d", &ele);
enque(&s1, ele);
break;
case 2:
c = deq(&s1, &s2);
printf("%d", c);
break;
case 3:
display(&s1);
break;
case 4:
exit(0);
default:
printf("Wrong choice");
}
} while (ch != 5);
}

Can you spot the error?
The compiler can spot the error faster than Stack-overflow.
OP is not compiling with all warnings enabled or is using a weak compiler
Enable all warnings to save time.
int deq(stack*s1, stack*s2) and int pop(stack *s) both have the same problem.
A common waning in such cases is warning: control reaches end of non-void function [-Wreturn-type]
Make certain each function path returns a value.
int pop(stack *s) {
if (s->top == -1) {
printf("UNDERFLOW"); // Notice, no return
} else {
return s->arr[s->top--];
}
}
Also push(&s1, ele); used before declaration. This make for conflicting function signature. Declare or define push() before using. Likely undefined behavior (UB) and this makes the code unreliable.
I recommend to print an '\n' more often.
// printf("entering");
printf("entering\n");
// or
puts("entering"); // \n automatically added.

You are passing pointer address in deque and enque functions.
push(&s2, pop(&s1)); --> push(s2, pop(s1));
x = pop(&s2); --> x = pop(s2);
push(&s1, ele);-->push(s1, ele);
since s1 and s2 are received as pointers to deque and enque functions
Also consider changes suggested by #Mr.Chux by considering compiler warnings you could have resolved all the issues by yourself.

Related

Error 'is_empty' was not declared in this scope.why does it give error?

output=[Error] 'is_empty' was not declared in this scope
must be:
Example
Input string : abbccbaabccbba message will be The string is valid
aaabbcbbcbaab message will be The string is invalid
aadbxcy*ycxbdaa message will be Wrong character!!!
what should i do?
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
typedef struct
{
char home[35];
int top;
} My_stack;
void push(My_stack * s, char c) // push (insert) operation
{ // assume there is enough space for pushing next element!
s -> top ++;
s -> home[s -> top] = c;
}
int pop(My_stack * s) // pop (remove) operation
{
if(is_empty (*s)) {
printf("ERROR: Nothing to pop - program terminates\n");
exit(1);
}
return (s ->home[s ->top --]);
}
int is_empty(My_stack * s) // checking whether stack is empty or not
{
return(s -> top < 0 ? 1 : 0);
}
int main(){
char ch[25];
int i,l;
My_stack stack;
printf("give the string");
scanf("%s",ch);
l=strlen(ch);
i=0;
while(ch[i]!='\0') {
if(ch[i]!='A'&&ch[i]!='B'&& ch[i]!='*') {
printf("the string is not accepted allowed caracters are A,B and * ");
exit(0);
}
i++;
}
i=0;
while(ch[i] != '*') {
push(&stack, ch[i]);
i++;
}
i++; // one step forward to pass '*
while(ch[i] != '\0') {
if(ch[i] != pop(&stack)) {
printf("the string is not valid");
exit(0);
}
i++;
}
printf("the string is valid");
return 0;
}
First of all, you need to pass the pointer to the function, not the actual value, so your functioncall must be changed to:
is_empty (s)
instead of
is_empty (*s)
Then, the reason is because you define your function is_empty after your first use. To prevent this error, you should declare your function first. This tells the compiler "hey, there exists this function with this signature, the definition is given later though" so then you can use it in your program before having implemented it explicitly.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
typedef struct
{
char home[35];
int top;
} My_stack;
int is_empty(My_stack * s); // <----- DECLARATION OF FUNCTION
int pop(My_stack * s) // pop (remove) operation
{
if(is_empty (s)) {
printf("ERROR: Nothing to pop - program terminates\n");
exit(1);
}
return (s ->home[s ->top --]);
}
int is_empty(My_stack * s) // checking whether stack is empty or not
{
return(s -> top < 0 ? 1 : 0);
}
Or, you put the entire definition before your first use so then there's no need for a declaration:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
typedef struct
{
char home[35];
int top;
} My_stack;
int is_empty(My_stack * s) // checking whether stack is empty or not
{
return(s -> top < 0 ? 1 : 0);
}
int pop(My_stack * s) // pop (remove) operation
{
if(is_empty (s)) {
printf("ERROR: Nothing to pop - program terminates\n");
exit(1);
}
return (s ->home[s ->top --]);
}

simple patient managing program using queue

I'm making simple patient managing program using circular queue but q.rear always have "0" value while executing exit_hos()
I thought that addq() makes variable "rear" different, but It doesn't work.
is_empty() always return front and rear is same.
I think I'm misunderstanding some codes and memory concepts.
how can I fix these functions?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 50
#define MAX_QUEUE_SIZE 6
typedef struct {
char** value;
int front;
int rear;
} Queue;
void init_queue(Queue* q) {
q->value = (char**)malloc(sizeof(char*) * MAX_QUEUE_SIZE);
q->front = 0;
q->rear = 0;
}
int is_full(Queue* q) {
if (((q->rear +1) % MAX_QUEUE_SIZE) == q->front)
return 1;
else
return 0;
}
int is_empty(Queue* q) {
if (q->front == q->rear)
return 1;
else
return 0;
}
void addq(Queue* q, char* value) {
q->rear = (q->rear+1) % MAX_QUEUE_SIZE;
q->value[q->rear] = value;
printf("addq: %s", value);
return;
}
char* deleteq(Queue* q) {
q->front = (q->front + 1) % MAX_QUEUE_SIZE;
return q->value[q->front];
}
void arrive(Queue q) {
int input;
char name[MAX_SIZE];
printf("\n");
printf("1. submit\n");
printf("2. cancel\n");
scanf("%d", &input);
if (input == 1) {
if (is_full(&q) == 1) {
printf("Service is not available\n");
}
else {
printf("name: ");
scanf("%s", name);
addq(&q, name);
}
}
else if (input == 2) {
return;
}
else {
printf("input error\n");
return;
}
return;
}
void exit_hos(Queue q) {
char patient[MAX_SIZE];
if (is_empty(&q) == 1)
{
printf("There is no patient waiting\n");
}
else {
strcpy(patient, deleteq(&q));
printf("patient: %s", patient);
}
return;
}
int main() {
int input;
Queue q;
init_queue(&q);
while (1)
{
printf("\nINPUT\n");
printf("1. Arrive hostpital\n");
printf("2. Exit hospital\n");
printf("3. service exit\n");
scanf("%d", &input);
if (input == 1)
arrive(q);
else if (input == 2) {
exit_hos(q);
}
else if (input == 3) {
printf("exit\n");
return 0;
}
else {
printf("input error\n");
}
}
free(q.value);
return 0;
}
I think that this line is wrong:
q->value = (char**)malloc(sizeof(char*) * MAX_QUEUE_SIZE);
I think that it should be:
char * _value = (char*)malloc(sizeof(char*) * MAX_QUEUE_SIZE);
q->value = &_value;
malloc is going to return a pointer to a char array. q->value is a pointer to a pointer to a char array. So you want to set it to the address of the char array that malloc is created for you.
Change you init_queue code to this and it will work:
void init_queue(Queue* q) {
char * _value = (char*)malloc(sizeof(char*) * MAX_QUEUE_SIZE);
q->value = &_value;
q->front = 0;
q->rear = 0;
}
Output:
Chris#DESKTOP-BCMC1RF ~
$ ./main.exe
INPUT
1. Arrive hostpital
2. Exit hospital
3. service exit
1
1. submit
2. cancel
1
name: fred
addq: fred
INPUT
1. Arrive hostpital
2. Exit hospital
3. service exit
2
If you already have a max queue size and a max size, you are better off pre-allocating the whole thing as an array, reducing memory headaches. As a general rule, avoid headaches unless they provide a feature you want.
Note: This method of keeping track of and re-using memory is called a circular buffer (not to be confused with the linked list types that are more commonly called queues).
#define MAX_SIZE 50
#define MAX_QUEUE_SIZE 6
typedef struct {
char value [MAX_QUEUE_SIZE][MAX_SIZE + 1]; //+1 to hold extra null termination
unsigned int front;
unsigned int size; //size is a clearer than rear, which could have meant end item or end+1 and needed special empty queue handling
} Queue;
void init_queue(Queue* q) {
memset(q,0,sizeof(Queue)); //just zero it all
//more info on this and some situation-dependent alternatives https://stackoverflow.com/questions/11152160/initializing-a-struct-to-0
}
int is_full(const Queue* q) {
return q->size >= MAX_QUEUE_SIZE;
}
int is_empty(const Queue* q) {
return q->size == 0;
}
//sometimes called a push operation
//return 0 if failed
int addq(Queue* q, const char* value) {
//error check, abort, error handling section:
//full queue -> abort
if(is_full(q)) return 0;
//long value -> truncate handled via strncpy
//actual operation
const unsigned int destination = (q->front + q->size) % MAX_QUEUE_SIZE;
strncpy(q->value[destination],value,MAX_SIZE);
q->size = q->size + 1;
printf("addq: %s", q->value[destination]);
return q->size;
}
//sometimes called a pop operation
//return value may not persist if addq is called, but fine for your use of copying on call
const char* deleteq(Queue* q) {
if(is_empty(q)) return 0;
const char * retval = q->value[q->front];
q->front = (q->front + 1) % MAX_QUEUE_SIZE;
q->size = q->size - 1;
return retval;
}
also remember to use either MAX_SIZE + 1 or strncpy with MAX_SIZE - 1 since "No null-character is implicitly appended at the end of destination if source is longer than num."
(and strcpy and scanf as you sling them onto arrays is unsafe)

How to fix Segmentation Fault while trying to do RPN in C

I am trying to make a program that will use RPN, which will calculate a series of integers. I have some standard functions (pop, push) that I can't change. But when I run the below code, I get a segmentation fault.
Since I can't change the inside core of those two functions, so I tried to change the way that I am calling them (I made stack[] a dynamic array and the top an int pointer) but nothing changes.
#include <stdio.h>
#include <stdlib.h>
#define N 1000
void push(int stack[],int *t,int obj)
{
if((*t)==(N-1))
{
printf("Stack overflow...\n");
getchar(); //getc
abort();
}
else
stack[++(*t)]=obj;
}
int pop(int stack[],int *t)
{
int r;
if((*t<0))
{
printf("Stack empty...\n");
printf("Error in expresion.\n");
getchar(); //getc
abort();
}
else
r=stack[(*t)--];
return(r);
}
int isdigit(char in)
{
int flag;
if (in>=48 && in<=57) //if its terminus
flag=1;
else if(in==42 || in==43 || in==45 || in==47) //if its operator
flag=2;
else
flag=0;
return flag;
}
int main(int argc, char** argv) {
int *stack=(int*) malloc(N*sizeof(int));
char input;
int i=0,*top=0,flag;
int num1,num2;
float result;
if (stack == NULL) {
printf("Out of memory!\n");
return (1);
}
printf("Give the Formula: ");
while(input=getchar())
{
flag=isdigit(input);
if(flag==1) //if its terminus
{
push(&stack[i],top,input);
}
if(flag==2) //if its enforcer
{
num1=pop(&stack[i],top);
num2=pop(&stack[i+1],top);
if (input==42) //case of +
result=num1+num2;
if (input==43) //case of *
result=num1*num2;
if (input==45) //case of -
result=num2-num1;
if (input==47) //case of /
if(num2!=0)
result=num2/num1;
else
printf("Can't do the operation");
push(&stack[i],top,result);
}
if(flag==0) //case of everything else
{
printf("Error");
exit(1);
}
printf("Operand: %c\n",input);
// for(int j=0;j<strlen(stack);j++)
// printf("stack[%d]=%d\n",i,stack[j]);
//printf current status of stack
i++;
}
return (EXIT_SUCCESS);
}
If you have a series of integers like 234+*, the stack should be firstly 2,3,4,+,*, secondly 5,4,*, thirdly 20.
In main you defined top as pointer and initialized it to point to null.
After that, in push, you try to dereference the null location via *t. Here you get segmentation fault.

How to read the values stored in a char array?

Here I am trying to implement a stack, where only opening braces from a string will be filtered out and stored in an array. The code I wrote stored the values in stackArr array. But whenever I attempt to print out the array, my code fails. It doesn't give any specific error message, it just fails to execute.
I think problem is in the following portion:
i = 0;
while(stackArr[i] != '\0')
{
printf("%c ",stackArr[i]);
i++;
}
Full code :
#include<stdio.h>
#include<stdlib.h>
int main()
{
char braces[10];
char stackArr[10];
int front = -1,rear = -1,size = 10;
gets(braces);
checkValidate(&braces,&stackArr,&front,&rear,size);
}
void checkValidate(char *braces,char *stackArr,int *front,int *rear,int size)
{
int i = 0;
while(braces[i] != '\0')
{
if((braces[i] == '(') || (braces[i] =='{') || (braces[i] =='['))
{
push(braces[i],&stackArr,&front,&rear,size);
}
i++;
}
//print(&front,&rear,size,*stackArr);
i = 0;
while(stackArr[i] != '\0')
{
printf("%c ",stackArr[i]);
i++;
}
}
void push (char val,char *stackArr,int *front,int *rear,int size)
{
if(isFull(*front,*rear,size))
{
printf("your string is larger that valid size\n");
}
else
{
if(isEmpty(*front,*rear))
{
*front = 0;
}
*rear = (*rear+1) % size;
stackArr[*rear] = val;
/*printf("%d ",*rear);
printf("%c",stackArr[*rear]);
printf("\n");*/
}
}
int isEmpty(int front,int rear)
{
if(front == -1 && rear == -1)
{
return 1;
}
else
{
return 0;
}
}
int isFull(int front,int rear,int size)
{
if(front == 0 && rear == size -1)
{
return 1;
}
else
{
return 0;
}
}
void print(int *front,int *rear,int size,char *arr)
{
int i;
for(i = *rear;i != *front; i = (i-1)% size)
{
printf("%c\n",arr[i]);
}
printf("%c\n",arr[i]);
}
Your code must produce a lot of warnings on compile, because the functions that you call lack forward declarations. Hence, compiler assumes that all functions that you call have parameters of type int, and that they also return an int. Since your functions take pointers instead, the calls of your functions result in undefined behavior, which is likely leading to a crash.
// Put these declarations in front of main
void checkValidate(char *braces,char *stackArr,int *front,int *rear,int size);
void push (char val,char *stackArr,int *front,int *rear,int size);
int isEmpty(int front,int rear);
int isFull(int front,int rear,int size);
void print(int *front,int *rear,int size,char *arr);
Adding forward declarations should fix this problem. In addition, you need to replace the now-deprecated gets call with a call to fgets, which is safe from buffer overruns.
You also pass pointers to arrays to functions that expect pointers to character. You need to remove & in front of braces and stackArr. Turn on compiler warnings to see all places where this needs to be done.
Finally, your code expects stackArr to be null-terminated, but you never set its elements to zeros. Add char stackArr[10] = {0} to initialize the array to zeros.

Trying to implement an array based stack in C for an assignment

I am trying to implement an array based stack in C. My stack is supposed to have two parameters, top (the number of the top element in the array), and array (the array itself). My implementation follows.
typedef struct
{
char array[20];
int top;
}
stack;
stack mystack;
int Push(char,stack);
char Pop(stack);
char Top(stack);
int isFull(stack);
char input;
char save;
void main()
{
mystack.top = -1;
printf("Please input the characters you would like in your stack \n
while(input != '^')
{
Push( (scanf("%c",&input)) , mystack );
if (isFull(mystack) == 1)
printf("Your Stack is full, please input '^'\n");
}
char junk;
scanf("enter any character to continue %c",&junk);
while(mystack.top != -1)
{
printf("%c \n",Pop(mystack));
}
scanf("enter any character to terminate the program",&junk);
}
int Push(char charpush,stack stackpush)
{
if(stackpush.top >=20 )
return -1;
else
{
stackpush.array[stackpush.top + 1] = charpush;
stackpush.top = stackpush.top +1;
return 0;
}
}
char Pop(stack stackpop)
{
if (stackpop.top != -1)
{
save = stackpop.array[stackpop.top];
stackpop.top = stackpop.top-1;
return save;
}
}
char Top(stack stacktop)
{
if (stacktop.top != -1)
return stacktop.array[stacktop.top];
}
int isFull(stack stackisfull)
{
if (stackisfull.top = -1)
return 0;
else if (stackisfull.top >= 20)
return 1;
else return -1;
}
Currently my program accepts characters from the user, but the program automatically terminates when '^' is entered. It doesn't display the stack, and it doesn't do anything if characters come through the input and the stack is already full.
Please let me know if i need to be more specific or any further information is needed.
You've got a whole lot of problems to correct...
You have misunderstood scanf greatly
It doesn't return what it read
It doesn't accept a prompt
When reading from the terminal, it doesn't "see" anything until return is pressed
What does your method Pop() return when the stack is empty?
What does your method Top() return when the stack is empty?
Why did you write while(mystack.top != -1)? Would it make more sense to write while (!isEmpty(mystack)) and then write an isEmpty method?
You didn't initialize input - do yo know what is in it at the start?
Your indention "scheme" makes my head hurt. :)
In addition to the points #John Hascall has mentioned, C is a pass by value language. Meaning for every function call the arguments you provide are local in scope see this other stackoverflow post.
Having your global mystack variable (not the best practice either) will work but not how you are currently using it. By passing mystack to each function the changes are only visible on the argument used thereby defeating the purpose of having that global.
I've made the minor edits to indentation and logical errors but the main change was editing your functions to not take a "stack" argument and use your global:
#include <stdio.h>
typedef struct
{
char array[20];
int top;
} stack;
stack mystack; // your global
int Push(char); // remove "stack" arg for each stack-utility function
char Pop(void);
char Top(void);
int isFull(void);
char input;
char save;
// main as returning int and excepting argc/*argv[]
int main(int argc, char *argv[])
{
mystack.top = -1;
printf("Please input the characters you would like in your stack \n");
while(input != '^')
{
// by including scanf inside the function call return is passed
scanf("%c", &input);
Push( input );
if (isFull() == 1)
printf("Your Stack is full, please input '^'\n");
}
char junk;
// scanf will not print
printf("enter any character to continue\n");
scanf("%c",&junk);
while(mystack.top != -1)
{
printf("%c \n",Pop());
}
// same as last comment
printf("enter any character to terminate the program\n");
scanf("%c",&junk);
}
int Push(char charpush)
{
if(mystack.top >=20 )
return -1;
else
{
mystack.array[mystack.top + 1] = charpush;
mystack.top = mystack.top +1;
return 0;
}
}
char Pop(void)
{
if (mystack.top != -1)
{
save = mystack.array[mystack.top];
mystack.top = mystack.top-1;
return save;
}
// return has to match declaration type
return 0;
}
char Top(void)
{
if (mystack.top != -1)
return mystack.array[mystack.top];
// same as last comment
return 0;
}
int isFull(void)
{
// you were assigning not comparing
if (mystack.top == -1)
return 0;
else if (mystack.top >= 20)
return 1;
else return -1;
}

Resources