I have a struct called employee in my program with the following definition:
struct employee {
int id;
int age;
struct *employee next;
};
How would I take in input from the user, create a struct from their input, and create a singly linked list using pointers? I'm having a lot of issues figuring out how to do this dynamically. In Java, this is easily done through the constructor but how would you do this in C?
EDIT: Assuming the input is simply two ints (id and age).
This is how you create a new employee struct. You are dynamically allocating the memory using malloc function.
struct employee *new_employee = (struct employee*)malloc(sizeof(struct employee));
Now, we need to fill the data into this newly created employee field:
new_employee -> id = input_id;
new_employee -> age = input_age;
As for the next pointer, it is usually given NULL value. This is to prevent the next pointer from pointing to any arbitrary memory location.
new_employee -> next = NULL;
Finally, we have to link the list. To do that, you have to point the next pointer of the previous employee field to the current employee field (ex:as you mentioned in comment, first one (9,3) having a next pointer to the second one (3, 2))
Since it is a singly linked list, we cannot backtrack. So, there are two methods to access the previous field.
First is to maintain a pointer that points to the last field of the link list.
Second is to traverse the entire list till the end, and when you reach the last element, change its next pointer.
Implementation of the second method:
node *temp = *start;
if(temp!=NULL)
{
while(temp -> next)
temp = temp -> next;
temp -> next = new_employee;
}
Hope it helps!
Note : don't give me fish teach me how to fish
This is an example :
struct node {
int value;
struct *node next;
};
How to create new Node pointer dynamically ?
node* aux = (node*) malloc(sizeof(node));
How to get user input ( safely ) ?
char line[256];
int i;
if (fgets(line, sizeof(line), stdin)) {
if (1 == sscanf(line, "%d", &i)) {
/* i can be safely used */
}
}
How to create a linked list's head ?
/* This will be the unchanging first node */
struct node *root;
/* Now root points to a node struct */
root = (struct node *) malloc( sizeof(struct node) );
/* The node root points to has its next pointer equal to a null pointer
set */
root->next = 0;
/* By using the -> operator, you can modify what the node,
a pointer, (root in this case) points to. */
root->value = 5;
How to add new node to the linked list ?
/* This won't change, or we would lose the list in memory */
struct node *root;
/* This will point to each node as it traverses the list */
struct node *conductor;
root = malloc( sizeof(struct node) );
root->next = 0;
root->value = 12;
conductor = root;
if ( conductor != 0 ) {
while ( conductor->next != 0)
{
conductor = conductor->next;
}
}
/* Creates a node at the end of the list */
conductor->next = malloc( sizeof(struct node) );
conductor = conductor->next;
if ( conductor == 0 )
{
printf( "Out of memory" );
return 0;
}
/* initialize the new memory */
conductor->next = 0;
conductor->value = 42;
Now you must be able to solve the problem easily .
Happy Coding :D
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!
-If A list has integer data such as: 1->2->3->4->5->6
-And pos_list has integer data such as: 4->0->5
-Then this function should return a New List hat contains the values that appear in list A at positions given in pos_list
such that New List= 5->1->6
I am implementing deep copy to make new List.
I am trying to use a loop that iterates according to the data of pos_list. Inside this loop, node of A will move to position of pos_list data. In this time i will copy the node A in new list to make another list.
Say for first case, pos_list has data 4, so the loop will run 4 times until the node of list A points to its fourth position. Inside this loop i will copy the data of list A in a new loop.
I need a guidance to solve this problem.
struct node * sublist(struct node * A, struct node * pos_list) {
struct node* newList=NULL;
struct node * curr;
int i=0;
for (i = 0, curr = pos_list->next; (curr != NULL); curr = curr->next) { //pos_list->data has a dummy node so loop until the end of pos_list->data.
struct node* newList = (struct node *) malloc(sizeof (struct node));
for(int i=0;i<=pos_list->data;i++){ //counter for pos_list as it will be (3 then 0,6 and 4)
if(i==pos_list->data){ //At the time when i == pos_list->data(3 or 0 or 6..)
newList->data = A->data; //Putting value of list A data in new list.
newList = newList->next; //Linking
printf("%d\t", newList->data); //Just for log
}
A=A->next; //Going to next position on A
}
pos_list=pos_list->next; //Going to next position on B
}
return newList ;
}
If A list is : 1->2->3->4->5->6
And pos_list is: 4->0->5
I expect the output is new list as 5->1->6
Your code has several problems:
You should start your traversal with pos_list, not with pos_list->next. The node pointed to by the head pointer is part of the list. Further, if pos_list == NULL, pos_list->next will lead to undefined behaviour.
The outer definition of int i isn't useful. Delete it.
Don't iterate through A by means of the position. If the position isn't valid, you will walk beyond the end of the list, get null pointers and invoke undefined behaviour. Lists should be iterated by list nodes accessed from the previous nodes' next pointers. (It is, of course, the caller's resposibility to provide valid positions, but your program should handle invalid input gracefully.)
Create the new node only when you have found a valid position. Otherwise you create a node that is never inserted and thus leak memory.
Here: newList = newList->next, newList->next isn't initialized. Remember that malloc gives you a chunk of uninitialized data.
You try to make newList point to the end of the newly created list, so that appending new nodes ist fast. That's a good idea, but if you return that pointer, you'll get a list that consists only of one element. (You'll also no loger be able to access any previously created nodes in that list.)
Here's an implementation that should work:
struct node *sublist(struct node *A, struct node *pos_list)
{
struct node *newHead = NULL;
struct node *newTail = NULL;
struct node *pos = pos_list;
while (pos) {
struct node *a = A;
int i = 0;
while (a) {
if (i == pos->data) {
struct node *node = malloc(sizeof(*node));
if (newHead == NULL) newHead = node;
if (newTail) newTail->next = node;
node->data = a->data;
node->next = NULL;
newTail = node;
break;
}
a = a->next;
i++;
}
pos = pos->next;
}
return newHead;
}
The question does not condone using a "struct" to implement the solution.
If it does, I am mistaken but if it does not, isn't it an overkill, when something akin to the following can be implemented....
#include <stdio.h>
#define CREATE_ARRAY(n) int result[n]
void main() {
int data[] = {1,2,3,4,5,6};
int pos[] = {4,0,5};
int i;
CREATE_ARRAY(sizeof(pos)/sizeof(int));
for(i = 0; i < sizeof(pos)/sizeof(int);++i)
result[i] = data[pos[i]];
/*
To print the values stored in result
for(i = 0;i < sizeof(result)/sizeof(int); ++i)
printf("%d ",result[i]);
putchar('\n');
}
*/
For starters the function sublist should be declared like
struct node * sublist( const struct node *A, const struct node *pos_list );
because neither the list A nor the list pos_list are changed in the function. Otherwise the declaration of the function confuses readers of the code.
It is a bad idea that the list pos_list contains a dummy node as it is wrote in the comment to this statement
for (i = 0, curr = pos_list->next; (curr != NULL); curr = curr->next) { //pos_list->data has a dummy node so loop until the end of pos_list->data
Neither dummy node should be in the list.
In this inner loop
for(int i=0;i<=pos_list->data;i++){
there is not used the dummy node of the list. Moreover the pos_list is traversed in the two loops: the outer loop and the inner loop
for (i = 0, curr = pos_list->next; (curr != NULL); curr = curr->next) { //pos_list->data has a dummy node so loop until the end of pos_list->data.
struct node* newList = (struct node *) malloc(sizeof (struct node));
for(int i=0;i<=pos_list->data;i++){
Within the loops the value of the variable newList is changed
newList = newList->next;
So as a result the function always returns some indeterminate value instead of the head of the newly created list. The value is indeterminate because the data member next of a new created node is not initialized.
newList->data = A->data; //Putting value of list A data in new list.
newList = newList->next;
The function can be defined the following way
struct node * sublist( const struct node *A, const struct node *pos_list )
{
struct node *newList = NULL;
struct node **current = &newList;
for ( ; pos_list != NULL; pos_list = pos_list->next )
{
const struct node *target = A;
for ( int index = pos_list->data; index != 0 && target != NULL; --index )
{
target = target->next;
}
if ( target != NULL )
{
*current = malloc( sizeof( struct node ) );
( *current )->data = target->data;
( *current )->next = NULL;
current = &( *current )->next;
}
}
return newList;
}
I am currently working on a project that takes in two text files with data and sorts them into two separate linked lists. My next step is to create a function that takes in those two lists to merge and sort them by ID in increasing order. I have started the implementation but I am stuck and need some guidance on what it is I am doing wrong for the merge sort function. Everything else is working correctly such as sorting each list individually. I just need a way to take in those two lists and merge sort them together in C. Note: I am using the Ubuntu gcc compiler.
struct List *merge_list(struct List *list1, struct List *list2)
{
struct Node *hand1 = list1->head;
struct Node *hand2 = list2->head;
struct Node *tmp1, *tmp2 = NULL;
struct List *list3 = malloc(sizeof(struct List));
while(list1 && list2 != NULL)
{
if(ptr1->id > ptr2->id)
{
ptr1 = list3->head;
ptr1 = ptr1->next;
}
else
{
ptr2 = list3->head;
ptr2 = ptr2->next;
}
}
return list3;
}
Note: Here are my Node and List structs
struct Node {
int id;
char *fname;
char *lname;
char *department;
float gpa;
struct Node *next;
struct Node *prev;
};
struct List {
struct Node *head;
struct Node *tail;
int count;
};
To merge two sorted lists:
while (hand1 && hand2) {
if (hand1->id <= hand2->id) {
tmp = hand1;
hand1 = hand1->next;
} else {
tmp = hand2;
hand2 = hand2->next;
}
insertNode(list3, tmp);
}
// either hand1 or hand2 will have some leftover elements
// they can be added to the back of list by inserting the head
if (hand1)
insertNode(list3, hand1);
else
insertNode(list3, hand2);
I've left it to you to write insertNode(). In order to preserve the sorting of the two lists, it should insert nodes at the end of the list. It should be very easy since you are tracking the tail of the list.
I would initialize the pointers in list3 to NULL and the count to 0, it should make writing insertNode() easier.
You have two doubly linked list and both are sorted and your requirement is to create a function that takes in those two lists to merge and sort them by ID in increasing order. Since both the doubly linked list is already sorted, you don't need to first merge them and then sort but you can merge them in sorted order.
You can do:
struct Node * merge_list(struct Node * head1, struct Node * head2)
{
struct Node* head3 = NULL;
struct Node* p1 = head1;
struct Node* p2 = head2;
struct Node* p3 = NULL;
while (p1 != NULL || p2 != NULL)
{
struct Node * tmp = NULL;
if (p1 == NULL) {
tmp = p2;
p2 = NULL;
} else if (p2 == NULL) {
tmp = p1;
p1 = NULL;
}
if ((p1 != NULL) && (p2 != NULL)) {
if (p1->id < p2->id) {
tmp = p1;
p1 = p1->next;
} else {
tmp = p2;
p2 = p2->next;
}
}
if (head3 == NULL) {
head3 = tmp;
} else {
p3->next = tmp;
tmp->prev = p3;
}
p3 = tmp;
}
return head3;
}
Output:
List 1:
1 3 7
List 2:
2 4 6 8
Merged list:
1 2 3 4 6 7 8
Few points about merge_list() function:
In this merge_list() function I am taking the head pointers of both the list and returning the head pointer of the merged list. But I can see that you have struct List which maintains the head and tail pointer of the lists. So, you need to do the changes accordingly in the function, like the argument and return type will be struct List * type and in the function, you need to take care of merge list tail pointer as well. The core logic is going to be same.
The function merge_list() modify the two list, which are passed as arguments to it, as it resets the next and prev pointers of the lists node in order to merge them. So, after this function call, both the lists passed as arguments to it are no more valid. Set their head and tail pointer to NULL.
If you want both the list, passed as arguments to merge_list(), intact after the merge_list() call then you need to make copy of node while adding to the merged list. For that, you need to allocate memory to tmp and wherever tmp is set to either p1 or p2, instead assign the values to tmp members. Be cautious here, if a member of the structure Node is a pointer to some memory then allocate memory to that tmp member pointer and copy the value.
Hope this helps.
How would you iterate this 2D linked list?
typedef struct _NODE
{
char *pszName;
unsigned long ulIntVal;
char *pszString;
struct _NODE *pNext;
struct _NODE *pDown;
} NODE;
I could do something like this..
NODE *pHEad;
while (pHead != NULL) {
printf("%s", pHead->pDown->pszName);
pHead = pHead->pNext;
}
.. but it would only give me the one node under every next node. What if it is another node under that one again? And under that one again? Or if there is a pNext attached to the pDown?
In the simplest case, you could use something like the following recursive function:
void processNode(NODE *current) {
if (current != NULL) {
printf("%s", current->pszName);
processNode(current->pNext);
processNode(current->pDown);
}
}
int main(void) {
NODE *pHead;
/* ... Do something to fill your list ... */
processNode(pHead);
/* ... */
}
Also be aware that this can cause a deep nesting of the function calls depending on your processed list. So if you are on an embedded system with limited stack size or if you are processing huge lists, you might run out of stack. In that case, you should find another approach for the processing.
Note that this will first process the pNext-list and then start with processing the first node of the pDown-list of the last node. So assuming the following structure (to the right is pNext and downwards is pDown):
pHead -> p1 -------> p2
|- p1_1 |- p2_1 -> p2_1_1
\- p1_2 |- p2_2
\- p2_3 -> p2_3_1
it should print the nodes in the following order:
pHead, p1, p2, p2_1, p2_1_1, p2_2, p2_3, p2_3_1, p1_1, p1_2
Look at this answer. Don't be overwhelmed by the amount of the code. I have added enough comments to help you proceed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node{
char data[100]; // Assume that this linked list will contain only 100 chars of data
struct Node* next;
} NODE;
// Global Variables are bad, but oh well.
NODE* head = NULL;
// Function to create a node
NODE* createNode(char* str)
{
// First allocate memory for struct
NODE* newNode = malloc(sizeof(NODE));
if(newNode == NULL)
{
printf("Unable to create a new node.");
}
else
{
// Use strcpy or strncpy or memcpy instead of doing something like newNode -> data = str, which changes the pointer, but doesn't copy the contents
// That is do not do newNode -> data = "hello" or something
strncpy(newNode -> data, str, strlen(str));
newNode -> next = NULL;
}
return newNode;
}
void addNode(char* str)
{
// Returns a node which contains str, but points to NULL
NODE* newNode = createNode(str);
// If the linked list is empty, then we make this node itself as the first node(or head)
if(head == NULL)
{
head = newNode;
}
// Else if the linked list is not empty, then we add this node at the start of the linked list
else
{
newNode -> next = head;
head = newNode;
}
}
int main()
{
// Example Linked List Generated(say you already have it in some form)
addNode("This");
addNode("Is");
addNode("Linked List");
// Now let's print the linked list
// Temporary NODE pointer ptr is used in order to not mess with the original NODE pointer head.
NODE* ptr = head;
// Traverse through the linked list starting from head and at the same time printing the corresponding data, until ptr is null
// This ptr != NULL check is exactly what you are looking for. This is your way of stopping the traversal of Linked List once you
// are at the end of it. You don't have to know the number of nodes to stop the traversal this way.
while(ptr != NULL)
{
printf("%s ", ptr -> data);
ptr = ptr -> next;
}
}
However note that the output will be printed in reverse order, since in this implementation of linked list we are adding things towards the back. Just try running the program and start reading the program starting from main function. I have made the code into separate functions to make it easier for you to understand. Just run the code first to get a grasp of what's happening.
You can use iteration instead of recursion by adding a queue, too, if you want to avoid the possibility of a stack overflow—though this will use slightly more heap memory, and there is still a risk that you can run out of heap memory if you have a large list or if you're running on a memory-constrained system. The important part is the print_list function at the end; the other stuff is just a (mostly) self-managing queue implementation I've provided:
typedef struct node_queue NodeQueue;
struct node_queue {
NODE *n;
NodeQueue *next;
};
/*
* Add an item to the end of the queue.
*
* If the item could not be added, 0 is returned.
* Otherwise, a nonzero value is returned.
*/
int enqueue(NodeQueue **headp, NodeQueue **endp, NODE *n)
{
NodeQueue *old_end = *endp;
NodeQueue *new_end;
new_end = malloc(sizeof *new_end);
if (new_end == NULL) {
return 0;
}
new_end->n = n;
new_end->next = NULL;
if (old_end != NULL) {
old_end->next = new_end;
}
if (*headp == NULL) {
*headp = new_end;
}
*endp = new_end;
return 1;
}
/*
* Remove an item from the head of the queue,
* storing it in the object that "nret" points to.
*
* If no item is in the queue, 0 is returned.
* Otherwise, a nonzero value is returned.
*/
int dequeue(NodeQueue **headp, NodeQueue **endp, NODE **nret)
{
NodeQueue *old_head = *headp;
NodeQueue *new_head;
if (old_head == NULL) {
return 0;
}
if (nret != NULL) {
*nret = old_head->n;
}
new_head = old_head->next;
free(old_head);
if (new_head == NULL) {
*endp = NULL;
}
*headp = new_head;
return 1;
}
void print_list(NODE *start)
{
NodeQueue *head = NULL;
NodeQueue *end = NULL;
NODE *current;
current = start;
/* Iterate all `pNext` nodes, then pop each `pDown` node and repeat. */
for (;;) {
/* Add the "down" node to the node queue. */
if (current->pDown != NULL) {
if (!enqueue(&head, &end, current->pDown)) {
perror("warning: could not add node to queue");
}
}
printf("%s", current->pszNode);
/*
* Move to the "next" node.
* If there is no next node, get the first "down" node from the queue.
* If there is no "down" node, break the loop to end processing.
*/
current = current->pNext;
if (current == NULL) {
if (!dequeue(&head, &end, ¤t)) {
break;
}
}
}
}
This will iterate through all pNext items before moving to a pDown item. The following 2-D list will be printed as A B C D E F G H I J K L M N O P Q:
A
|
B--C
|
D--E-----------F
| |
G-----H I-----J
| | | |
K--L M--N O P
|
Q
You can reverse the priority of pDown/pNext in the print_list function by swapping pNext and pDown inside it, so pNext items are added to the queue and pDown items are iterated until exhausted, which will change the order in which the items are printed to A B D C E G K F I O H M Q L J P N unless you change the structure of the list.
You can see an example using both the code above and the first sample 2-D linked list above at https://repl.it/NjyV/1, though I changed the definition of NODE to make the code using its fields a bit simpler.
I wanted to make a list using double pointer and using void as return.
#include<stdio.h>
#include<stdlib.h>
typedef struct list{
int value;
struct list *next;
}*list;
void addnode(struct list **List, int number) {
if(*List == NULL) {
*List = (struct list*)malloc(sizeof(struct list*));
(*List)->value = number;
(*List)->next = NULL;
} else {
while((*List)->next != NULL) {
(*List) = (*List)->next;
}
*List = (struct list*)malloc(sizeof(struct list*));
(*List)->value = number;
(*List)->next = NULL;
}
}
int main() {
list List1 = NULL;
addnode(&List1, 20);
printf("%d \n", List1->value);
addnode(&List1, 30);
printf("%d \n", List1->value);
printf("%d \n", List1->next->value);
return 0;
}
The first if in addnode is always executed but i want to append the list if its not empty but it seems like it never work. Ill also get segmenation fault because in the last printf it tries to take the next element in the list but its never initialized like i want.
If everthing worked as i wanted i should have printed out
printf("%d\n", List1->value)
20
printf("%d\n", List1->value)
20
printf("%d\n", List1->next->value)
30
The size you are passing to malloc is wrong.
You are allocating a struct list, not a struct list *.
If you are trying to append a new list item, remember (*List)->next will already be NULL on the second call. The malloc following that uses the pointer before the NULL list item (*List) when it should be assigned to the next list item, the one that is NULL, to make it non-NULL ((*List)->next=malloc(struct list);).
Also, your malloc should be using sizeof(struct list), without the *. If you add the *, you're allocating a struct list **. A rule you can use is use one * fewer than the destination type as the sizeof operand. Since your destination is *List, which is of type struct list *, use sizeof(struct list). Alternatively, because your destination is *List, use sizeof **List (use one more * than the destination variable has). This avoids you needing to know the type. It won't matter if List or *List is NULL because the sizeof operation is executed first; pointer dereferencing never occurs since sizeof works on the type of the variable.
Modify your program like this
int addNode(struct list **List, int number)
{
struct list *new, *tmp; // new = create new node, tmp = navigate to last
new = malloc(sizeof(struct list));
if(!new) { //always validate "malloc"
perror("malloc");
exit(1);
}
new -> value = value; // assigning values to new node
new -> next = NULL;
if(!(*list)) { //Check if list is empty or not, plz initialize *list#main() with NULL as like your program. or write seperate function to initialize
*list = new;
return 0; //no need write else condition, bcoz its the first node. and u can directly return
}
tmp = *list;
while(tmp -> next) // To navigate to last node
tmp = tmp -> next;
tmp -> next = new; //creating link to new node
return 0;
}
It's better to write print function seperatly.
int print(struct list **list)
{
struct *current; //current is your current node position
current = *list;
while(current) { //loop till current node addr == NULL
printf("%d\t", current -> value);
current = current -> next;
}
printf("\n");
return 0;
}