Can't push after using pop - c

I've been at this for about 7 hours trying to get this to work on my own, but I can't figure it out. With my testing earlier I was able to successfully fully push all the values of my char[] into the stack and I could properly pop them off and return the value.
However, if I try to push something back onto the stack then the whole program crashes.
Notes:
The code is supposed to be used to create nodes for an Expression Tree later on
The commented out code in the switch statement is code that I had when the error occurred, was just saving it for when I could have fixed it.
-When pushing after using a pop, the function is properly called, however it does not enter either the if or the else statement within push.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Stack;
typedef struct StackNode;
typedef struct StackPtr;
struct StackPtr
{
struct StackPtr *prev;
struct StackNode *ptr;
};
struct StackNode
{
char c;
struct StackNode *lchild;
struct StackNode *rchild;
};
struct Stack
{
struct StackPtr *top;
};
// Prototypes
void initStack(struct Stack*);
struct StackNode* createNode(char);
struct StackNode* pop(struct Stack*);
void push(struct Stack*, struct StackNode*);
int isEmpty(struct Stack*);
int main()
{
struct Stack *s = malloc(sizeof(s));
initStack(s);
char exp[7] = "45+67+*";
int length = 0;
for(length; length<3; length++) // push the expression onto the stack
{
struct StackNode *exp1 = malloc(sizeof(exp1));
struct StackNode *exp2 = malloc(sizeof(exp2));
struct StackNode *c = malloc(sizeof(c));
if(exp[length] > 47 && exp[length] < 58) // is a number
{
c->c = exp[length];
push(s,c);
}
else
{
switch(exp[length])
{
default:
printf("exp[length] error\n");
break;
case '+':
exp2 = pop(s);
exp1 = pop(s);
c->c = '7';
push(s, c);
//push(s, exp1->ptr);
//push(s, exp2->ptr);
//c->c = exp[length];
//c->rchild = exp2;
//c->lchild = exp1;
//printf("test ");
//push(s, c);
//printf("test ");
break;
case '-':
break;
case '*':
break;
case '/':
break;
}
}
}
return 0;
}
void initStack(struct Stack *s)
{
struct StackNode *n = malloc(sizeof(n));
struct StackPtr *p = malloc(sizeof(p));
n->c = NULL;
n->lchild = NULL;
n->rchild = NULL;
p->prev = NULL;
p->ptr = n;
s->top = p;
}
struct StackNode* createNode(char c)
{
struct StackNode *n = malloc(sizeof(n));
n->c = c;
n->lchild = NULL;
n->rchild = NULL;
return n;
}
void push(struct Stack *s, struct StackNode *n)
{
if(s->top->ptr->c == NULL) // First item being pushed
{
s->top->ptr = n;
printf("1Added: %c to the stack\n", n->c);
}
else
{
struct StackPtr *o = malloc(sizeof(o));
o->prev = s->top;
s->top = o;
s->top->ptr = n;
printf("2Added: %c to the stack\n", n->c);
}
}
struct StackNode* pop(struct Stack *s)
{
if(isEmpty(s) == 1)
{
printf("Stack is empty!\n");
return;
}
else
{
struct StackPtr *tmp = malloc(sizeof(tmp));
tmp = s->top;
s->top = s->top->prev;
printf("Popped: %c from the stack.\n",tmp->ptr->c);
return tmp->ptr;
}
}
int isEmpty(struct Stack *s)
{
if(s->top == NULL)
return 1;
else
return 0; // false

your POP function is setting
s->top = s->top->prev;
after two nodes are popped out the Prev value is NULL so top is pointing to NULL, which is causing the segmentation fault during the next PUSH
Few more things to consider, change value to 8 instead of 7 as \0 needs to be fit. or use it as
char exp[]
char exp[8] = "45+67+*";

Related

Doubly circular linked list strange behaviour

I use the following code snippet to add an element to the back of my doubly circular linked list.
typedef struct node
{
int nb;
struct node *prev;
struct node *next;
} st_node;
void add_back(st_node *origin, st_node *node)
{
st_node *tmp;
if (!origin || !node)
exit(1);
tmp = origin;
while (tmp->next != origin)
tmp = tmp->next;
tmp->next = node;
node->prev = tmp;
node->next = origin;
origin->prev = node;
}
Then I print my list with the folling function :
void printer(st_node *origin)
{
st_node *node;
node = origin;
while (node->next != origin)
{
printf("%d\n", node->nb);
node = node->next;
}
printf("%d\n", node->nb);
}
I got the origin value with printf and then random values in a loop. I don't know what to do and I realized origin->prev = node; was causing the problem inside the add_back function but I don't know why.
Here's the main:
int main(int ac, char **av)
{
st_node *stack;
int i;
if (ac <= 2)
return (1);
stack = create_element(atoi(av[1]));
i = 2;
while (i < ac)
add_back(stack, create_element(atoi(av[i++])));
printf("Stack:\n");
printer(stack);
}
st_node *create_element(int nb)
{
st_node *element;
element = malloc(sizeof(st_node *));
element->nb = nb;
element->next = element;
element->prev = element;
return (element);
}
Your create_element() function is wrong. It does not allocate enough memory for each node. This ...
st_node *element;
element = malloc(sizeof(st_node *));
... should be ...
st_node *element;
element = malloc(sizeof(st_node));
... or, better ...
st_node *element;
element = malloc(sizeof(*element));
With that correction, and adding a closing brace to main(), your program works for me.
Several bugs:
malloc in create_element is wrong
In add_back, the order of the link setting is wrong
In add_back, no need to loop to find the tail node. It is origin->prev
The printer function will segfault on an empty list because it is dereferencing node before checking whether it is non-null
The first if in main is too strict: It does not allow: ./myprogram 1 (i.e. a list with one element)
Here is the refactored/working code. It is annotated with the bugs/fixes:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int nb;
struct node *prev;
struct node *next;
} st_node;
st_node *
create_element(int nb)
{
st_node *element;
// NOTE/BUG: does _not_ allocate enough space (causing UB/undefined behavior)
#if 0
element = malloc(sizeof(st_node *));
#else
element = malloc(sizeof(*element));
#endif
element->nb = nb;
element->next = element;
element->prev = element;
return (element);
}
void
add_back(st_node *origin, st_node *node)
{
st_node *tmp;
if (!origin || !node)
exit(1);
// NOTE/BUG: no need to traverse -- origin->prev is the back
#if 0
tmp = origin;
while (tmp->next != origin)
tmp = tmp->next;
#else
tmp = origin->prev;
#endif
// NOTE/BUG: order and set is incorrect -- causes self loop
#if 0
tmp->next = node;
node->prev = tmp;
node->next = origin;
#else
node->prev = tmp;
node->next = tmp->next;
tmp->next = node;
#endif
origin->prev = node;
}
void
printer(st_node *origin)
{
st_node *node;
// NOTE/BUG: this will segfault on an empty list
#if 1
node = origin;
while (node->next != origin) {
printf("%d\n", node->nb);
node = node->next;
}
printf("%d\n", node->nb);
#else
node = origin;
if (node != NULL) {
while (1) {
printf("%d\n", node->nb);
node = node->next;
if (node == origin)
break;
}
}
#endif
}
int
main(int ac, char **av)
{
st_node *stack;
int i;
// NOTE/BUG: does _not_ allow for list of only one element
#if 0
if (ac <= 2) {
#else
if (ac < 2) {
#endif
printf("main: too short\n");
return (1);
}
stack = create_element(atoi(av[1]));
// NOTE/BUG: for loop is cleaner
#if 0
i = 2;
while (i < ac)
add_back(stack, create_element(atoi(av[i++])));
#else
for (i = 2; i < ac; ++i)
add_back(stack, create_element(atoi(av[i])));
#endif
printf("Stack:\n");
printer(stack);
}
In the above, I used cpp conditionals to denote old/broken vs. new/fixed code:
#if 0
// old code
#else
// new code
#endif
The above code fixed most of the bugs, but the program could not create an empty list.
Here's some more cleanup/refactoring to make the program more general. In particular, I generalized add_back to allow adding a node to an empty list. In the original code, it treated this as a fatal exit condition.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int nb;
struct node *prev;
struct node *next;
} st_node;
st_node *
create_element(int nb)
{
st_node *element;
element = malloc(sizeof(*element));
element->nb = nb;
element->next = element;
element->prev = element;
return (element);
}
st_node *
add_back(st_node *origin, st_node *node)
{
st_node *tmp;
if (node == NULL)
exit(1);
do {
// add to empty list
if (origin == NULL) {
origin = node;
break;
}
tmp = origin->prev;
node->prev = tmp;
node->next = tmp->next;
tmp->next = node;
origin->prev = node;
} while (0);
return origin;
}
void
printer(st_node *origin)
{
st_node *node;
node = origin;
if (node != NULL) {
while (1) {
printf("%d\n", node->nb);
node = node->next;
if (node == origin)
break;
}
}
}
int
main(int ac, char **av)
{
st_node *stack = NULL;
int i;
for (i = 1; i < ac; ++i)
stack = add_back(stack, create_element(atoi(av[i])));
printf("Stack:\n");
printer(stack);
}

Error in creating stack header file. In C

#include <stdbool.h>
#include <stdlib.h>
typedef struct Node{
void *data;
struct Node *next;
}node;
typedef struct Stack{
node *top;
}stack;
bool push (stack *s , void *val)
{
node *n;
n = create_node (val);
if (n)
{
n->next = s->top;
s->top = n;
return true;
}
return false;
}
void* pop (stack *s)
{
node *temp;
void *x = NULL;
if (s->top)
{
x = s->top->data;
temp = s->top;
s->top = s->top->next;
free(temp);
}
return x;
}
void* peek (stack *s)
{
void *x = NULL;
if (s->top)
x = s->top->data;
return x;
}
node* create_node (void *val)
{
node *n;
n = (node*) malloc (sizeof(node));
if (n)
{
n->data = val;
n->next = NULL;
}
return n;
}
stack* create_stack (void)
{
stack *s;
s = (stack*) malloc (sizeof(stack));
if (s)
s->top = NULL;
return s;
}
I tried to write a header file for stack in C. I included this header file in another program. I added the header file #include"mystack.h"
I think the error is somewhere in passing void pointer but I don't know how to debug it.
The stack gets created successfully but as I try to push or pop the code terminates. I can't seem to find the error.
The code for calling program is,
#include <stdio.h>
#include <stdbool.h>
#include "mystack.h"
void main()
{
stack *s = NULL;
int *x;
int val;
bool res;
s = create_stack ();
printf ("Enter value to push : ");
scanf ("%d" , val);
res = push (s , &val);
if (res)
printf ("...PUSHED %d IN STACK...\n", *x);
else
printf ("...STACK OVERFLOW...\n");
free(s->top);
free(s);
}
The code stops after push operation is called.

Why I need to cast "((node)s->top)->next = q" on "push" method? Dubs an declaration pointer to struct

I'd like to have explanations regard some dubs. Here is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct sNode {
int data;
struct sNode* next;
} sNode;
typedef sNode* node;
typedef struct {
node *top;
node *head;
int nodes;
} stack;
void push(stack *s);
void printStack(stack *s);
int main(){
srand((unsigned)time(NULL));
stack s = {NULL, NULL, 0};
push(&s);
push(&s);
push(&s);
push(&s);
printStack(&s);
return 0;
}
void push(stack *s){
node q = (node)malloc(sizeof(sNode));
q->data = rand() % 10 + 1;
q->next = NULL;
if(s->top){
((node)s->top)->next = q;
s->top = q;
} else {
s->top = q;
}
if(s->nodes == 0) s->head = q;
s->nodes++;
}
void pop(stack *s){
}
void printStack(stack *s){
printf("Number of nodes: %d\n", s->nodes);
node q = s->head;
while(q != NULL){
printf("%d -> ", q->data);
q = q->next;
}
printf("NULL");
}
Can you explain me why I need to cast (*node) on function push? Why, also, is sufficient declare a pointer to the struct in this way:
stack *s;
and start working on?
What's the difference with this:
stack s;
stack *ss = &s;

implementing stack with linked list in C

I'm having trouble implementing a Stack using a linked list with struct. The program compiles fine but when I run it, it prints the first element but then reads the next node as a NULL. I think it might be an error with my passing of the stack to the push method but I am not sure and I have not been successful in fixing it so I'm asking for your help:
#include <stdio.h>
#include <stdlib.h>
struct stackNode{
char data;
struct stackNode *nextPtr;
};
typedef struct stackNode StackNode;
typedef StackNode *StackNodePtr;
void convertToPostfix(char infix[], char postfix[]);
int isOperator(char c);
int precedence(char operator1, char operator2);
void push(StackNodePtr *topPtr, char value);
char pop(StackNodePtr *topPtr);
char stackTop(StackNodePtr topPtr);
int isEmpty(StackNodePtr topPtr);
void printStack(StackNodePtr topPtr);
int main(){
convertToPostfix(NULL, NULL);
return 0;
}
void convertToPostfix(char infix[], char postfix[]){
StackNode stack = {'(', NULL};
StackNodePtr stackPtr = &stack;
push(stackPtr, 'a');
//printf("%s\n", stackPtr->data);
printStack(&stack);
}
void push(StackNodePtr *topPtr, char value){
StackNode *node;
node=(StackNodePtr)malloc(sizeof(StackNodePtr));
node->data=value;
node->nextPtr=*topPtr;
*topPtr=node;
}
void printStack(StackNodePtr topPtr){
if(topPtr == NULL){
printf("%s\n", "NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO");
return;
}
printf("%c\n", topPtr->data);
printStack(topPtr->nextPtr);
}
Any help would be appreciated.
Thanks
Several problems I could see:
1) printStack(&stack); should be printStack(stackPtr); as you are passing address of stackPtr to the push function.
2)
node = (StackNodePtr)malloc(sizeof(StackNodePtr));
should be:
node = malloc(sizeof(StackNode));
3)
push(stackPtr, 'a');
should be:
push(&stackPtr, 'a');
As you need to pass the address of the top pointer.
This is incorrect:
node=(StackNodePtr)malloc(sizeof(StackNodePtr));
as it is only allocating memory for a struct stackNode* (commonly 4-bytes for any pointer type), when it should be allocating memory for a struct stackNode (at least 5 bytes):
node = malloc(sizeof(StackNode));
--
See Do I cast the result of malloc?
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node * link;
};
void push(struct node **, int);
int pop(struct node **);
void display(struct node *);
void printMenu();
int main() {
struct node * p;
p = NULL;
int data, ch, data1;
//char choice[10];
do {
printMenu();
printf("Enter your choice\n");
scanf("%d", &ch);
switch (ch) {
case 1:
printf("Enter the element to be pushed\n");
scanf("%d", &data);
push(&p, data);
break;
case 2:
data1 = pop(&p);
if (data1 != -1000)
printf("The popped element is %d\n", data1);
break;
case 3:
printf("The contents of the stack are");
display(p);
printf("\n");
break;
default:
return 0;
}
} while (1);
return 0;
}
void printMenu() {
printf("Choice 1 : Push\n");
printf("Choice 2 : Pop\n");
printf("Choice 3 : Display\n");
printf("Any other choice : Exit\n");
}
void push(struct node **q, int num) {
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->link = (*q);
temp->data = num;
(*q) = temp;
}
void display(struct node *q) {
//Fill in the code here
struct node *temp = q;
if (temp == NULL)
printf(" {}");
while (temp != NULL)
{
printf(" %d", temp->data);
temp = temp->link;
}
}
int pop(struct node **q) {
//Fill in the code here
struct node *temp;
int item;
if (*q == NULL)
{
printf("Stack is empty\n");
return -1000;
}
temp = *q;
item = temp->data;
*q = (*q)->link;
free(temp);
return item;
}

C Typed Stack: Linked-List Implementation

I have a computer science exam coming up and a large portion is going to be on programming in ansi C. I'm new to C and as a review I tried to implement a stack using a linked-list. My code compiles but it doesn't run as expected.
I believe there is an error with my push() function. I'm assuming that my stack reference isn't being updated properly.
I wrote the following code from scratch to study / practice. Any advice on how to fix my code or improve my programming style would be greatly appreciated.
Thanks guys!
stack.h
#ifndef __STACK__
#define __STACK__
#include <stdlib.h>
#include "bool.h"
#define EMPTY -1
typedef struct Node {
int index;
enum { INT = 0, CHAR, STRING } type;
union {
int i;
char c;
char* s;
} value;
struct Node* prev;
} Node;
typedef Node* Stack;
Stack init();
void push(Stack stack, int type, void* value);
void pop(Stack stack, Node* node);
void empty(Stack stack);
Bool isempty(Stack stack);
#endif
stack.c
#include <stdlib.h>
#include <string.h>
#include "stack.h"
Stack init() {
Stack stack = (Node*) malloc(sizeof(Node));
stack->index = EMPTY;
stack->type = INT;
stack->value.i = 0;
stack->prev = 0;
return stack;
}
void push(Stack stack, int type, void* value) {
int length;
Node* node = (Node*) malloc(sizeof(Node));
node->index = stack->index + 1;
node->type = type;
switch(node->type) {
case INT:
node->value.i = *((int*) value);
break;
case CHAR:
node->value.c = *((char*) value);
break;
case STRING:
length = strlen((char*) value) + 1;
node->value.s = (char*) malloc(length * sizeof(char));
strcpy(node->value.s, value);
break;
}
node->prev = stack;
stack = node;
}
void pop(Stack stack, Node* node) {
int length;
Node* temp = stack;
if (!isempty(stack)) {
node->index = stack->index;
node->type = stack->type;
switch(stack->type) {
case INT:
node->value.i = stack->value.i;
break;
case CHAR:
node->value.c = stack->value.c;
break;
case STRING:
length = strlen(stack->value.s) + 1;
node->value.s = (char*) malloc(length * sizeof(char));
strcpy(node->value.s, stack->value.s);
free(stack->value.s);
break;
}
node->prev = 0;
stack = stack->prev;
free(temp);
} else {
/*TODO: handle empty case */
puts("Stack empty!");
}
}
void empty(Stack stack) {
while (!isempty(stack)) {
Node* temp = malloc(sizeof(Node));
pop(stack, temp);
free(temp);
}
}
Bool isempty(Stack stack) {
return stack->index == EMPTY ? TRUE : FALSE;
}
bool.h
#ifndef __BOOL__
#define __BOOL__
typedef int Bool;
#define FALSE 0
#define TRUE 1
#endif
main.c
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
int main() {
Stack stack = init();
Node* node = malloc(sizeof(Node));
int i = 5;
push(stack, 0, &i);
pop(stack, node);
printf("Node value: %d\n", node->value.i);
free(node);
empty(stack);
puts("done.");
return 0;
}
Really you are not modifying stack. You must to use &stack for push, pop and empty methods. They will have following signature:
void push(Stack * stack, int type, void* value);
void pop(Stack * stack, Node* node);
void empty(Stack *stack);
and, of course, use pointer contents inside these methods, like:
void push(Stack * stack, int type, void* value) {
int length;
Node* node = (Node*) malloc(sizeof(Node));
node->index = (*stack)->index + 1;
node->type = type;
switch(node->type) {
case INT:
node->value.i = *((int*) value);
break;
case CHAR:
node->value.c = *((char*) value);
break;
case STRING:
length = strlen((char*) value) + 1;
node->value.s = (char*) malloc(length * sizeof(char));
strcpy(node->value.s, value);
break;
}
node->prev = *stack;
*stack = node;
}
void pop(Stack * stack, Node* node) {
int length;
Node* temp = *stack;
if (!isempty(*stack)) {
node->index = (*stack)->index;
node->type = (*stack)->type;
switch((*stack)->type) {
case INT:
node->value.i = (*stack)->value.i;
break;
case CHAR:
node->value.c = (*stack)->value.c;
break;
case STRING:
length = strlen((*stack)->value.s) + 1;
node->value.s = (char*) malloc(length * sizeof(char));
strcpy(node->value.s, (*stack)->value.s);
free((*stack)->value.s);
break;
}
node->prev = 0;
*stack = (*stack)->prev;
free(temp);
} else {
/*TODO: handle empty case */
puts("Stack empty!");
}
}
void empty(Stack *stack) {
while (!isempty(*stack)) {
Node* temp = malloc(sizeof(Node));
pop(stack, temp);
free(temp);
}
}

Resources