I have an array of struts called arrayOfElements , each element being a struct called Element
typedef struct {
void* data;
} Element;
data is a void pointer as I dont know in advanced what type of variable will be stored
I've malloc'd this array to have 4 elements ( this is done by user input but ive hard coded 4 for this question)
Element* arrayOfElements;
arrayOfElements= malloc(4 * sizeof(Element));
Now to this point I can store strings and ints in arrayOfElements
Store Int
arrayOfElements[0].data = malloc( sizeof(int) );
int *ptr = arrayOfElements[0].data;
*ptr = 65;
Store String
arrayOfElements[0].data = malloc( strlen(str) + 1 );
strcpy( arrayOfElements[0].data, str );
And that all works. My Issue is how do I got about making a linked List and making each element store an instance of arrayOfElements
so far my linked list is
typedef struct LinkedListNode {
void** ElementArray;
struct LinkedListNode* next;
} LinkedListNode;
typedef struct {
LinkedListNode* head;
} LinkedList;
so the void** ElementArray will point to each arrayOfElements
void insert(LinkedList* head, Element inArrayOfElements)
{
LinkedListNode insertNode;
/* Points ElementArray to inArrayOfElements */
HOW DO I DO THIS AS ElementArray is a void**
/* Points next to the head */
(*insertNode).next = head;
/* Re-points head to new head of Linked List */
head = insertNode;
}
My Goal is to have something like this
LINKEDLIST
+---+ +---+---+----+
| | -> | | | | arrayofElements
+---+ +---+---+----+ +---+---+----+
| | -------------------> | | | |
+---+ +---+---+----+ +---+---+----+
| | -> | | | |
+---+ +---+---+----+ +---+---+----+
| | -------------------> | | | |
+---+ +---+---+----+
Question / TL;DR
My question is how do I make void** ElementArray (in the linked list) point to arrayOfElements.
If I understand your question correct, there is no need for double pointers. Just do:
typedef struct LinkedListNode {
Element* data;
struct LinkedListNode* next;
} LinkedListNode;
LinkedListNode* insert(LinkedListNode* head, Element* inArrayOfElements)
{
LinkedListNode* insertNode = malloc(sizeof(LinkedListNode));
insertNode->next = head;
insertNode->data = inArrayOfElements;
return insertNode;
}
Use it like:
head = insert(head, someArrayOfElements);
Note: The real code should check for NULL pointers but I omitted that for simplicity.
Related
I'm trying to implement a linked list and adding nodes to it. I encountered the following problem, when I try to free the pointer n after setting list->next to point to the same address of n, the int value inside the second node also changes to garbage value when I print it again. I want to know if inside the memory, n and list->next is stored as two separate pointers that hold the same value or it is stored as a single pointer? And if they were distinct, then why freeing n also affect list->next? Furthermore if freeing n make the second node became lost, then why I can still use the list->next->next pointer to add a third node, was list->next->next pointer also some random value that points to a random usable location ? Here is my code, sorry if my question is too vague, I'm trying my best to understand all this pointers.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
typedef struct node {
int number;
struct node *next;
} node;
int main(void) {
node a;
a.number = 1;
a.next = NULL;
node *list = NULL;
list = &a; // the first node
printf("%i \n", a.number);
node *n = malloc(sizeof(node)); // creating pointer to the second node
if (n != NULL) {
n->number = 2;
n->next = NULL;
}
list->next = n; // add the node to the list
printf("%p \n%p \n", n, list->next); // print out the address and value
printf("%i \n", list->next->number);
free(n);
printf("%p \n%p \n", n, list->next); // print out the address and value
printf("%i \n", list->next->number);
n = malloc(sizeof(node));
printf("%p \n%p \n", n, list->next);
if (n != NULL) {
n->number = 3;
n->next = NULL;
}
list->next->next = n;
printf("%i\n", (*(*(*list).next).next).number);
return 0;
}
Here is the output
1
0x5562319d62a0
0x5562319d62a0
2
0x5562319d62a0
0x5562319d62a0
1445140950
0x5562319d62a0
0x5562319d62a0
3
The assignment
list->next = n
doesn't copy the allocated memory. It just add another pointer pointing to the same memory.
If we "draw" it, before the assignment it looks something like this:
+---+ +-----------------+
| n | ---> | memory for node |
+---+ +-----------------+
Then after the assignment you have:
+---+
| n | -----------\
+---+ | +-----------------+
>--> | memory for node |
+------------+ | +-----------------+
| list->next | --/
+------------+
Then you pass n to free leading to this situation:
+---+
| n | -----------\
+---+ |
>--> ???
+------------+ |
| list->next | --/
+------------+
After the call to free, the pointer list->next is invalid. Any attempt to dereference it will lead to undefined behavior.
First, sorry if my question has already been answered. I found some threads that are (in a way) similiar but I was not able to solve my problem.
Second, I am new to single-linked-list in C so I would be happy if you could answer my question as easy as possible.
I made a simple linke-list, that has characters in it:
#include <stdio.h>
#include <stdlib.h>
// declaration of node
struct _Node_
{
char data_string;
struct _Node_ *next;
};
int main() {
//a simple linked list with 3 Nodes, Create Nodes
struct _Node_* head = NULL;
struct _Node_* second = NULL;
struct _Node_* third = NULL;
//allocate 3 Nodes in the heap
head = (struct _Node_*)malloc(sizeof(struct _Node_));
second = (struct _Node_*)malloc(sizeof(struct _Node_));
third = (struct _Node_*)malloc(sizeof(struct _Node_));
// assign data for head
head->data_string = 'H'; //assign value according struct
head->next = second; //points to the next node
// assign data for second
second->data_string = 'E';
second->next = third;
third->data_string = 'Y';
third->next = NULL;
return 0;
}
The linked list does now look like this:
/* Linked list _Node_
head second third
| | |
| | |
+---+---+ +---+---+ +----+------+
| 1 | o-----> | 2| o-------> | 3 | NULL |
+---+---+ +---+---+ +----+------+
*/
Let's assume I have 3 arrays with the following:
char name1[] = "Joe";
char name2[] = "Eve";
char name3[] = "Brad";
And my goal is to copy this array into each data field, so the result looks like this:
/* Linked list _Node_
head second third
| | |
| | |
+-----+---+ +-------+---+ +-------+------+
| Joe | o-----> | Eve | o-----> | Brad | NULL |
+-----+---+ +-------+---+ +-------+------+
*/
How can I achieve this? I already tried adding/changing the following:
...
struct _Node_
{
char data_string[8];
struct _Node_ *next;
};
...
...
char name1[] = "Joe";
char name2[] = "Eve";
char name3[] = "Brad";
// assign data for head
head->data_string = name1; //assign value according struct
head->next = second; //points to the next node
// assign data for second
second->data_string = name2;
second->next = third;
third->data_string = name3;
third->next = NULL;
...
But all I get after compiling is:
stack_overflow.c:27:23: error: array type 'char [8]' is not assignable
head->data_string = name1; //assign value according struct
~~~~~~~~~~~~~~~~~ ^
stack_overflow.c:31:25: error: array type 'char [8]' is not assignable
second->data_string = name2;
~~~~~~~~~~~~~~~~~~~ ^
stack_overflow.c:34:24: error: array type 'char [8]' is not assignable
third->data_string = name3;
~~~~~~~~~~~~~~~~~~ ^
3 errors generated.
Maybe someone could help, I appreciate any help.
Again, sorry if this is a duplicate but I am not able to solve this with other threads..
You asked for a code example:
struct Node
{
char *data_string;
struct Node *next;
};
struct Node *newNode (char *s)
{
struct Node *node;
if (!s) return 0; // error: no string
if (!(node= malloc(sizeof(struct Node)))) return 0; // no more memory
node->data_string= malloc(strlen(s)+1);
if (!node->data_string) {
free(node);
return 0;
}
strcpy(node->data_string,s);
node->next= 0;
return(node);
}
void freeNode(struct Node *node)
{
if (!node) return;
if (node->data_string) free(node->data_string);
free(node);
}
Notes:
you alocate the memory for the string 1 more than the length because a string in C has a null terminating character.
do not use underscores before an identifier name - those are reserved for the compiler.
do not cast the result of malloc. It returns a void pointer, which is compatible with any pointer type.
this example includes all required error checking.
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 4 years ago.
Improve this question
what i need to do is to implement a function in c for deleting a node in a linked list, using a for and while loop with strcmp. The program compiles fine but the loop never stop, any suggestion on how to make it better?
The structure is this:
struct Test
{
char name[16];
int id;
};
typedef struct Node
{
struct Test structure;
struct Node * next;
}TNode;
typedef TNode * Nodo;
And the function i wrote is this:
void Delete(Nodo * pp)
{
Nodo i;
char temp[16], name[16];
printf("Insert the name to delete:");
scanf(" %s", name);
for(i = *pp; i->next != NULL ; i = i->next)
{
if(strcmp(i->structure.name, name) == 0)
{
while(i->next != NULL)
{
strcpy(temp,i->structure.name);
strcpy(i->structure.name, i->next->structure.name);
strcpy(i->next->structure.name, temp);
i = i->next;
}
}
}
}
UPDATE: The working function is this, thanks to Some programmer dude for the explanation:
void Delete(Nodo * pp)
{
Nodo i, prev;
char name[16];
printf("Insert the name to delete:");
scanf(" %s", name);
//case for the first node
if(strcmp((*pp)->structure.name, name) == 0)
{
Nodo old = *pp;
*pp = (*pp)->next;
free(old);
return;
}
//loop to delete node inside list
for(prev = *pp, i = prev->next; i != NULL ; prev = i, i = i->next)
{
if(strcmp(i->structure.name, name) == 0)
{
prev->next = i->next;
free(i);
break;
}
}
}
[Note: This doesn't actually answer the question, but it tells how to unlink nodes in a single-linked list, which IMO is the bigger problem the OP have.]
Lets say you have the following list
+---+ +---+ +---+ +---+
| A | -> | B | -> | c | -> | D |
+---+ +---+ +---+ +---+
If you want to remove node B then you don't copy the contents of the remaining list. Because that would give you the follow list:
+---+ +---+ +---+ +---+
| A | -> | C | -> | D | -> | D |
+---+ +---+ +---+ +---+
And that's not correct.
Instead you make the A node's next pointer point to C instead, so now the list becomes
+---+ +---+ +---+ +---+
| A | -\ | B | /-> | c | -> | D |
+---+ | +---+ | +---+ +---+
\-------/
Then you just free the node B, and you end up with
+---+ +---+ +---+
| A | -> | c | -> | D |
+---+ +---+ +---+
The trick to unlinking the node is to keep track of the previous node. It could be implemented something like this:
// Special case: Removing the first node in the list
if (strcmp((*pp)->structure.name, name) == 0)
{
TNode *old = *pp; // Save a pointer to the node that should be removed
*pp = (*pp)->next; // Actually unlink the node from the list
free(old); // Free the memory of the old node
return;
}
TNode *prev; // To keep track of previous node
TNode *curr; // The "current" node
for (prev = *pp, curr = prev->next; curr != NULL; prev = curr, curr = curr->next)
{
if (strcmp(curr->structure.name, name) == 0)
{
// Found the node to remove
prev->next = curr->next; // Unlink the current node from the list
free(curr); // Free the node
break; // No need to iterate anymore
}
}
The "special case" of the first node being removed could also be solved inside the loop, by initializing prev to NULL, and start curr with *pp instead. Then you need to check if prev is NULL or not inside the if in the loop.
The code might look like more, and it might be more lines (even after removing some or all of the empty lines), but I think most people would say it's easier to follow and see what's going on.
Of course, you also need to add a check for an empty list and that pp itself is not null (like pp != NULL && *pp != NULL).
I am trying to swap two nodes. For example if the nodes are a and b I am passing the pointers
(a-1)->next and (b-1)->next which are basically nodes a and b.
void swap(struct stack **a,struct stack **b)
{
struct stack *temp1 = *a, *temp2 = *b, *temp3 = *b;
*a = *b;
(*b)->next = (temp1)->next;
temp2 = temp1;
(temp2)->next = temp3->next;
}
What am I doing wrong? When I am trying to print the nodes after calling the function it's an infinite loop. Please help.
Why Infinite loop?
Infinite loop is because of self loop in your list after calling swap() function. In swap() code following statement is buggy.
(*b)->next = (temp1)->next;
Why?: Because after the assignment statement in swap() function temp1's next starts pointing to b node. And node[b]'s next point to itself in a loop. And the self loop is reason for infinite loop, somewhere in your code where you traverse linked list.
Below I drawn to show how swap() works step-by-step. May be this help you to understand your error:
You didn't mention but I am assuming linked list having following relation between a and b: (read red comments)
(step-1):
+----+----+----+ +---+----+----+
| one |----->| two |
+----+----+----+ +---+---+-----+
^ ^ ^ ^
| | | |
| *a | *b
| |
temp1 temp2, temp3 "after assignment to temp variables"
(step-2): ^
|
*a = *b | *a "<--- next step"
(step-3): The buggy statement
(*b)->next = (temp1)->next; "Change link: (temp1)->next; is `two` node"
" *b is `two`, So Self loop"
+----+----+----+ +---+----+----+ <---|
| one | | two |-----|
+----+----+----+ +---+---+-----+
^ ^ ^ ^
| | | |
| | *b *a
| |
temp1 temp2, temp3 " after assignment to temp"
See (temp1)->next; is actually b and you are assigning (*b)->next = (*b) by doing (*b)->next = (temp1)->next; hence adding a self loop.
(step-4):
I think with the diagram you can easily understand what last two lines of your swap() code are doing:
temp2 = temp1;
(temp2)->next = temp3->next;
Following is my diagram for this two lines:
temp2 = temp1;
+----+----+----+ +---+----+----+ <---|
| one | | two |-----| "<--- Self loop"
+----+----+----+ +---+---+-----+
^ ^ ^ ^
| | | |
| | *b *a
| |
temp2 = temp1; temp3
(step-5): Even last line of your function swap() left loop as below:
(temp2)->next = temp3->next; " last line of your code"
+----+----+----+ +---+----+----+ <---|
| one |----->| two |-----| "<-- Self loop"
+----+----+----+ +---+---+-----+
^ ^ ^ ^
| | | |
| | *b *a
| |
temp2 = temp1; temp3
So loop still there at two node so infinite loop.
How to swap two nodes in single linked list?
One way is swap node's data instead of swapping node's position it self in linked list (as I commented to your question). But you wants to swap node's position in list.
Well this good! if node data size is larger, that time its better to swap node's position rather then swap node's data(swapping data will be bad choice)
Because you having single linked list, to swap any two arbitrary nodes in list you need there previous node addresses too. (this is the point you don't consider in your swapping logic)
WHY need previous pointers?:
Suppose after some successful insert(push) operations, your list becomes as follows:
0 <--------TOP - "head"
9 <--p
2
6 <--q
5
A horizontal diagram- Suppose you want to swap say two nodes (q) and (p):
+---+ +---+ +---+ +---+ +---+
| 0 |--->| 9 |--->| 2 |--->| 6 |--->| 5 |---
+---+ +---+ +---+ +---+ +---+ |
^ ^ ^ null
| | |
| (q) (p)
(head)
As I said, to swap we need previous pointers. You need to think about following
(In theory, I am writing for specific nodes (p) and (q) just to keep explanation simple. but my implementation is quit general):
In list previous pointers:
node[0] points to node[9] that is (q), and
node[2] points to node[6] that is (p)
And
node[9] points to node[2]
node[6] points to node[5]
NOTICE: If you want to swap two nodes say node[ 9 ] and node[ 6 ] then you should use pointers of the nodes previous to these two nodes.
For example: two swap node[ 9 ] and [ 6 ], you also need to change next pointer of node[ 0 ] and next pointer of node[ 2 ] in above diagram.
How would be the list after swapping this two nodes?
+---+ +---+ +---+ +---+ +---+
| 0 |--->| 6 |--->| 2 |--->| 9 |--->| 5 |---
+---+ +---+ +---+ +---+ +---+ |
^ ^ ^ null
| | |
| (p) (q)
(head)
What is now in previous nodes [o] and [2]?
After swapping, In list previous pointers
node[0] points to node[6] that is (q), and
node[2] points to node[9] that is (p)
And
node[9] points to node[5]
node[6] points to node[2]
So if you want to swap two nodes; there immediate previous node also effects and because list is single link list you need previous pointers too.
How to find previous node pointers?
Suppose you want to swap any two nodes node[p] and node[q] then you can use head pointer to find previous node.
So swap function syntax (In my implementation) is like:
void swap(struct stack **head, // head node
struct stack **a, // first candidate node to swap
struct stack **b); // first candidate node to swap
And you will call function like:
swap(&head, &p, &q);
Definition: (To understand code please read comments I added at almost each line)
void swap(struct stack **head,
struct stack **a,
struct stack **b){
// first check if a agrgument is null
if( (*head) == NULL || // Empty list
(*a) == NULL || (*b) == NULL){ // one node is null
// Nothing to swap, just return
printf("\n Nothing to swap, just return \n");
return;
}
// find previos nodes
struct stack* pre_a = get_prevnd(*head, *a);
struct stack* pre_b = get_prevnd(*head, *b);
//Now swap previous node's next
if(pre_a) pre_a->next = (*b); // a's previous become b's previous, and
if(pre_b) pre_b->next = (*a); // b's previous become a's previous
//Now swap next fiels of candidate nodes
struct stack* temp = NULL;
temp = (*a)->next;
(*a)->next = (*b)->next;
(*b)->next = temp;
//change head: if any node was a head
if((*head)==(*a))
*head = *b;
else
if((*head)==(*b))
*head = *a;
}
In swap() function you can notice that I call a helper function get_prevnd(, );. This function returns address of previous node in list. In The function get_prevnd(, );, first argument is list head and second argument is node for which you are looking for.
// find previous node function()
struct stack* get_prevnd(
struct stack* head,
struct stack* a
){
if(head == a){
// node[a] is first node
return NULL;
}
struct stack* temp = head; // temp is current node
struct stack* pre_a = NULL;
while(temp && temp!=a){ //search while not reach to end or the node
pre_a = temp; // find previous node
temp = temp->next;
}
if(temp!=a){// node[a] not present in list
fprintf(stderr, "\n error: node not found!\n");
exit(EXIT_FAILURE); // bad technique to exit()
}
return pre_a;
}
And fortunately the code is WORKING :). Below is link for online test of this code. I have tested for various kind of inputs.
CodePad: To Swap node in single linked list. Please check output.
And sorry for bad English
I was hoping for cut-and-paste code, but didn't find it. If anyone is still interested, this is the answer. I did the brute force analysis of all 3 cases.
// swaps nodes at locations *sp and *tp
struct stack *s = *sp; // store locations to prevent overwritten bugs
struct stack *t = *tp;
if(&t->next == sp) { // order u (tp)-> t (sp)-> s -> ...
t->next = s->next;
s->next = t;
*tp = s;
} else if(&s->next == tp) { // order u (sp)-> s (tp)-> t -> ...
s->next = t->next;
t->next = s;
*sp = t;
} else { // disconnected u (sp)->s -> ..., v (tp)->t -> ...
struct stack *next = s->next;
s->next = t->next;
t->next = next;
*sp = t;
*tp = s;
}
// If you track the end of your list, it be the one pointing to NULL.
if(s->next == NULL) {
end = &s->next;
} else if(t->next == NULL) {
end = &t->next;
}
Note: This code works if sp == tp, but assumes you don't have the pathological case where BOTH &s->next == tp && &t->next == sp (starting with cycle).
"KING KHAN"
SwapanyTwoNodeData(int, int); this function take two integer as parameter and swap these
node data.
1->2->6->3->4->5
SwapanyTwoNodeData (2,4);
1->3->6->2->4->5
100% Working Function. . . . Enjoy.
void Swap_Any_Two_Locations_data(int x,int x1){
if(head!=NULL){
int count=1,count1=1;
Node *temp,*temp1;
temp=head;
temp1=head;
while(temp->next!=NULL && count!=x ){
temp=temp->next;
count++;
}
while(temp1->next!=NULL && count1!=x1){
temp1=temp1->next;
count1++;
}
if(count==x && count1==x1){
int z=0;
z=temp->info;
temp->info=temp1->info;
temp1->info=z;
cout<<"Data Swapped"<<endl;
}
}
}
Past few days I'm working on my c\c++ skills. I was going through my Data structure book and then I thought why not implement doubly linked list program. I wrote the program; surprisingly it work fine too, but , I'm not sure whether I've written it correctly. I'm not able to figure it out how to free the memory I've allocated. Please help me with this guys.
Also if any of you can explain me this "while(linkNode!=0)", i'll be really thankfull.
#include<stdio.h>
#include<malloc.h>
struct node
{
int x;
struct node * next;
struct node * prev;
};
struct head
{
unsigned int count;
struct node * hd;
struct node * tl;
};
void main()
{
int i =0;
struct node * linkNode;
struct head *hdd;
hdd = (head *)malloc(sizeof(head));
linkNode = (node *) malloc(sizeof(node));
hdd->count = 1;
hdd->hd = linkNode;
linkNode->prev = 0;
linkNode->next = 0;
linkNode->x = 0;
for(;i<10;i++)
{
linkNode->next = (node *) malloc(sizeof(node));
linkNode->next->prev = linkNode;
linkNode = linkNode->next;
linkNode->next = 0;
linkNode->x = i;
hdd->count+=1;
hdd->tl = linkNode;
}
linkNode = hdd->hd;
printf("priniting in next direction\n");
while(linkNode!=0)
{
printf("%d\n",linkNode->x);
linkNode = linkNode->next;
}
linkNode = hdd->tl;
printf("priniting in prev direction\n");
while(linkNode!=0)
{
printf("%d\n",linkNode->x);
linkNode = linkNode->prev;
}
linkNode = hdd->hd;
while(linkNode!=0)
{
free(linkNode->prev);
linkNode = linkNode->next;
}
free(hdd);
}
Your linked list looks something like this:
+------+----+----+
| Head | hd | tl | ---------->--------
+------+----+----+ \
| ---->------ | NULL
| / \ | |
+------+-----+------+------+ +------+-----+------+------+
| Node | x=0 | next | prev | | Node | x=1 | next | prev |
+------+-----+------+------+ +------+-----+------+------+
| | |
\ NULL /
-----------------------<----------------------
(I've simplified it to two nodes).
Now, we can just write out what this code does:
linkNode = hdd->hd;
while(linkNode!=0) {
free(linkNode->prev);
linkNode = linkNode->next;
}
linkNode = hdd->hd leaves linkNode pointed at the first node
(linkNode!=0) is true (the first node is not NULL), so we enter the while loop
free(linkNode->prev) calls free(NULL) since hdd->hd->prev == NULL (you set the first node up like this explicitly). This is fine, but does nothing.
linkNode = linkNode->next leaves linkNode pointed at the last node
linkNode!=0 is still true (the last node is also not NULL), so we go round the loop again
free(linkNode->prev) frees the previous node (which is the first one)
linkNode = linkNode->next leaves linkNode == NULL
linkNode!=0 is false now, so the loop terminates.
So, we free'd all but the last node. No node's prev member points to that node, so calling free(linkNode->prev) can never free it. You could, however, free it via hdd->tl.
You are already freeing the memory allocated to your nodes of your linked list in the reverse order from the tail of the list. This line is doing this.
free(linkNode->prev);
There is a memory leak in your program . Your last node in the list is not freed.
Just include
free(linkNode);
before freeing hdd .
Explanation for:
while(linkNode!=0)
This is to make sure that you are dereferencing a NULL pointer. Since dereferncing a NULL pointer could cause undefined behaviours.
These are the dereference operations
linkNode->x
linkNode->prev