stack implementation - linked list - c

I'm trying to figure out why my stack struct is not popping the elements and considers the stack to be NULL (i get the else condition from the pop() executing both times)? I'm confused because the printf shows the elements are being added onto to the stack.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int element;
struct node *pnext;
} node_t;
void push(node_t *stack, int elem){
node_t *new = (node_t*) malloc(sizeof(node_t)); // allocate pointer to new node memory
if (new == NULL) perror("Out of memory");
new->pnext = stack;
new->element = elem;
stack = new; // moves the stack back to the top
printf("%d\n", stack->element);
}
int pop(node_t *stack) {
if (stack != NULL) {
node_t *pelem = stack;
int elem = stack->element;
stack = pelem->pnext; // move the stack down
free(pelem); // free the pointer to the popped element memory
return elem;
}
else {
printf("fail");
return 0; // or some other special value
}
}
int main(int argc, char *argv[]){
node_t *stack = NULL ; // start stack as null
push(stack, 3);
push(stack, 5);
int p1 = pop(stack);
int p2 = pop(stack);
printf("Popped elements: %d %d\n", p1, p2);
return 0 ;
}

As said in a remark when you exit push/pop the variable stack in main is unchanged, so it is like you did nothing, except a memory leak in push
To have the new stack in main after a push that function can return the new stack, but this is not possible for pop already returning the poped value, so to have the same solution for both just use give the address of the variable in parameter to the functions to allow to modify it, so a double pointer rather than a simple
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int element;
struct node *pnext;
} node_t;
void push(node_t ** stack, int elem){
node_t *new = (node_t*) malloc(sizeof(node_t)); // allocate pointer to new node memory
if (new == NULL) {
perror("Out of memory");
exit(-1);
}
new->pnext = *stack;
new->element = elem;
*stack = new; // moves the stack back to the top
printf("%d\n", (*stack)->element);
}
int pop(node_t ** stack) {
if (*stack != NULL) {
node_t *pelem = *stack;
int elem = (*stack)->element;
*stack = pelem->pnext; // move the stack down
free(pelem); // free the pointer to the popped element memory
return elem;
}
else {
printf("fail");
return 0; // or some other special value
}
}
int main(int argc, char *argv[]){
node_t *stack = NULL ; // start stack as null
push(&stack, 3);
push(&stack, 5);
int p1 = pop(&stack);
int p2 = pop(&stack);
printf("Popped elements: %d %d\n", p1, p2);
return 0 ;
}
Compilation and execution :
% gcc -Wall s.c
% ./a.out
3
5
Popped elements: 5 3

Related

Stack using linked list in C, freeing temp_node in pop function but still want to return it

I am implementing a stack using linked list in C, and I stumbled upon two issues:
I need the stack_pop function to return a valid value temp, that is the temporary node/cell, and therefore, I can't free it. So, 1) Do you think freeing each node for every pop function call is better than until the end using the stack_destroy() 2) How can I achieve both, free(temp) and return it at the same time in stack_pop?
How bad my implementation becomes not using exit(1) in both stack_push and stack_pop functions?
This is the implementation:
//// Stack
// Linked list
typedef struct {
int data;
Cell* next;
} Cell;
struct stack_l {
size_t count;
Cell *top;
};
typedef struct stack_l *Stack;
You've got stack_pop declared to return an int, but you're attempting to return a Cell * which doesn't make sense.
Copy the value in the popped cell to a local variable, free the popped cell, then return the value.
temp = stack->top;
stack->top = stack->top->next;
temp->next = NULL;
stack->count--;
int val = temp.data;
free(temp)
return val;
Also, it makes no sense to call exit in either stack_push or stack_pop as that ends the program.
I think it is a bit overcomplicated. You only need to remember the previous stack pointer. Nothing else
typedef struct stack
{
int data;
struct stack *prev;
}stack;
stack *push(stack **sp, int data)
{
stack *new = malloc(sizeof(*new));
if(new)
{
new -> prev = *sp;
new -> data = data;
*sp = new;
}
return new;
}
int isempty(stack *sp)
{
return !stack_pointer;
}
int pop(stack **sp)
{
stack *new;
int result = 0;
if(sp && *sp)
{
result = (*sp) -> data;
new = (*sp) -> prev;
free(*sp);
*sp = new;
}
return result;
}
int main(void)
{
stack *stack_pointer = NULL;
int result;
push(&stack_pointer, 1);
push(&stack_pointer, 2);
push(&stack_pointer, 3);
do
{
result = pop(&stack_pointer);
printf("%d\n", result);
}while(stack_pointer) ;
printf("Stack was empty so the loop has exited\n");
}

My code for pre-order traversal of Binary Search Tree is working but how is the stack whose each element is a pointer to the structure working?

This is my code of preorder traversal of BST. It's working fine on Ubuntu. But I don't understand one thing.
In the function iterative_preorder(), I actually wanted a stack to store the pointers to the structure that I defined on the top. I want to know the concept that how is it working. Since, while allocating memory to the stack, I didn't specify anywhere separately that stack should contain size number of pointers to the structure.
Like, when we define:
int stack[size];
We know that stack[1] will be the second block in the stack. But here, I used malloc, which actually just makes one block of the size specified as size * sizeof(node *).
So when the program executes:
stack[++top] = root;
How does the program understand that it has to go to the next pointer to the structure in the stack? I hope my question is clear.
I made another small program, based on the confusion that I had. Here, instead of structure, I used int. I tried to create a stack of size 2, which stores pointers to the integer. Here's the code:
#include <stdio.h>
#include <stdlib.h>
void main() {
int** stack = (int**)malloc(2 * sizeof(int*));
printf("%d", *stack[0]);
}
But this code is throwing segmentation fault (core dumped). As both the codes used the same logic, just that this one used int instead of structure, I don't understand why this is throwing error.
#include <stdio.h>
#include <stdlib.h>
int size = 0;
typedef struct mylist {
int data;
struct mylist *left;
struct mylist *right;
} node;
node *root;
void create_root(node *root) {
root = NULL;
}
//Inserting nodes
node *insert(node *root, int val) {
node *ptr, *parentptr, *nodeptr;
ptr = (node*)malloc(sizeof(node));
ptr->data = val;
ptr->left = NULL;
ptr->right = NULL;
if (root == NULL)
root = ptr;
else {
parentptr = NULL;
nodeptr = root;
while (nodeptr != NULL) {
parentptr = nodeptr;
if (val < nodeptr->data)
nodeptr = nodeptr->left;
else
nodeptr = nodeptr->right;
}
if (val < parentptr->data)
parentptr->left = ptr;
else
parentptr->right = ptr;
}
return root;
}
void iterative_preorder(node *root) {
if (root != NULL) {
int top = -1;
node **stack = (node**)malloc(size * sizeof(node*));
node *cur;
stack[++top] = root;
while (top > -1) {
cur = stack[top--];
printf("%d\t", cur->data);
if (cur->right != NULL)
stack[++top] = cur->right;
if (cur->left != NULL)
stack[++top] = cur->left;
}
}
}
void main() {
int option, val;
node *ptr;
int flag = 1;
create_root(root);
while (flag != 2) {
printf("\nChoose-\n1-Insert\n2-Iterative Preorder Traversal\n3-Exit\n");
scanf("%d", &option);
switch (option) {
case 1: {
printf("\nEnter the value of new node\n");
size++;
scanf("%d", &val);
root = insert(root, val);
}
break;
case 2:
iterative_preorder(root);
break;
case 3:
flag = 2;
break;
default:
printf("\nWrong entry\n");
}
}
}
Your code has a dereference of uninitialized pointer error.
int** stack = (int**)malloc(2*sizeof(int*));
printf("%d",*stack[0]);
In the above code, stack points to an array of two int pointers, what stack[0] points to? it's not initialized.
A live test of your code is available here segfault. you can modify and test it again.

C program:Converting infix to postfix using linked list stack and queue

This is the first time I learn programming. I'm a first year unversity student. My major is software engineering. This is my third assignment for software class.
The teacher wants this program reads in an infix expression from the command line and outputs a postfix expression. We should use "the Shunting Yard algorithm".We should have 2 linked list queue and 1 linked list stack. 2 queues for holding input and output and a stack for holding operators. We also should write general enqueue,dequeue, pop,push function that I already did.
The Shunting Yard algorithm:
put arguments into input queue
dequeue token from input queue
if oprand(number),add to output queue
if operator, the pop operators off stack and add to output queue as long as top operator on stack has higher or equal precedence, then push new operator onto stack
return to step 1 as long as tokens remain in input
pop remaining operators from stack and add to output queue
The program should operate as follows:
programename 34 / 5 + 16 * 2
postfix: 34 5 / 16 2 * +
We also should space between each output
This is so hard for me as a beginner. I already spend more than thirty hour in this program. But the program doesn't work. The program continues run in the "while" loop in main function and never stop. I would be very aprciate if someone can help me.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct listnode {
//Define structure of the node
char *element;
struct listnode* pnext;
};
struct Stack {
//Define structure of the stack
struct listnode* ptop;
};
struct Queue {
//Define structure of the queue
struct listnode* pfront;
struct listnode* prear;
};
void push (struct Stack* stack,char* element);
char* pop (struct Stack* stack);
void enqueue(struct Queue* queue,char* element);
char* dequeue(struct Queue* queue);
void s_travel(struct Stack* stack);
void q_travel(struct Queue* stack);
int precedence(char* x);
int empty(struct Stack* stack);
char* peek(struct Stack* stack);
int main (int argc,char *argv[]) {
struct Stack stack;
struct Queue input_queue;
struct Queue output_queue;
stack.ptop = NULL;
input_queue.pfront = NULL;
input_queue.prear = NULL;
output_queue.pfront = NULL;
output_queue.prear = NULL;
if (argc<3) {
//If the arguments is less then 3, unavailable input
printf("Input error");
return -1;
}
int i=0;
//Put all the arguments into the input_queue
for (i=1;i<argc;i++) {
enqueue(&input_queue,argv[i]);
}
printf("infix expression is : ");
q_travel(&input_queue);
printf("at the beginning, the peek of the stack is %s \n",peek(&stack));
for (i=1;i<argc;i++) {
//Token from input_queue
char *token;
char *x;
token = dequeue(&input_queue);
if(atof(token)) {
//If the element is a number,put it into output_queue
enqueue(&output_queue,token);
}
else {
/*If the element is a operator, c
* ompare the precedence of the top element of the stack and the precedence of token element
*/
char *peek1;
peek1=peek(&stack);
while ((precedence(peek1) >= precedence(token)) && (peek1 != NULL)){
/*while the precedence of the top element of the stack is greater
and equal to the precedence of token element*/
printf("inside,the top of the stack is %s \n",peek1);
//Pop element out of the stack and put it into output_queue
x = pop(&stack);
printf("after pop,x is %s,the top of the stack is %s \n",x,peek1);
enqueue(&output_queue,x);
}
//Then, push the new operator(token) into the stack
push(&stack,token);
}
}
while(peek(&stack)!=NULL) {
//Enqueue remaining operator from stack into output_queue
char *elem = pop(&stack);
enqueue(&output_queue,elem);
}
printf("Postifx expression is :\n");
q_travel(&output_queue);
return 0;
}
void push (struct Stack* stack,char* element) {
//Allocate a new node
struct listnode* new_node = (struct listnode *)malloc(sizeof(struct listnode));
new_node->element = element;
//Add new node at the top of the stack
new_node->pnext = stack->ptop;
stack->ptop = new_node;
}
char* pop (struct Stack* stack_buffer) {
//If the stack is not empty
if (stack_buffer->ptop) {
//Create a temporary node to replace top(removed) node
struct listnode *pelem = stack_buffer->ptop;
//The top pointer points to the next node
stack_buffer->ptop = pelem->pnext;
//Store the element of the removed node
char *elem = pelem->element;
//Remove node from memory
free(pelem);
//Return the element of the node that we removed
return elem;
}
//If the stack is empty, removing element fails,return -1
else {
return NULL;
}
}
void enqueue(struct Queue* queue,char *element) {
//Allocate a new node
struct listnode *new_node = (struct listnode *)malloc(sizeof(struct listnode));
new_node->element = element;
new_node->pnext = NULL;
//If the queue is not empty,add new node at the end of the queue
if (queue->prear) {
queue->prear->pnext = new_node;
}
//If the queue is empty,add new node at front of the queue
else {
queue->pfront = new_node;
}
//Added node becomes new rear node
queue->prear = new_node;
}
char* dequeue(struct Queue* queue) {
/*Create a temporary node to replace the front node of the queue
struct listnode *pelem = queue->pfront;*/
//If the queue is not empty
if (queue->pfront) {
//Store the element of the front node
char *elem = queue->pfront->element;
//The front pointer points to the next node
queue->pfront = queue->pfront->pnext;
//If the queue only has one node
if(pelem == queue->prear) {
//After removing the only node, the queue becomes empty
queue->prear = NULL;
}
//Remove node from memory
free(pelem);
//Return the element of the node that we removed
return elem;
}
//If the queue is empty, removing node fails,return NULL
else {
return NULL;
}
}
void s_travel(struct Stack* buffer) {
//Function to print out the element in the stack
//Create a temporary node to replace the top node of the stack
struct listnode* elem = buffer->ptop;
while(elem != NULL) {
printf("%s ", elem->element);
elem = elem->pnext;
}
printf("\n");
}
void q_travel(struct Queue* buffer) {
//Function to print out the element in the queue
//Create a temporary node to replace the front node of the stack
struct listnode* elem = buffer->pfront;
while(elem != NULL) {
printf("%s ", elem->element);
elem = elem->pnext;
}
printf("\n");
}
int precedence(char* operator) {
/*Function to determine the precedence of the operator,prior operator has greater return value*/
printf("entering precedence with %s \n",operator);
if (operator == NULL) {
return -1;
}
else if (strcmp(operator,"(")==0){
printf("Pr: %s 0\n",operator);
return 0;
}
else if (strcmp(operator,"+")==0||strcmp(operator,"-")==0) {
printf("Pr: %s 1\n",operator);
return 1;
}
else if ( (strcmp(operator,"*")==0) || (strcmp(operator,"/")==0) || (strcmp(operator,"%")==0) || (strcmp(operator,"x")==0) ) {
printf("Pr: %s 2\n",operator);
return 2;
}
else {
return -2;
}
return -3;
}
int empty(struct Stack* stack) {
//Function to check if the stack is empty
//If the stack is empty, the return value would be 1;otherwise, it would be 0
return NULL == stack->ptop;
}
char* peek(struct Stack* stack) {
//Function to find out the top element of the stack
//If the stack is empty, return NULL
if (empty(stack)) {
return NULL;
}
//If the stack is not empty, return the top element of the stack
char* elem = stack->ptop->element;
return elem;
}

Dynamic stack in C [pop crash] [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Im making a program to convert a decimal int to binary using a dynamic stack.
It crashes on the last pop.
ex. num: 4 output: 10crash
#include <stdio.h>
struct stack {
struct stack *prev;
int val;
struct stack *next;
};
struct stack *first,*cur,*tmp;
struct stack *GETNODE(){
struct stack *pt = (struct stack *)malloc(sizeof(struct stack));
};
int counter=1;
void push(int val){
tmp=GETNODE();
tmp->prev=NULL;
tmp->val=val;
tmp->next=NULL;
if(first==NULL){
first=tmp;
cur=first;
}else{
tmp->prev=cur;
cur->next=tmp;
cur=tmp;
}
counter++;
};
int pop(){
int val=tmp->val;
cur=tmp->prev;
free(tmp);
tmp=cur;
tmp->next=NULL;
counter--;
return(val);
};
main(){
int num = 4;
while(num!=0){
push(num%2);
num/=2;
}
while(counter!=1){
printf("%d ",pop());
}
}
The problem is in your pop function. If you think about how it operates, in the final pass you will free(tmp), which is currently pointing to the very first item. After you free it, you then assign:
tmp->next=NULL;
You are trying to dereference an invalid pointer at this point.
I made a lot of changes to your code. Mainly, it was far too complicated - only a singly linked list was needed, and you don't need a counter - just track the list pointer. Your GETNODE() function did not return a value, causing undefined behaviour in the calling function. I simplified that too, there is no need for a separate function to allocate memory because malloc() already does that.
#include <stdio.h>
#include <stdlib.h>
struct stack {
struct stack *prev;
int val;
};
struct stack *first = NULL;
void push(int val){
struct stack *pt = malloc(sizeof(struct stack));
if (pt == NULL){
printf ("Bad call to malloc()\n");
exit (1);
}
pt->prev=first;
pt->val=val;
first = pt;
}
int pop(){
int val;
struct stack *pt = first;
if (first == NULL)
return -1;
val=first->val;
first = first->prev;
free(pt);
return(val);
}
void dec2bin(int num){
printf("%-5d", num);
while(num!=0){
push(num%2);
num/=2;
}
while(first){
printf("%d",pop());
}
printf("\n");
}
int main(void){
dec2bin (4);
dec2bin (129);
dec2bin (160);
return 0;
}
Program output:
4 100
129 10000001
160 10100000
I change some part of your code and your code working now.
#include <stdio.h>
#include <stdlib.h>
struct stack {
struct stack *prev;
int val;
struct stack *next;
};
struct stack *first, *cur, *tmp;
int counter = 0;
struct stack *GETNODE()
{
return malloc(sizeof(struct stack));
}
void push(int val)
{
tmp = GETNODE();
tmp->prev = NULL;
tmp->val = val;
tmp->next = NULL;
if (first == NULL) {
first = tmp;
cur = first;
} else {
tmp->prev = cur;
cur->next = tmp;
cur = tmp;
}
counter++;
}
int pop(void)
{
int val = cur->val;
tmp = cur;
cur = cur->prev;
free(tmp);
counter--;
return val;
}
int main(int argc, char *argv[])
{
int num;
scanf("%d", &num);
while (num != 0) {
push(num % 2);
num /= 2;
}
while (counter != 0)
printf("%d ", pop());
printf("\n");
}

malloc and pointer in a struct

I have the following C code:
typedef struct DListNode_ {
void *data;
struct DListNode_ *prev;
struct DListNode_ *next;
} DListNode;
typedef struct DList_ {
int size;
DListNode *tail;
DListNode *head;
} DList;
void insert(DList * list, DListNode * element, int data) {
DListNode * new_element = (DListNode *)malloc(sizeof(DListNode));
new_element->data = &data;
if (list->head==NULL) {
list->head=list->tail=new_element;
list->size++;
return;
}
if(element == NULL) {
// handle size==0?
new_element->next=list->head;
list->head->prev=new_element;
list->head=new_element;
list->size++;
} else {
printf("Not yet implemented!\n");
}
}
void printNodes(DList *list) {
DListNode * pointer = list->head;
if (pointer!=NULL) {
int v= *((int*)pointer->data);
printf("Node has value: %d\n", v);
while (pointer->next != NULL) {
v = *((int*)pointer->data);
printf("Node has value: %d\n", v);
pointer=pointer->next;
}
}
}
int main(int argc, const char * argv[])
{
int e0 = 23;
int e1 = 7;
int e2 = 11;
DList *list = (DList *)malloc(sizeof(DList));
initList(list);
assert(count(list)==0);
insert(list, NULL, e0);
assert(count(list)==1);
insert(list,NULL, e1);
assert(count(list)==2);
insert(list,NULL, e2);
assert(count(list)==3);
printNodes(list);
return 0;
}
I have a few problems:
does DListNode * new_element = (DListNode *)malloc(sizeof(DListNode)); also allocate space for the, data, prev, next pointer or do I manually need to call malloc on each of those pointers?
When I print the content of the data pointer in each node they all have the value 3 even though I insert 23, 7 and 11 and set the data pointer to the address of the int: ** new_element->data = &data;**.
(Introductionary textbooks on C have been ordered)
EDIT:
insert now takes a void pointer to the data:
// Insert data as the new head
void insert(DList *list, DListNode *element, void *data) {
DListNode *new_element = malloc(sizeof(DListNode));
new_element->data = data;
if (list->head==NULL) {
list->head=list->tail=new_element;
list->size++;
return;
}
if(element == NULL) {
new_element->next=list->head;
list->head->prev=new_element;
list->head=new_element;
list->size++;
} else {
printf("Not yet implemented!\n");
}
}
In main I do:
int main(int argc, const char * argv[])
{
int i0=7;
int *ip0 = malloc(sizeof(int));
ip0 = &i0;
int i1=8;
int *ip1 = malloc(sizeof(int));
ip1 = &i1;
int *ip2 = malloc(sizeof(int));
int i2=44;
ip2 = &i2;
DList *list = malloc(sizeof(DList));
initList(list);
// create some nodes
assert(count(list)==0);
insert(list, NULL, ip0);
assert(count(list)==1);
insert(list,NULL, ip1);
assert(count(list)==2);
insert(list,NULL, ip2);
assert(count(list)==3);
printNodes(list);
return 0;
}
which outputs:
Node has value: 44
Node has value: 44
Node has value: 8
but it should be:
Node has value: 44
Node has value: 8
Node has value: 7
malloc(sizeof(DListNode)) allocates space for exactly one DListNode, which by definition consists of a void* and two DListNode pointers. It does not initialize those pointers, though.
You're assigning the address of the data argument to insert. That's a pointer to a temporary which is invalidated once insert returns. The behavior of the program is undefined. The easy solution is to just replace void *data by int data.
You need to manually set those pointers to where they point with malloc. Without it, they will point to a space that isn't of size DListNode.
Don't make the data a pointer. Just make the data an int (it gets auto allocated) and then just set data = data (the data that is passed into insert).

Resources