I've created a Stack structure in C. When the stack is initialized with a value, I am able to print it back and receive the correct output. However, after pushing a new string, the print function prints what appears to be a random character (ASCII 177).
Originally, I implemented this project with pointers, but I was unable to get it working. Instead, I opted to only use a pointer for the Node *nodes member of Stack. That way, when I need to grow the stack, I can just multiply the amount of memory required by Stack.size. However, this approach has not worked yet either.
#define MAX_DATA 64
struct Node{
char val[MAX_DATA];
};
struct Stack{
int size;
struct Node *nodes;
};
These are used as follows:
struct Node node = {.val = "Test"};
struct Stack stack = newStack(node);
printStack(stack);
The newStack function initializes nodes properly. For the sake of inclusion:
struct Stack newStack(struct Node node)
{
struct Stack stack;
stack.size = 1;
stack.nodes = (struct Node*) malloc(sizeof(struct Node));
stack.nodes[0] = node;
return stack;
}
The stack is then printed iteratively in printStack(), with stack.size being the upper bound of the for-loop.
The trouble comes when I try to run:
struct Node node2 = {.val = "Test1"};
push(stack, node2);
printStack(stack);
The push function aims to create a temporary stack and assign the value of the stack to it. After this, the size is incremented, the pointer to the nodes is freed, and new memory is allocated, with room for a new member at the end.
void push(struct Stack stack, struct Node node)
{
struct Stack temp_stack = stack;
stack.size += 1;
free(stack.nodes);
stack.nodes = (struct Node*) malloc(sizeof(struct Node) * stack.size);
for(int i = 0; i < temp_stack.size; i++){
stack.nodes[i] = temp_stack.nodes[i];
}
stack.nodes[stack.size - 1] = node;
}
Needless to say, this doesn't execute properly.
The expected output would be:
Test
Test1
But, instead, I receive only ASCII-177. It is also worth noting that the execution hangs after it prints that and moves to the new line. This results in Aborted (core dumped).
Am I improperly freeing and re-allocating memory? Any help would be appreciated. Thank you in advance!
It's worth remembering that in C, passing a struct to a function is pass-by-value, i.e., the function gets a copy of the struct. All members of the struct, including pointer variables (but not whatever the pointer references), are duplicated.
So in the push function, think about what happens to the original when you modify this copy (e.g., stack.size += 1, and also when you free() the stack.nodes.
Thank you to peekay for the recommendations. I ended up doing a re-write. It became quite a bit simpler. I did remove a layer of "visibility" by storing the nodes as a pointer, but I suppose this implementation is a bit more true to the data structure.
Node is implemented as a means to hold data, and the user doesn't interact with it directly. It also points to the following Node. Stack is implemented to hold the top Node, and also the size of the Stack.
Node:
struct Node{
char val[MAX_DATA];
struct Node *next;
};
Stack:
struct Stack{
struct Node *top;
int size;
};
Push:
void push(struct Stack *stack, char *newVal)
{
struct Node *newNode;
newNode = (struct Node*) malloc(sizeof(struct Node));
strcpy(newNode->val, newVal);
newNode->next = stack->top;
stack->top = newNode;
stack->size++;
}
Usage:
struct Stack stack;
newStack(&stack);
push(&stack, "Test");
push(&stack, "Test1");
push(&stack, "Test2");
push(&stack, "Test3");
Complete Code
Updated, accessible Nodes
Related
What I did :
I added a pointer in the parameter of malloc(struct Node *) which is usually malloc(struct Node).
Problem :
When I am allocating memory for the size of a pointer then how the code is working?
malloc() is allocating 8 bytes of memory and returning the pointer
So the pointer points to an 8 bytes memory block which but further I am storing more data in it.
struct Node
{
int data;
struct Node *next;
};
struct Node *GetNode(int data)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node *));
node->data = data;
node->next = NULL;
return node;
}
Difference in size:
I know that malloc is allocating different sizes because I did this
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void main(){
int i = sizeof(struct Node);
int j = sizeof(struct Node *);
printf("%d,%d", i, j);
}
Output
16,8
What you've done is undefined behavior. It could work (on some systems, on certain days of the week), or it could crash, or it could produce incorrect results in seemingly unrelated calculations.
Imagine you rent a garage space for your truck, but to save money you request a space for a car. What happens when you drive your truck in? Maybe it fits, maybe you wreck the truck, maybe you destroy the garage.
So don't do that, and to help you find cases where you've made similar mistakes, build with Address Sanitizer. It will log when you access memory in an invalid way.
UB is a fickle mistress. Sometimes agreeable; sometimes not.
That is why you should use a syntax that makes it less likely to make mistakes:
struct Node *node = (struct Node *)malloc(sizeof(struct Node *)); // bad
struct Node *node = malloc( sizeof *node ); // good
No casting, and no redundancy.
I would even recommend using typedef's to free yourself from "struct, struct, struct".
typedef struct s_node
{
int data; // use more indentation, please. whitespace is cheap.
struct s_node *next;
} Node_t;
/* ... */
Node_t *node = malloc( sizeof *node ); // better
Finally, a lot of hours are wasted tracking down bugs that appear and disappear. Until performance becomes a real issue that you understand, I'd recommend using calloc() as the go-to allocation function:
Node_t *node = calloc( 1, sizeof *node ); // best
You can sleep easier knowing the byte values will be repeatable from run to run.
All the implementations I have seen online use pointer to declare nodes and then will use malloc to create space for them like this:
struct Node
{
int data;
struct Node *next;
};
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
...
But I can also create the same without pointers and malloc like this:
struct node {
int id;
struct node* next;
};
struct node head = {0, NULL};
struct node one = {1, NULL};
struct node two = {2, NULL};
struct node tail = {3, NULL};
int main(){
head.next = &one;
one.next = &two;
two.next = &tail;
...
My question is, why the 1st method is mostly the one used, why do we need to declare each node as pointer and why do we need malloc?
(Just to point out I know why struct Node *next; is declared as pointer int the struct declaration).
You should do this with local variables, not global ones, but the general idea would be the same. You should also steer towards having arrays and not heaps of otherwise unrelated variables:
struct node {
int id;
struct node* next;
};
int main(){
struct node nodes[4];
for (int i = 0; i < 4; ++i) {
nodes[i].id = (3 - i);
if (i != 0) {
nodes[i].next = &nodes[i-1];
}
}
return 0;
}
Where something like that assembles them in reverse order for convenience, but they're all grouped together in terms of memory initially.
malloc is used because you often don't know how many you're going to have, or they get added and removed unpredictably. A general-purpose solution would allocate them as necessary. A specialized implementation might allocate them as a single block, but that's highly situational.
Here the lifespan of nodes is within that function alone, so as soon as that function ends the data goes away. In other words:
struct node* allocateNodes() {
struct node nodes[10];
return &nodes; // Returns a pointer to an out-of-scope variable, undefined behaviour
}
That won't work. You need a longer lived allocation which is precisely what malloc provides:
struct node* allocateNodes() {
struct node *nodes = calloc(10, sizeof(struct node));
return nodes; // Returns a pointer to an allocated structure, which is fine
}
The problem is if you malloc you are responsible for calling free to release the memory, so it becomes more work.
You'll see both styles used in code depending on the required lifespan of the variables in question.
If you know ahead of time exactly how many items will be in your list, then you're probably better off using an array rather than a list. The whole point of a linked list is to be able to grow to an unknown size at runtime, and that requires dynamic memory allocation (i.e., malloc).
So, I wanted to create a stack as follows:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node{
int data;
struct node *link;
}node;
typedef struct Stack{
struct Node *topnode;
int count;
}stack;
void push(int data, stack *ourstack){
node newnode;
newnode.data = data;
ourstack.topnode = &newnode;
}
int main()
{
stack mystack;
push(1,mystack);
printf("%d",(mystack.(*topnode).data));
}
but I do get errors. I am a bit confused here. Inside the push() function, in the last line, I tried various ways of implementing it right but I failed each time. Now, my thinking is, ourstack is a pointer pointing to a struct Stack. And the topnode is also a pointer inside a structure of a stack which points to another node structure. So, should not (*ourstack).(*topnode) = newnode or ourstack.topnode = &newnode work? Why?
Neither work because newnode is on the stack and once the code exits push, it will no longer exist. You need to allocate it dynamically.
void push(int data, stack *ourstack){
node *newnode;
newnode = malloc(sizeof(*newnode));
newnode->next = ourstack->topnode; // Point the next of the new node to the top node of the stack
newnode->data = data;
ourstack->topnode = newnode;
}
And also you need to initialise mystack properly in main or else you risk undefined behaviour as topnode could be NULL or it could have a random value.
stack mystack;
mystack.topnode = NULL;
mystack.count = 0;
variable in a method, only exists in stack, will be unavailable after exit method. since you wish keep it after call of push, you need alloc a node with function like malloc, which will save data in heap. and you have to free it after you do not need it any more.
There are number of bugs in your program.
ourstack is pointer variable of structure type, while accessing data using ourstack use -> operator instead of dot operator
Replace
ourstack.topnode = &newnode;
with
ourstack->topnode = &newnode;
there is a conflict in push function definition and function call, you are passing just mystack and catching with struct pointer variable. pass the address of mystack, your function call should be
push(1,&mystack);
newnode is the local variable declared in push function and whatever you are trying with newnode it will reflects in this function only, not outside of this. So Allocate memory dynamically for newnode and do the operation.
void push(int data, stack *ourstack){
node *newnode;
newnode = malloc(sizeof(stack));
newnode->data = data;
ourstack->topnode = newnode;
}
Once compiled successfully debug the code using gdb and analyze.
I wanted to make an array of stacks in C, where I should be able to retain individual stacks and their respective information. I currently have the following implementation, which only works for one stack. How can I modify the functions push and pop to achieve multiple stacks each using the same function.
(I was easily able to do this in Java, as I could create a class, but I have no idea in C)
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *first = NULL;
void push(int x) {
struct node *newnode = malloc(sizeof(struct node));
newnode->data = x;
newnode->next = first;
first = newnode;
}
int pop() {
int temp = first->data;
first = first->next;
return temp;
}
You have a memory leak in your code in the pop() function. You should free the memory that you have malloc'd.
Taking advice from #Jongware's comments below your question.
Here's a new version of the push() and pop() functions.
#include <stdlib.h>
struct node {
int data;
struct node *prev;
};
void push(struct node **stack, int x) {
if (stack != NULL)
{
struct node *newnode = malloc(sizeof(struct node));
newnode->data = x;
newnode->prev = *stack;
*stack = newnode;
} else
{
// You didn't give me a valid pointer to a stack, so I'm ignoring you!
}
}
int pop(struct node **stack) {
int temp = 0; // This is the default value that is returned when there is an error.
struct node *oldnode;
if (stack != NULL)
{
if (*stack != NULL)
{
oldnode= *stack;
temp = oldnode->data;
(*stack) = oldnode->prev;
free(oldnode);
} else
{
// The stack is empty. I will just ignore you and return the default value for temp.
}
} else
{
// You didn't give me a valid pointer to a stack so I'm ignoring you and returning the default value of 0 for temp!
}
return temp;
}
And here's an example of how to use them:
#include <stdio.h>
int main()
{
struct node *stack1 = NULL, *stack2 = NULL;
int value;
// Push some values onto the stacks
printf("Pushing 7 and then 8 onto stack1\n");
push(&stack1, 7);
push(&stack1, 8);
printf("Pushing 3 onto stack2\n");
push(&stack2, 3);
// Pop and print both stacks
value = pop(&stack2);
printf("Popped %d from stack2\n", value);
value = pop(&stack1);
printf("Popped %d from stack1\n", value);
value = pop(&stack1);
printf("Popped %d from stack1\n", value);
return 0;
}
As for where you should be declaring your stack pointers that is really up to you and how you intend to use them.
Have a read about C variable scope for some options and how you might use them.
Also, I will have to include a warning with declaring these pointers inside functions. In whichever function you declare your pointer you must make sure that you pop everything off the stack before you exit the function, otherwise you will lose the pointer and leak all the allocated memory. If this is not what you want, or you want the pointer to outlive the function then you can declare the pointer globally or pass it around, making sure that everything is popped off the stack before your program exists or loses the pointer.
Another thing that you might want to consider is what happens when you use pop() on an empty stack? The implementation that I have given you simply returns 0 and ignores you. You might want to handle that a little better.
You can only have one stack because you defined it as a global variable:
struct node *first = NULL;
In Java you would have used a class. In C, you can likewise do "object based" programming by defining an abstract data type which holds your instance variables, instead of using global variables:
struct stack {
struct node *first;
};
there are no class features like constructors or destructors, so you write functions to initialize a stack, destroy a stack and so forth. To achieve multiple instantiation, you explicitly pass a stack * argument to each function in the stack module.
You might want to name your functions in some consistent way, like stack_init, stack_cleanup, stack_push and so on.
There are design questions to settle such as: does the caller allocate struct stack, for which you provide stack_init function? Or do you provide a one-step stack_alloc function that allocates and returns a stack? Or perhaps both, so the user can choose performance or convenience?
void stack_init(struct stack *);
void stack_cleanup(struct stack *);
struct stack *stack_alloc(void); /* also calls stack_init on new stack */
void stack_free(struct stack *); /* calls stack_cleanup, then frees */
It's possible to do information hiding in C, whereby you can completely conceal from the client code (which uses the stack module) what a struct stack is.
However, if you provide a stack_init, then the client has to know how large a stack is, since it provides the memory for it. Generally, modules which completely hide an implementation also hide how large it is, and so provide only a stack_alloc and stack_free type interface.
An advantage of that is that client code doesn't have to be recompiled if the stack module is changed and the structure is larger. This is very good if you're writing a widely-used library: it is easy for users to upgrade or possibly downgrade.
However, revealing the implementation allows for more efficient code, since the client has the freedom to choose memory management for stacks. Stacks can be declared as local variables in automatic storage ("on the stack", so to speak), statically as global variables, or packed into arrays.
The user can do things like:
{
struct stack temp_stack;
stack_init(&temp_stack); /* stack is good to go! */
/* ... use stack ... */
stack_cleanup(&temp_stack); /* don't forget to clean up */
}
and things like:
struct stack array_of_stacks[42];
int i;
for (i = 0; i < 42; i++)
stack_init(&array_of_stacks[i]); /* no memory allocation taking place */
All this code has a compile-time dependency of the definition of struct stack; whenever struct stack is touched, it must be recompiled.
Note that if the above struct stack definition is the exact definition for a stack (the only property of a stack is that it has a pointer to a top node which can be null) then, physically speaking, a struct stack * pointer is actually a pointer to a pointer. We can use a typedef name to write the code so that we can use either definition:
/* Alternative "A" */
typedef struct node *stack_t; /* a stack_t type is a pointer to a node */
/* Alternative "B" */
typedef struct stack {
struct node *top;
} stack_t; /* stack_t is a structure containing a pointer to a node */
Either way, the API in terms of stack_t then looks like this:
void stack_init(stack *s);
int stack_push(stack *s, int item);
or whatever. If stack is a pointer (alternative "A" above) then stack *s is a pointer-to-pointer, and so your code will be full of pointer-to-pointer manipulation.
If you're not comfortable with pointer-to-pointer syntax all over the place, then you can give yourself a macro to pretend that it's a structure anyway.
/* Alternative "A" */
typedef struct node *stack_t; /* a stack_t type is a pointer to a node */
#define stack_top(s) (*(s)) /* dereference stack s to obtain the top pointer */
/* Alternative "B" */
typedef struct stack {
struct node *top;
} stack_t; /* stack_t is a structure containing a pointer to a node */
#define stack_top(s) ((s)->top) /* dereference struct pointer to get top pointer */
In the code you can then do things like:
/* push new_node onto stack */
new_node->next = stack_top(s);
stack_top(s) = new_node;
If you consistently use the stack_top accessor, you can now flip the representation of the stack type between alternative "A" and "B" without rewriting any of your code (only recompiling it).
Some nit-picky C programmers will cringe at stack_top(s) = new_node since it looks like a function call is being assigned (which is impossible in C without using macros to bend the language), and prefer a "setter" function for that stack_top_set(s, new_node). That's mostly just outdated, parochial thinking.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int Item;
#define ItemFormat "%d"
struct node {
Item data;
struct node *next;
};
typedef struct node *Stack;
void push(Stack *st, Item x){
struct node *newnode = malloc(sizeof(struct node));
newnode->data = x;
newnode->next = *st;
*st = newnode;
}
bool isEmpty(Stack st){
return st == NULL;
}
Item pop(Stack *st) {
if(!isEmpty(*st)){
struct node *p = *st;
Item value = p->data;
*st = p->next;
free(p);
return value;
}
fprintf(stderr, "Stack is Empty!\n");
return (Item)0;
}
bool inputItem(Item *x){
int stat;
if(1==(stat=scanf(ItemFormat, x)))
return true;
if(stat == EOF)
return false;
scanf("%*[^\n]");
return false;
}
void printItem(Item x){
printf(ItemFormat, x);
}
int main(void){
Stack st = NULL, array[5] = { NULL };
Item x;
while(inputItem(&x)){
push(&array[1], x);
}
while(!isEmpty(array[1])){
x = pop(&array[1]);
printItem(x);
printf("\n");
}
/*
while(inputItem(&x)){
push(&st, x);
}
while(!isEmpty(st)){
x = pop(&st);
printItem(x);
printf("\n");
}
*/
return 0;
}
The static implemetation of two stacks in a single array in C looks something like this...the stack structure will have two top variables top1 and top2.
struct stack
{
int data[MAX];
int top1,top2;
}s;
top1 is initialized to -1 while top2 is initialized to MAX
Overflow condtitions:
1]
if((s->top1)+1==s->top2)
printf("Stack 1 overflow\n");
2]
if((s->top2)-1==s->top1)
printf("Stack 2 overflow\n");
The underflow conditions become pretty obvious. This method may not be memory efficient since we might run out of storage space in the array but it is the basic fundamentals of multiple stacks in a single array.
Excuse the beginner level of this question. I have the following simple code, but it does not seem to run. It gets a segmentation fault. If I replace the pointer with a simple call to the actual variable, it runs fine... I'm not sure why.
struct node
{
int x;
struct node *left;
struct node *right;
};
int main()
{
struct node *root;
root->x = 42;
printf("Hello world. %d", root->x);
getchar();
return 0;
}
What is wrong with this code?
struct node *root;
root->x = 42;
You're dereferencing an uninitialized pointer. To allocate storage for the node:
struct node *root = malloc(sizeof(struct node));
You could also allocate a node on the stack:
struct node root;
root.x = 42;
In order to use a pointer to access something, the pointer must be pointing at that something. In order for the pointer to be pointing at that something, that something must exist. Creating a pointer does not create anything for it to point at. You must do so explicitly, either by dynamic allocation (malloc()), stack allocation (i.e. a local variable) or by pointing to something that already exists (e.g. a static instance, such as a global; a value that was passed in as a parameter; etc.).
After struct node *root; line add the
root = (sturct node*) malloc(sizeof(struct node));
Also, before Return 0 line add the
free(root);