#include<stdio.h>
typedef struct Node
{
int data;
struct Node *next;
struct Node *prev;
} node;
void insert(node *pointer, int data)
{
while(pointer->next!=NULL)
{
pointer = pointer -> next;
}
pointer->next = (node *)malloc(sizeof(node));
(pointer->next)->prev = pointer;
pointer = pointer->next;
pointer->data = data;
pointer->next = NULL;
}
int main()
{
node *start;
start = (node *)malloc(sizeof(node));
int data;
scanf("%d",&data);
insert(start,data);
}
Well, I'm trying to understand the basics of lists in C. I have one question here - the 3rd line from the insert()'s bottom - what is this for? It seems like if the first list's element remains empty and the data is being saved into the second one. But only this works.
In main() there's being created first empty element, right?
while() is not executed as the element is null.
Then the second element is being created. (pointer->null)
Pointer pointing to the first element is set to point to the second element (that 3rd line from the bottom)
And the data is being saved to that second element.
Where do I make a mistake?
pointer = pointer->next;
This line changes the current node we're concentrating on from the last node of the original list to the newly allocated last node of the new list (i.e. the node after the last node of the original list). We then set that node's values directly in the next two lines.
You could get rid of this line and change the two lines below it to read
pointer->next->data = data;
pointer->next->next = NULL;
and you would have the same result.
Edit: Looking further into things, I see more issues:
1) You need #include <stdlib.h> to use malloc().
2) You need to explicitly set start->next = NULL; before you call insert().
In your insert function, you have this assignment:
pointer = pointer->next;
This will not work, as the pointer pointer is passed by value. This means that all changes to the value will be lost when the function returns.
You can pass the pointer by reference:
void insert(node **pointer, int data)
{
/* ... */
*pointer = (*pointer)->next;
/* ... */
}
Or return the pointer from the function:
node *insert(node *pointer, int data)
{
/* ... */
return pointer;
}
There is also the problem that you don't initialize the pointers in the node structure. This means that when you allocate a node structure, the fields in it will be pointing to seemingly random locations.
This is solved simply by setting the next and prev pointer to NULL directly after allocation:
start = malloc(sizeof(node));
start->next = NULL;
start->prev = NULL;
Related
I'm still learning how to program in C and I've stumbled across a problem.
Using a char array, I need to create a linked list, but I don't know how to do it. I've searched online, but it seems very confusing. The char array is something like this char arr[3][2]={"1A","2B","3C"};
Have a look at this code below. It uses a Node struct and you can see how we iterate through the list, creating nodes, allocating memory, and adding them to the linked list. It is based of this GeeksForGeeks article, with a few modifications. I reccommend you compare the two to help understand what is going on.
#include <stdio.h>
#include <stdlib.h>
struct Node {
char value[2];
struct Node * next;
};
int main() {
char arr[3][2] = {"1A","2B","3C"};
struct Node * linked_list = NULL;
// Iterate over array
// We calculate the size of the array by using sizeof the whole array and dividing it by the sizeof the first element of the array
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
// We create a new node
struct Node * new_node = (struct Node *)malloc(sizeof(struct Node));
// Assign the value, you can't assign arrays so we do each char individually or use strcpy
new_node->value[0] = arr[i][0];
new_node->value[1] = arr[i][1];
// Set next node to NULL
new_node->next = NULL;
if (linked_list == NULL) {
// If the linked_list is empty, this is the first node, add it to the front
linked_list = new_node;
continue;
}
// Find the last node (where next is NULL) and set the next value to the newly created node
struct Node * last = linked_list;
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
}
// Iterate through our linked list printing each value
struct Node * pointer = linked_list;
while (pointer != NULL) {
printf("%s\n", pointer->value);
pointer = pointer->next;
}
return 0;
}
There are a few things the above code is missing, like checking if each malloc is successful, and freeing the allocated memory afterwards. This is only meant to give you something to build off of!
This will most likely seem like I am missing something obvious but when I try to pass a Linked List pointer to my Selection sort I get a NULL pointer problem. In my C code I have this as my linked list:
typedef struct iorb
{
int base_pri;
struct iorb *link;
char filler[100];
} IORB;
Then I pass my new linked list into this function after creating it:
void swapNodes(POINTER *head, POINTER CurrentHead, POINTER CurrentMinimum, POINTER TempSwap);
POINTER SortList(POINTER *head, char *SortMethod[])
{
POINTER TempHead = *head;
//Only one node, no need to sort.
if (TempHead->link == NULL)
{
return head;
}
//Store node with the new minimum value.
POINTER TempMin = *head;
//Store curent node for swapping
POINTER TempSwap = *head;
//Transverse the list.
POINTER TempCurrent;
for (TempCurrent = *head; TempCurrent->link != NULL; TempCurrent = TempCurrent->link)
{
//Check if this node has a lower priority than the current minimum and if so, swap them.
if (TempCurrent->link->base_pri < TempMin->base_pri)
{
TempMin = TempCurrent->link;
TempSwap = TempCurrent;
}
}
//Swap nodes if the head is not the same as the minimum.
if (TempMin != TempHead)
{
swapNodes(&TempHead, TempHead, TempMin, TempSwap);
}
//Recursively sort the rest of the list.
//FOR SOME REASON THE NODE POINTER IS NOT BEING PASSED HERE (EMPTY)
TempHead->link = SortList(TempHead->link, *SortMethod);
return head;
}
void swapNodes(POINTER *head, POINTER CurrentHead, POINTER CurrentMinimum, POINTER TempSwap)
{
//Set new head as the minimum.
*head = CurrentMinimum;
//Link the current temp swap to the head.
TempSwap->link = CurrentHead;
//Swap pointers.
POINTER temp = CurrentMinimum->link;
CurrentMinimum->link = CurrentHead->link;
CurrentHead->link = temp;
}
I am not sure why it is isn't being passed back into the same function, when I debug the linked list seems okay. I suspect that I am missing something in the swap node function, but I don't quite understand what this is. Can someone please offer some insight as to how this code should go for swapping the nodes around?
If you need additional information please let me know.
SortList(TempHead->link, *SortMethod); needs to be listed as SortList(&TempHead, *SortMethod);
To correctly pass the pointer.
I am currently trying to push a struct to list, thing is I have to do this without the use of standard libraries (so no malloc, or calloc etc). Therefore I am struggling a bit, this is what I've got so far.
typedef struct node node_t;
struct node{
int val;
node_t *next;
node_t *prev;
};
node_t nodes[10];
node_t blocked[10];
void init(){
for(int i = 0; i < 10; i++){
nodes[i].val = i;
if(i == 0){
nodes[i].next = &nodes[i+1];
nodes[i].prev = NULL;
}
else if(i == 9){
nodes[i].next = NULL;
nodes[i].prev = &nodes[i-1];
}else{
nodes[i].next = &nodes[i+1];
nodes[i].prev = &nodes[i-1];
}
}
}
node_t *push(node_t **arr, node_t node){
node_t *newhead = &node;
printf("%d\n", newhead->val);
newhead->next = (*arr);
printf("%d\n", (*arr)->val);
return newhead;
}
int main(){
init();
node_t *head = &nodes[0];
node_t *blockhead = &blocked[0];
blockhead = push(&blockhead,nodes[3]);
blockhead = push(&blockhead,nodes[4]);
return 0;
}
The problem I have is that the list only keeps track of the last element I've added to the list, and will crash if trying to access the next value in the list which probably means I am trying to access a NULL pointer but everything seems correct as far as I can tell, but maybe I am missing something super obvious? The point of the "push" function as a whole is to simply add the node to the front of the list ahead of everything else.
Your immediate problem is there is no declaration for node prior to:
node_t *newhead = &node;
You are taking the address of something that doesn't exist -- that's never a good idea (and invokes Undefined Behavior and generally a SegFault).
There is no need for nodes to be declared globally and no need for blocked at all (based on your current code). Avoid using global variables. Declare your variables in main() and pass the variables (or a pointer) to any functions as required.
If you are using an array of type node_t as a linked list without allocation, and are then looking to "push" (e.g. add a new node_t at the beginning as the new list address) then you are essentially just needing to have you newnode.next point to your nodes array (as the address of an array is simply a pointer to its first member) and you need array[0].prev to point to the address of newnode.
From what I can glean from your question, the purpose for the code is an exercise in pointer understanding. Regardless of whether you are dealing with a list stored on the stack or one allocated globally, if you change the first-node in the list, you are changing the list address (because the start of the list is the address of the first node) In order to change the list address within a function, you must pass the address of the list as a parameter to the function --or-- you return a pointer to the new first node and assign address to your list pointer back in the caller. (both are shown below)
Since you are wanting to "push" a locally declared node to the head of the list, in like manner, you must pass the address of that node to your push function so it is working with the actual address of that node rather than the address of the copy of the node created if the node itself is passed as a parameter to your push function. You can do this with something similar to the following to handle addressing your array of nodes as a list through a new node pushed to the head of the list:
/* push takes address of array and address of node as parameters */
node_t *push (node_t **arr, node_t *node)
{
node->next = *arr; /* next for new node is list address */
(*arr)[0].prev = node; /* prev for list is new node address */
*arr = node; /* new node address is new list address */
return node; /* return pointer to new 1st node */
}
Above you are simply setting newnode->next to the current list address, then setting the list->prev to point to the new node, and then setting the list address as the address of the newnode (a pointer to that address is also returned which can be assigned back in the caller, as needed).
The remainder of the changes were really just clean-ups to what you had, adding parameters to your functions as required so that nodes can be properly declared in main() and adding a prn function to print the list. Also node there are no magic numbers used in the code. If you need a constant #define one (or more), or use a global enum to define them (that is a valid use of a global).
Putting it altogether, you could do something like the following:
#include <stdio.h>
#define LMAX 10 /* if you need a constant, define one */
typedef struct node {
int val;
struct node *prev, *next;
} node_t;
void init (node_t *nodes)
{
for (int i = 0; i < LMAX; i++){
nodes[i].val = i;
if (i == 0)
nodes[i].prev = NULL;
else {
nodes[i-1].next = &nodes[i];
nodes[i].prev = &nodes[i-1];
}
}
}
/* push takes address of array and address of node as parameters */
node_t *push (node_t **arr, node_t *node)
{
node->next = *arr; /* next for new node is list address */
(*arr)[0].prev = node; /* prev for list is new node address */
*arr = node; /* new node address is new list address */
return node; /* return pointer to new 1st node */
}
/* simple print list */
void prn (node_t *list)
{
for (; list; list = list->next)
printf (" %d", list->val);
putchar ('\n');
}
int main (void) {
node_t nodes[LMAX], /* array of nodes */
*head = nodes, /* list pointer */
singlenode = { .val = LMAX }; /* new node to push */
init(head); /* init list */
prn (head); /* print list */
push (&head, &singlenode); /* push new node to list */
prn (head); /* print new list */
return 0;
}
Example Use/Output
$ ./bin/lldblstatic
0 1 2 3 4 5 6 7 8 9
10 0 1 2 3 4 5 6 7 8 9
Look things over, paying attention to the use of addresses and pointers. If you have further questions, do not hesitate to ask.
I was completing a Hackerrank challenge involving addition of elements to a linked list and printing it.
The input is of this format: A set of integers, in which the first element gives the size and the rest are the components of the list.
I completed the challenge in Java, but I am not able to do it in C.
Input of 4 2 3 4 1 should print 2 3 4 1, but this snippet that I coded is giving me 1 1 1 1 1 1 .... {truncated}
My approach: Declare a new struct temp of type Node (with the data input as data field, and NULL in next field), then iterate thorough the linked list with head as the starting point, and when it reaches the last element, change the next field of the last element to the address of the current element.
Code:
#include <stdlib.h>
#include <stdio.h>
typedef struct Node{
int data;
struct Node* next;
}Node;
Node* insert(Node *head,int data)
{
Node temp = {data, NULL} ;
if (head == NULL)
{ head =&temp;
return head;
}
else{
Node* current = head ;
while(current->next !=NULL)
current = current->next ;
current->next = &temp;
return head;
}
}
void display(Node *head)
{
Node *start=head;
while(start)
{
printf("%d ",start->data);
start=start->next;
}
}
int main()
{
int T,data;
scanf("%d",&T);
Node *head=NULL;
while(T-->0){
scanf("%d",&data);
head=insert(head,data);
}
display(head);
}
List nodes must be allocated dynamically. This
Node temp = {data, NULL} ;
declares a local variable. Referring to its address outside the scope of its declaring function is undefined behavior.
Replace with
Node *temp = malloc(sizeof(Node));
temp->data = data;
temp->next = NULL;
Now thtat temp is a pointer, expression &temp has to be replaced with temp as well.
Because you save a pointer to a local variable in the list. When the insert function returns, the local variable temp will go out of scope and cease to exist. Saving a pointer to it and using that pointer will lead to undefined behavior. Find a good beginners book and read about dynamic allocation of memory.
Working on a linked list where I'm storing a pointer to head as a global variable. My question is: How can I assign a (new)value (in this case address) to head from within a void function?
EDIT
Alright here's some code:
Note: this is not how i would design this, but we're not supposed to stray from the spec.
typedef struct NODE Node;
typedef Node *NodePtr;
struct NODE{
char *item;
Node *next;
};
NodePtr first = NULL; //global
//insert function
Boolean insert( char *new_string ) {
printf("insert called\n");
if(first == NULL) {
first = malloc(sizeof(Node));
first->next = NULL;
first->item = new_string;
}
else {
NodePtr inserted = malloc(sizeof(Node));
inserted->next = first;
inserted->item = new_string;
first = inserted;
}
return 1;
}
the problem is that when i use insert() in a function. it works fine. i get a working list. but when another function tries to access first, its empty.
Am I right in assuming that modifying the global variables within the function does not alter the actual first ptr? I know I could pass in a pointer to first as an argument, but I'm not supposed to modify the prototype design.
You'll need to pass in the pointer and a pointer to pointer to head.. Update pointer to head, and head-> next to old head
if it is a global variable just assign the value like you would have done if it was a local variable in your void function.
assuming your struct is similar to this:
struct list {
int data;
struct list* next;
};
and you have the global variable
struct list* L
you can make a new node by making a new node, making the next variable to the head, and making your global value point to the new node:
newnode->next = L;
L = newnode