Implementing a linked list with a stack in C - c

For a prelab (meaning it's not for a grade), I'm supposed to implement my first ever stack using linked lists. I wrote it adding only one thing to the stack just as practice, as to why it's so short. Anyway, I have no compile errors, besides it saying that "new" is uninitialized in my create_stack function. This is also where I'm getting a segmentation fault, as it's not printing out my first printf function. I am also guessing that the problem is bigger than just me initializing the stack, but this is my problem's start. Please go easy on me if it's something simple, as, like I said, it's my first time doing stacks, and thanks for your help.
#include <stdio.h>
#include <stdlib.h>
typedef struct node_{
char data;
struct node_ *next;
}node;
typedef struct stack_{
unsigned int size;
node* stack;
}stack;
stack* create_stack();
void push(stack* s, char val);
char top(stack* s);
void pop(stack*s);
int main(void) {
char value, val;
stack* new = create_stack();
printf("Enter a letter: ");
scanf("%c", &value);
push(new, value);
val = top(new);
printf("%c\n", val);
pop(new);
return 0;
}
stack* create_stack(){ //initializes the stack
stack* new;
new->size = 0;
new->stack = NULL;
return new;
}
void push(stack* s, char val) {
node* temp = (node*)malloc(sizeof(node)); //allocates
if ( temp == NULL ) {
printf("Unable to allocate memory\n");
}
else{
temp->next = s->stack;
temp->data = val;
s->stack = temp;
s->size = (s->size) + 1; //bumps the counter for how many elements are in the stack
}
}
void pop(stack* s) {
node* temp;
temp = s->stack;
s->stack = temp->next;
free(temp);
s->size = (s->size) - 1; //subtracts from counter
}
char top(stack* s) {
node* temp = s->stack;
char value = temp->data;
return value;
}

The reason it crashes is that you never allocate any memory when you create the stack. Do stack* new = malloc (sizeof(stack)); in the create_stack function.
For the future you might want to use better variable names. Using for instance using new as the name for the stack isn't that good - it isn't very descriptive plus it's a reserved keyword in several languages, C++ for example.

stack *new creates a local pointer, but it has nothing to point to yet. Since you want the stack to continue to exist after the function completes, you should allocate memory for it using malloc (and eventually free it using free).
So your create_stack function should start with:
stack* new = malloc(sizeof(stack));
An alternative would be to declare the stack as a local variable in your main function, and pass it as an argument into create_stack to initialize it:
stack new;
create_stack(&new);

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");
}

How to implement a character string in a linked list

The main code itself works fine but I want to make use of character strings instead of the char, and it might be because I've overlooked something absurdly simple. Here is a small snippet of code:
struct Stack
{
char *SData;
int counter;
struct Stack *next;
};
struct Stack* StackNewNode(char SData)
{
struct Stack *stackNode = (struct Stack*)malloc(sizeof(struct Stack));
stackNode->SData = SData; //error here because of the difference of char, should i use []?
stackNode->next = NULL;
return stackNode;
}
void PUSH(struct Stack **root, char SData) //this part only pushes a character
{
struct Stack *stackNode = StackNewNode(SData);
stackNode->next = *root;
*root = stackNode;
printf("\n%c pushed to stack\n", SData);
}
void POP(struct Stack **root)
{
if (*root == NULL)
{
return;
}
struct Stack *temp = *root;
*root = (*root)->next;
char pop = temp->SData; //how should i pop a full string?
free(temp);
printf("%c popped from stack\n", pop);
}
I also want to implement a counter in the Stack. Should i use Stack->counter++ or is there some other more correct way to do it?
Sorry for the wall of text its my first time here
I don't see counter in struct Stack used anywhere in the code snippets you provided. Assuming you want some count of the number of elements in the stack, it wouldn't make sense for this value to be part of the struct. After all, you only need one count, not one attached to every element in the stack. You would want to make this its own variable, perhaps a global defined in the same place as you define root. Just make sure to initialize it to zero.
As for using character strings, you already have char *SData, which can point to a string. All you need to do is change PUSH and StackNewNode to use char* parameter rather than char and then pass it a string, something like this:
PUSH(&root, "My string");
To start with your current code have some type mismatch here: stackNode->SData = SData;
stackNode->SData is a char pointer and SData is a char. I assume your compiler warns you about that - never ignore warnings.
If you want to use C type string you need updates like:
Pass char pointer instead of char
Allocate memory for the string
Copy the passed string to the allocated memory
Free the memory when done
Something like:
struct Stack
{
char *SData;
int counter;
struct Stack *next;
};
struct Stack* StackNewNode(const char* str)
{
struct Stack *stackNode = malloc(sizeof(struct Stack));
if (stackNode == NULL) exit(1);
stackNode->SData = malloc(strlen(str) + 1);
if (stackNode->SData == NULL) exit(1);
strcpy(stackNode->SData, str);
stackNode->next = NULL;
return stackNode;
}
void PUSH(struct Stack **root, const char* str)
{
struct Stack *stackNode = StackNewNode(str);
stackNode->next = *root;
*root = stackNode;
printf("\n%s pushed to stack\n", str);
}
void POP(struct Stack **root)
{
if (*root == NULL)
{
return;
}
struct Stack *temp = *root;
*root = (*root)->next;
printf("%s popped from stack\n", temp->SData);
free(temp->SData);
free(temp);
}
Usage example:
struct Stack *root = NULL;
PUSH(&root, "Hello World");
Adding a counter
In your code you have placed int counter; inside every stack element. You can make that work but I would prefer two structs. One struct type holding information about the whole stack and another struct type for the elements.
Like:
struct StackNode
{
char *SData;
struct StackNode *next;
};
struct Stack
{
int counter;
struct StackNode *root;
};
The functions would need some updates like:
void PUSH(struct Stack *stack, const char* str)
{
struct StackNode *stackNode = StackNewNode(str);
stackNode->next = stack->root;
stack->root = stackNode;
++stack->counter; // Increment counter
printf("\n%s pushed to stack\n", str);
}
Usage example:
struct Stack stack = {0, NULL};
PUSH(&stack, "Hello World");

Segmentation fault when reading from stack

This is my first time creating stacks. I'm quite clear at what I must do, but am quite discouraged by the code not working.
It runs fine till I try to retrieve any data from the root, which immediately results in a segfault.
Here's my program:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct stackNode
{
char letter;
struct stackNode * next;
};
int size=0;
int capacity=10;
struct stackNode * root=NULL;
void push(char data, struct stackNode * root)
{
if(size==capacity)
{
printf("Error: Stack Overflow\n");
return;
}
struct stackNode * new=(struct stackNode *)malloc(sizeof(struct stackNode *));
new->letter=data;
new->next=root;
printf("%c,%u", new->letter, new->next);
root=new;
printf("%c,%u", new->letter, new->next);
size++;
}
char pop(struct stackNode ** root)
{
if(size==0)
{
printf("Error: Stack is Empty\n");
return '\0';
}
printf("\npop*\n");
char temp;
printf("\n*\n");
struct stackNode * tempad;
printf("\n*\n");
temp=(*root)->letter;
printf("\n*\n");
tempad=*root;
printf("\n*\n");
*root=(*root)->next;
printf("\n*\n");
free(tempad);
printf("\n*\n");
size--;
return temp;
}
int main()
{
push('c', root);
push('v', root);
push('n', root);
printf("%c %c %c", pop(&root), pop(&root), pop(&root));
}
Here's the output:
pop*
*
*
Segmentation fault
Could someone point out the mistake?
The main issue is usage of unnecessary global variables which seem to be causing confusion. In push, the parameter is of type struct stackNode * yet it's being manipulated as if it referred to the global root. But root = new is purely local and has no impact on the global root. However, size++ does impact the global scope. This corrupts the stack's logical state, and your error handler at the beginning of pop thinks that size == 3 and doesn't complain. The function then dutifully dereferences root, crashing the program.
A correct stack class should not use global data. It should encapsulate all necessary state in structs. This makes it reusable, enabling creation of multiple stacks (a property I'd want in most classes I'm using).
A few other suggestions:
Avoid side effects where possible. Prints are OK for temporary debugging purposes but should be completely separated from program logic otherwise.
If you are planning on writing error handlers, print to stderr and avoid magic values like return '\0'; that might be mistaken for actual node data.
Don't cast the result of malloc. This can suppress errors and is visually noisy.
Hardcoding capacity feels pretty arbitrary. I'm not sure there's any point to having this (but if there is, add it to the struct). If there's too much metadata about the stack inside each node (ideally, there should be none), create a Stack struct to contain this metadata and point it to the actual stackNode chain.
Another stack design point: malloc/free are slow. For character data, a simple array with a top pointer will be faster and simpler to implement. You can amortize allocation calls with periodic doubling the array when top >= capacity and contracting when top < capacity / 2.
Here's a quick re-write (without the suggestion for the Stack wrapper struct or the array):
#include <stdio.h>
#include <stdlib.h>
struct stackNode {
char letter;
struct stackNode *next;
int size;
};
void push(char data, struct stackNode **root) {
struct stackNode *new = malloc(sizeof(*new));
new->size = *root ? (*root)->size + 1 : 1;
new->letter = data;
new->next = *root;
*root = new;
}
char pop(struct stackNode **root) {
if (!*root || !(*root)->size) {
fprintf(stderr, "pop from empty stack\n");
exit(1);
}
char popped = (*root)->letter;
struct stackNode *cull = *root;
*root = (*root)->next;
free(cull);
return popped;
}
int main() {
struct stackNode *root = NULL;
push('c', &root);
push('v', &root);
push('n', &root);
while (root) {
printf("%c ", pop(&root));
}
puts("");
return 0;
}
This is really confusingly written code (i.e globals with the same name as variables in the local scope). I'm just going to rewrite it, untested and on mobile but should be fine. You can diff to see the issue(s). For one thing though you're setting local variable root to the newest allocation rather than global root.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct stackNode
{
char letter;
struct stackNode* prev;
};
stackNode* kTailStack = NULL;
void push(char data)
{
stackNode* p=(stackNode *)malloc(sizeof(stackNode));
p->letter=data;
p->prev=kTailStack;
kTailStack = p;
}
char pop()
{
stackNode* prev_tail = kTailStack;
char n = 0;
if (prev_tail != NULL)
{
n = prev_tail->letter;
kTailStack = prev_tail->prev;
free(prev_tail);
}
return n;
}
int main()
{
push('c', kTailStack);
push('v', kTailStack);
push('n', kTailStack);
printf("%c %c %c", pop(kTailStack), pop(kTailStack), pop(kTailStack));
}

Destructor and constructor in C

I'm very new to C and I'm trying yet to fully understand it. I implemented a stack
but found trouble when making its destructor and it constructor/init.
Are these well done?
These are the typedefs for the structures used by the stack:
typedef struct Node{
void* cargo;
struct Node* next;
}Node;
typedef struct Stack{
int size;
Node* firstOut;
}Stack;
And these are the functions:
void newStack(Stack* stack){
stack = (Stack*)malloc(sizeof(Stack));
stack->firstOut = NULL;
stack->size = 0;
}
void freeStack(Stack** stack){
empty((*stack));
free((*stack)->top);
(*stack)->size = 0;
free(stack);
}
My question is: are they well done? How would someone with proper experience do it?
newStack should simply return the stack pointer that it allocates. It doesn't need to receive a Stack* as an argument.
stack *newStack() {
Stack *stack = malloc(sizeof(Stack));
if (stack != NULL) { // allocation successful
stack->firstOut = NULL;
stack->size = 0;
}
return stack;
}
and freeStack should receive a stack pointer as argument, it doesn't need double indirection.
void freeStack(Stack *stack) {
empty(stack);
free(stack->firstOut); // This isn't done by empty()?
free(stack);
}
There's no need to set stack->size before freeing, since the memory is going to go away and the value it contains is irrelevant.

C Programming Stack

I am currently working on stacks right now. I am supposed to use the following structures and function prototypes:
typedef struct node_{
char data;
struct node_ *next;
}node;
typedef struct stack_{
unsigned int size;
node* stack;
}stack;
stack* create_stack();
void push(stack* s, char val);
Here is my actual code for create_stack() and push():
stack* create_stack()
{
stack *stack;
stack = malloc(sizeof(stack));
stack->size = 0;
stack->stack = NULL;
return stack;
}
void push(stack* s, char val)
{
stack *newStack;
newStack = create_stack();
newStack->stack->data = val;
newStack->stack = s->stack;
s = newStack;
}
I am getting a segmentation fault when I try to store char val into newStack->stack->data. How does this not work? What do I need to do to make this stack on top???
The push function is wrong.
void push(stack* s, char val)
{
stack *newStack;
newStack = create_stack(); /* new stack created, why not work on the existing one ? */
newStack->stack->data = val; /* you're writing to a NULL pointer */
newStack->stack = s->stack;
s = newStack; /* this will not be visible from outside the function */
}
First of all, you are trying to recreate a new stack for each call of this function, which is certainly not what is intended.
If you try to modify the value of s, it will not be visible from outside the function, and you will still have your original stack.
Then, you are accessing the stack->data member even though stack has no space allocated to it yet (because you set it to NULL). You actually set it right after, which is why it crashes, most probably.
You probably want to do something like this:
void push(stack* s, char val)
{
node * n;
/* go to the end of the "stack" */
n = s->stack;
while (n != NULL) {
n = n->next;
}
/* allocate memory for a new node */
n = malloc(sizeof(node));
/* initialize node */
n->data = val;
n->next = NULL;
/* increment stack size */
s->size++;
}
And as mentionned before, this is merely a singly-linked list which is not the best fit for a stack, because as it exists now, you have to follow the node pointers to reach the last element, which makes push and pop operations O(N).
A faster implementation would look like this:
void push(stack* s, char val)
{
node * first_node, * new_node;
first_node = s->stack;
/* allocate memory for a new node */
new_node = malloc(sizeof(node));
/* initialize node */
new_node->data = val;
new_node->next = first_node;
/* increment stack size */
s->stack = new_node;
s->size++;
}
The top of the stack is always the first node, and the performance is O(1).
Follow your code....
stack *newStack = create_stack(); // in push()
newStack = malloc(sizeof(stack)); // in create_stack()
newStack->stack = NULL; // in create_stack()
newStack->stack->data = val; // in push()... this is where you crash.
Because newStack->stack is a NULL pointer. Your create_stack() function sets it to NULL, and you then dereference it. You have to allocate a struct node somewhere.
This code also has some readability issues which might be contributing to the problem. You are naming variables the same names as their types, which is very confusing. Consider using some other naming pattern like stack_t for types and stack for variable names.

Resources