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.
Related
I am following an online tutorial which presents me with the following (simplified) code:
typedef struct {
int data;
Node* next;
} Node;
int main(){
Node *head;
init(&head);
return 0;
}
What is the purpose & functionality of the init function? I did not define it myself, however am struggling to find documentation online as well.
For starters this declaration
typedef struct {
int data;
Node* next;
} Node;
is incorrect. The name Node used in this data member declaration
Node* next;
is undefined.
You need to write
typedef struct Node {
int data;
struct Node* next;
} Node;
As for your question then in this declaration
Node *head;
the pointer head has an indeterminate value because it is not initialized.
So it seems the function init just initializes the pointer. You need to pass the pointer by reference through a pointer to it. Otherwise the function will deal with a copy of the pointer head. Dereferencing the pointer to pointer you will get a direct access to the original pointer head that can be changed within the function. That is the function can look the following way
void init( Node **head )
{
*head = NULL;
}
Pay attention to that you could just write in main
Node *head = NULL;
without a need to call the function init.
I think that the init function is gonna be implemented in the next videos. I suppose that your teacher wants to use an init function to set some values if you create a new Node (or a struct in this case) to prevent some easter eggs undefined behaviour.
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
I am implementing a queue using a generic linked list in C where each node in list is a simple struct which contains a void pointer and a node pointer to the next node. In the dequeue operation I want to remove the head (which is working fine), but I also want to return that node after it is removed.
EDITED TO CLARIFY
What i did in the dequeue function is (example):
//This is my queue struct
typedef struct Queue{
LinkedList* list;
size_t item_size;
} Queue;
//this is the dequeue function
Node* dequeue(Queue* queue){
Node* head = queue->list->head;
Node* returnedValue = (Node*)malloc(sizeof(Node));
memcpy(returnedValue, head, sizeof(Node));
removeBegin(queue->list);
return returnedValue;
}
//this is the remove head function
void removeBegin(LinkedList* list){
Node* tempHead = list->head;
list->head = list->head->next;
tempHead->next = NULL;
free(tempHead->value);
tempHead->value = NULL;
free(tempHead);
tempHead = NULL;
}
the problem is everything before the free function is ok. Everything is being copied correctly. But immediately after the free function call the value that is copied to the newly allocated node becomes garbage (or 0).
The way I call the function is simply initialize the queue using this function:
Queue* init_queue(size_t size){
Queue* queue = (Queue*)malloc(sizeof(Queue));
// int x = 10;
queue->list = createList(NULL, size);
return queue;
}
then call dequeue and pass it the pointer of the queue.
How can I solve this?
thanks a lot.
The memory allocating using
Node* n1 = (Node*)malloc(sizeof(Node));
is uninitialised. This means that accessing the value of n1->value gives undefined behaviour. A consequence is that
memcpy(n1->value, n->value, sizeof(n->value));
also gives undefined behaviour.
When behaviour is undefined, the consequences of executing any further code could be anything. Your observation
newly allocated node becomes garbage (or 0)
is one possible outcome.
There are more problems as well. However, you haven't provided enough information (e.g. how is the function called? how is the pointer passed as n initialised? how is n->value initialised?) so it is not possible to give advice on how to FIX your function.
I've been reviewing the basics of singly linked list In C with materials from Stanford CS Library, where I came cross the following code:
struct node{
int data;
struct node* next;
};
struct node* BuildWithDummyNode(){
struct node dummy;
struct node* tail = & dummy; // this line got me confused
int i;
dummy.next = NULL;
for (i=1;i<6;i++){
Push(&(tail->next), i);
tail = tail->next;
}
return dummy.next;
}
Probably not revenant, but the code for Push() is:
void Push(struct node** headRef, int data){
struct node* NewNode = malloc(sizeof(struct node));
newNode->data = data;
newNode->next = *headRef;
*headRef = newNode;
}
Everything runs smoothly, but I've always been under the impression that whenever you define a pointer, it must point to an already defined variable. But here the variable "dummy" is only declared and not initialized. Shouldn't that generate some kind of warning at least?
I know some variables are initialized to 0 by default, and after printing dummy.data it indeed prints 0. So is this an instance of "doable but bad practice", or am I missing something entirely?
Thank you very much!
Variable dummy has already been declared in the following statement:
struct node dummy;
which means that memory has been allocated to it. In other words, this means that it now has an address associated with it. Hence the pointer tail declared in following line:
struct node* tail = & dummy;
to store its address makes perfect sense.
"But here the variable "dummy" is only declared and not initialized."
The variable declaration introduces it into the scope. You are correct in deducing it's value is unspecified, but to take and use its address is well defined from the moment it comes into scope, right up until it goes out of scope.
To put more simply: your program is correct because you don't depend on the variables uninitialized value, but rather on its well defined address.
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);