This question already has answers here:
Delete node from Linked List
(3 answers)
Closed 1 year ago.
I'm trying to delete a data from linked list loaded from drivers.txt and I haven't got any ideas to how to do it...
So to imagine this is my drivers.txt file.
***
Carl
RedBull
***
John
Mercedes
***
Jessica
Mercedes
***
Brandon
RedBull
I'm trying to remove every driver driving for RedBull. So when I print next time I want to see only John and Jessica.
My struct:
typedef struct drivers {
char *name;
char *team;
struct drivers *next;
} drivers_t;
How I load the drivers.txt.
drivers_t *drivers_load(const char *file){
int i = 0;
FILE *fp = fopen("drivers.txt", "r");
drivers_t *ptr = NULL;
drivers_t *head = NULL;
char buffer[255];
while (fgets(buffer, 255, fp) != NULL){
switch(i++){
case 0:
if( !ptr ) {
ptr = drivers_new();
head = ptr;
}
else {
ptr->next = drivers_new();
ptr = ptr->next;
}
break;
case 1:
ptr->name = strdup(buffer);
break;
case 2:
ptr->team = strdup(buffer);
break;
i = 0;
break;
}
}
return head;
}
My print function:
void drivers_print(drivers *head){
int number = 1;
for (drivers_t *drivers = head; drivers != NULL; drivers = drivers->next){
printf("%d.\n", number++);
printf("Driver: %s", drivers->presenter);
printf("Team: %s", drivers->birth_number);
}
}
Thanks in advance for any ideas.
Deleting node:
void node_delete(drivers_t *head){
char team[32];
scanf("%s", &team);
strcat(team, "\n");
for (node_t *node = head; node != NULL; node = node->next){
if(strcmp(node->team, team) == 0){
drivers_t *temp;
temp = head->next;
head->next = temp->next;
free(temp);
}
else{}
}
}
If you have a list like this:
A -> B -> C -> D -> E
and you want to delete C, all you need to do is to ensure that the next pointer of B now points to D, so you get:
A -> B -> D -> E
Basically the algorithm is:
Go down the list and find C, the node you want to remove.
While going down the list, always also remember the last node you have seen, which would be B in that case.
Once you reached C, assign the next pointer value of C to the next pointer value of B and you are done, as now going over the list directly jumps from B to D.
Finally clean up C, which means free any memory C or any of its struct fields are using.
The only tricky case is the first node, as removing A is a special case, in which case you must set the list pointer itself to the next value of A, so the list now starts with B. You can recognize that case easily, though, as in step (2) you have remembered the last node. When you start, there is no last node, so initially that value should start with NULL. If you found the node (step 3) and the last one is NULL, you will know that you just hit the first node and you can handle that case appropriately.
Related
This question already has answers here:
Why is the gets function so dangerous that it should not be used?
(13 answers)
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 4 years ago.
When I try to run this code, all I get is a warning that gets() is too dangerous too use. And then when I run it, I get blank. I am suppose to display this:
Ollie 2.9 freshmen
John 3.2 senior
Julie 2.2 freshmen
Joe 1.8 freshmen
Mary 3.8 senior
Sue 3.4 junior
Jane 2.7 senior
Bob 2.8 senior
Fred 3.2 freshmen
Bill 3.3 junior
Here is my code:
Student *top = NULL; // to point top node of list
Student * temp, *temp1, *temp2; // for traversing list
// Creates the entire linked list from the file.
// Should call readNext and push
// Returns head of the linked list
Student *buildStudentList()
{
Student *p; // will hold the data to be pushed in list
p = readNext();
push(&top, p);
return top; //TODO: Change return
}
//Read a single line from standard input and return a student structure located on the heap
Student *readNext()
{
Student *s = (Student*)malloc(sizeof(Student)); // allocating dynamic memory in heap
printf("Please Enter Student Name, gpa, year :");
gets(s->name);
scanf("%f", &s->gpa);
gets(s->year);
s->next = NULL; // initially make next as NULL
return s; //TODO: Change return
}
//Return a student structure stored on the heap
Student *makeStudent(char *name, float gpa, char *year)
{
Student *s = (Student*)malloc(sizeof(Student));// allocating memory in heap
s->name = name;
s->gpa = gpa;
s->year = year;
s->next = NULL;
return s; //TODO: Change return
}
//insert a new student node at the head of the linked list
void push(Student **list, Student *student)
{
top = *list;
student->next = top; // assign current top node of list to be second node of the list
top = student; // make current node as top node of the list
printf("push successful.\n");
}
//Insert a student node in the desired position on the linked list
void insert(Student *list, Student *s, int position)
{
int i;
top = list;
temp = top;// temp is for traversing the list
for (i = 1; i < position - 1; i++) // loop to reach desired position in the list
{
temp = temp->next;
}
if (temp == NULL)
{
printf("Position does not exist.\n");
}
else
{
s->next = temp->next;
temp->next = s;
}
}
//Displays contents of a single student structure
void display(Student *s) {
printf("NAME:%s\t| GPA:%f\t| YEAR:%s\n", s->name, s->gpa, s->year);
}
//Displays contents of the entire linked list
void displayAll(Student *list)
{
temp = list;
while (temp != NULL)
{
display(temp);
temp = temp->next;
}
}
//Delete all data allocated on the heap before terminating program
void cleanUp(Student *list)
{
temp1 = list; // will point to the top node of list
temp2 = temp1->next; // will point to the second node of the list
while (temp1 != NULL)
{
free(temp1);
temp1 = temp2;
temp2 = temp2->next;
}
printf("Cleanup Successful.\n");
}
//Main function tests your functions.
int main()
{
Student *list, *s;
printf("Program Started ");
//Construct Linked List from Standard Input
list = buildStudentList();
//Insert a new student in desired position
s = makeStudent("Max", 3.0, "senior");
insert(list, s, 1);
//Display entire linked list
displayAll(list);
//Free all heap memory
cleanUp(list);
printf("Program Successful Exit ");
return 0;
//exit(EXIT_SUCCESS);
}
And here is the output I am getting:
Program Started
Segmentation fault
Should I try to use the fgets() instead of gets()? The output I am trying to do is part of a different file, does that have a affect to it?
Ignoring warnings is never the right thing to do. The aim is not just to remove the warnings using some hack but to address the root cause that produces warning. In this particular case, the compiler explicitly has warned you that using gets is too dangerous. Why would you not heed such a clear warning?
gets has been removed from the standard from C11 onwards.
The gets() function does not perform bounds checking, therefore this function is extremely vulnerable to buffer-overflow attacks. It cannot be used safely (unless the program runs in an environment which restricts what can appear on stdin). For this reason, the function has been deprecated in the third corrigendum to the C99 standard and removed altogether in the C11 standard. fgets() and gets_s() are the recommended replacements.
Never use gets().
Also look at your memory allocation/deallocation for the members of the struct.
Also read this question on whether the result of malloc should be cast.
Hello I went through your code, assuming that your structure description is as follows:
typedef struct Student_s{
char name[32];
float gpa;
char year[5];
struct Student_s* next;
}Student;
The problem with gets() is already pointed out in previous answer by P.W
. You could use scanf("%s",s->name) instead of gets(),
And in makeStudent() you should be using strcpy() for copying string. [ Reason ]
Also in cleanUp() consider the case when the last node is being freed, temp1 will be pointing to the last node and temp2 to NULL. In this situation if you do a temp2 = temp2->next it will result in segmentation fault. You could avoid that by enclosing the statement in an if.
if(temp2 != NULL){
temp2 = temp2->next;
}
If the following assumptions can be made, is it possible to recover the head node of a linked list.
The linked list is created using malloc and it can be accessed from heap area.
The heap start and end address can be found from /proc/self/maps (at least in Linux).
At least one node in the original linked list is accessible.
The pointer to the previous node will be found in the heap somewhere.
And it can be recursively searched until the actual head is found.
To illustrate it better, please use the following program which can be compiled successfully with gcc under at-least Ubuntu/WSL under default configurations.
Program
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
typedef struct node
{
int val;
struct node *next;
} node_t;
node_t *head = NULL;
unsigned long start_address = 0;
unsigned long end_address = 0;
node_t *getLastNode()
{
node_t *iter = head;
for (; iter->next != NULL; iter = iter->next)
;
return iter;
}
void addToLinkedList(int value)
{
node_t *data = malloc(sizeof(node_t));
data->val = value;
data->next = NULL;
if (head == NULL)
head = data;
else
getLastNode()->next = data;
}
void createLinkedList()
{
// Add 10 nodes to the linked list
int start_val = 0x10101010;
for (int i = 1; i <= 10; i++)
addToLinkedList(start_val * i);
}
void printLinkedList()
{
printf("Head pointer of Linked List : %p\n", head);
for (node_t *iter = head; iter != NULL; iter = iter->next)
printf("%p -> value = %X, next = %p \n", iter, iter->val, iter->next);
printf("\n");
}
void resetHeadPtr()
{
// Lets make head point to the last node
head = getLastNode();
}
void findHeapBoundary()
{
// Code inspired from https://unix.stackexchange.com/a/251769/152334
char mapsFilename[1024];
char line[256];
char area[1024];
sprintf(mapsFilename, "/proc/%d/maps", getpid());
FILE *pMapsFile = fopen(mapsFilename, "r");
while (fgets(line, 256, pMapsFile) != NULL)
{
// Dirty hack to get the heap start and end address
sscanf(line, "%08lx-%08lx%*[^[]%s\n", &start_address, &end_address, area);
if (strcmp(area, "[heap]") == 0)
break;
}
fclose(pMapsFile);
printf("Heap memory start address : %p\n", (int *)start_address);
printf("Heap memory end address : %p\n", (int *)end_address);
}
node_t *findPointerInMemory()
{
for (int *ptr = (int *)start_address; ptr < (int *)(end_address - sizeof(node_t)); ptr++)
{
if (((node_t *)ptr)->next == head)
return (node_t *)ptr;
}
return NULL;
}
void recoverHeadPtr()
{
node_t *ptr = findPointerInMemory();
if (ptr == NULL)
{
printf("Cannot find %p in heap memory\nStopping Search\n\n", head);
return;
}
printf("Found %p at %p\n", head, ptr);
head = ptr;
recoverHeadPtr();
}
int main(int argc, char const *argv[])
{
createLinkedList();
printf("Original Linked List Contents\n*****************************\n");
printLinkedList();
resetHeadPtr();
printf("Linked List Contents after reset\n********************************\n");
printLinkedList();
findHeapBoundary();
recoverHeadPtr();
printf("Recovered Linked List Contents\n******************************\n");
printLinkedList();
return 0;
}
Output
Original Linked List Contents
*****************************
Head pointer of Linked List : 0x1db6010
0x1db6010 -> value = 10101010, next = 0x1db6030
0x1db6030 -> value = 20202020, next = 0x1db6050
0x1db6050 -> value = 30303030, next = 0x1db6070
0x1db6070 -> value = 40404040, next = 0x1db6090
0x1db6090 -> value = 50505050, next = 0x1db60b0
0x1db60b0 -> value = 60606060, next = 0x1db60d0
0x1db60d0 -> value = 70707070, next = 0x1db60f0
0x1db60f0 -> value = 80808080, next = 0x1db6110
0x1db6110 -> value = 90909090, next = 0x1db6130
0x1db6130 -> value = A0A0A0A0, next = (nil)
Linked List Contents after reset
********************************
Head pointer of Linked List : 0x1db6130
0x1db6130 -> value = A0A0A0A0, next = (nil)
Heap memory start address : 0x1db6000
Heap memory end address : 0x1dd7000
Found 0x1db6130 at 0x1db6110
Found 0x1db6110 at 0x1db60f0
Found 0x1db60f0 at 0x1db60d0
Found 0x1db60d0 at 0x1db60b0
Found 0x1db60b0 at 0x1db6090
Found 0x1db6090 at 0x1db6070
Found 0x1db6070 at 0x1db6050
Found 0x1db6050 at 0x1db6030
Found 0x1db6030 at 0x1db6010
Cannot find 0x1db6010 in heap memory
Stopping Search
Recovered Linked List Contents
******************************
Head pointer of Linked List : 0x1db6010
0x1db6010 -> value = 10101010, next = 0x1db6030
0x1db6030 -> value = 20202020, next = 0x1db6050
0x1db6050 -> value = 30303030, next = 0x1db6070
0x1db6070 -> value = 40404040, next = 0x1db6090
0x1db6090 -> value = 50505050, next = 0x1db60b0
0x1db60b0 -> value = 60606060, next = 0x1db60d0
0x1db60d0 -> value = 70707070, next = 0x1db60f0
0x1db60f0 -> value = 80808080, next = 0x1db6110
0x1db6110 -> value = 90909090, next = 0x1db6130
0x1db6130 -> value = A0A0A0A0, next = (nil)
Background
A friend of mine was asked the following question in an interview. “Can you find the head pointer of a single linked list if the last node is given?”. He answered “no” and even though the interviewer was not entirely satisfied with the answer, he was offered the job. This got me into thinking, whether it is possible do this.
So, the real questions are.
Is this approach correct?
Do we need to search in other memory segments?
Can this approach be generalized to work on Windows too?
Will ASLR have any impact on this approach?
The correct answer would have been:
Not cleanly and attempting to do so would be a risky workaround for a bad design.
If you actually do try to search for the address of anything in memory (which is not in any way guaranteed to only contain the address if it is the pointer in question), then you might find instead any piece of memory which seems to accidentally contain a number which looks like the address in question.
If you then continue using that, assuming it to be the pointer, you are inviting all kinds of problems.
If you do that repeatedly to go backwards through a single-linked list, then you practically guarantee to find at least one nonsense.
In short: No.
A simple "No." is too short and might have made the examiner frown because of that.
In standard C it's not possible.
accessing the heap other than via pointers given by malloc (or copies of those pointers etc) will get you undefined behaviour.
However if you have knowledge of the allocator and can walk the structure of the allocated memory blocks you can find candidate list nodes. one of them will be the head.
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'm having an issue: in a function, program needs to compare two nodes and delete one of them if the node values are the same (example: A -> B -> B -> C >>> A -> B -> C). In a few words: it have to leave only unique nodes.
Steps that I've done: created list from data given in data file and it prints out perfectly. Now I'm struggling comparing two nodes.
Steps that I'm thinking of doing: Put two nodes values in two different variables, then comparing those two and if latest node is equal to previous, delete the latest and somehow link previous node to next node. Then the cycle goes all over again.
Question: How do I compare node with further one?
Here's the code that I have right now:
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 255
struct node {
int info;
struct node *next;
} *head = NULL;
int create(FILE **data){
char read[LENGTH];
printf("Write data file name: ");
scanf("%s", read);
*data = fopen (read, "r");
if (data == NULL) {
printf("Error reading given file.");
}
return 0;
}
int put_Symbols_into_list(FILE *data) {
struct node *new_node, *current;
char c;
printf("Data given: ");
while (!feof(data)){
new_node = (struct node*)malloc(sizeof (struct node));
c = fscanf(data, "%s", &new_node -> info);
printf("%s ", &new_node -> info);
if (head == NULL){
head = new_node;
current = new_node;
} else {
current -> next = new_node;
current = new_node;
}
}
}
int delete_Same_Symbols() {
}
int main() {
FILE *data;
struct node *n;
create(&data);
put_Symbols_into_list(data);
delete_Same_Symbols();
//display_List(n);
return 0;
}
An efficient way of remove duplicates is the following:
1. Sort the list
2. Run through the list once deleting any adjacent duplicates.
Whether this solution works for you depends on whether your data can be ordered.
Traverse the list from head to end and maintain a Hash table.
For every element,check whether value is in the hash table: if yes, remove the node; else put value in the hash table.
Time Complexity: O(n) on average (assuming that hash table access time is O(1) on average).
I'll give you the function that will remove the duplicates.
Assuming that your code is working fine and that the info is an int value
Note that if info is a string you will need strcmp function instead of head->info == info.
int exist(NODE *head, int info) {
while (head && head->info != info) // strcmp(info,head->info) != 0
head = head->next;
return head->info == info; // strcmp(info,head->info)
}
void removeDuplicates(NODE **phead, int info) {
NODE *tmp = *phead;
while (tmp->info != info) // strcmp(info,head->info) != 0
tmp = tmp->next;
NODE *tmp1 = tmp->next;
tmp->info = tmp1->info; // strcpy(tmp->info,tmp1->info)
tmp->next = tmp1->next;
free(tmp1);
}
I'm trying to add a node to a linked list. The idea is to pass in the pointer, see where new node will go to through a ranked order, in this case G, then D, then M, then S.
Yet, when I compile and run, I'm not actually generating a linked list (this has already been done in the main). I'm more than certain that there's something wrong with my addp() function. Is it that I should pass in double pointers instead?
Sorry for being rather unprofessional and clueless. I'm not the strongest of coders.
Any help would be helpful.
I have attached my method which I have gone through so many times.
typedef struct node {
char fname[1024];
char lname[1024];
char pos;
int val;
int rank;
struct node * next;
} player;
struct node* addp (player* newnode, struct node* list){
player* templist = list;
player* templist1;
// if the list is non empty.
if (list!=NULL){
if(newnode->pos == GOALKEEPER){ //insert if G.
newnode->next = list;
}
if(newnode->pos == DEFENDER){// after G bef M.
// iterate through templist.
while (templist->next != NULL && (templist->next)->rank < 1) { // go to end of G.
// when the list isn't empty next node rank is less than one, keep going
templist = templist -> next;
}
// when finally rank == or > 1, then add newnode.
templist1 = templist->next;
templist->next = newnode;
newnode->next = templist1;
}
if(newnode->pos == MIDFIELDER){ //after G and M but before S
while (templist->next != NULL && (templist->next)->rank <2 && (templist->next)->rank> 2){
templist = templist -> next;
}
// when stopped, then add newnode.
templist1 = templist->next;
templist->next = newnode;
newnode->next = templist1;
}
if(newnode->pos == STRIKER){ // at the end.
while (templist->next != NULL && (templist->next)->rank <3){
templist = templist -> next;
}
templist1 = templist->next;
templist->next = newnode;
newnode->next = templist1;
}
return list;
printf("player added");
}
// if list is empty
else{
newnode->next = list;
return 0;
}
}
The following is the list function I've come up with. It keeps saying that my linked list is empty. Maybe it's something wrong with this function.
int print(struct player* list){
// create temp list so non modify origin.
struct player* temp = list;
if (list == NULL && temp == NULL)
printf("linked list is empty");
while (temp != NULL){
printf("%s \n", temp->lname);
printf("%s \n", temp->fname);
printf("%c \n", temp->pos);
printf("d \n", temp->val);
temp = temp->next;
}
return 0;
}
Without knowing the player typedef this is hard to analyze, but I think you can make it much easier on yourself by simplifying the signature of the function to only use player.
void addp(player* newnode, player* firstnode)
The return is unnecessary since you're just returning the 2nd argument, which the caller already has. The 2nd argument should be a pointer to a player node, which is the first element in your linked list. If you can call the function without the compiler complaining about implicitly casting pointers then I don't see anything wrong with your algorithm, although it could certainly be simplified.
Ok so what I understood is that your player structure contains a variable pos that will indicate in which place insert the player in the list. Am I right ?
In that case the best thing you can do is to sorted the list by the rank variable. Then modify your pos variable (in the player structure) to match with the rank variable of your list.
Then you will just have to add it with a classic "add in sorted list" function : C++ Add to linked list in sorted orderenter link description here