Below programme doesn’t work for bigger size strings , but it works properly for small strings.I am not sure why sortedInsert function is not taking full length of string.There is no string length constraint also being used in this programme.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/* Link list node */
struct node
{
char* pattern;
struct node* next;
};
/* function to insert a new_node in a list. Note that this
* function expects a pointer to head_ref as this can modify the
* head of the input linked list (similar to push())*/
void sortedInsert(struct node** head_ref, struct node* new_node)
{
struct node* current;
/* Special case for the head end */
if (*head_ref == NULL || (strcmp((*head_ref)->pattern ,new_node->pattern)> 0))
{
new_node->next = *head_ref;
*head_ref = new_node;
}
else
{
/* Locate the node before the point of insertion */
current = *head_ref;
while (current->next!=NULL &&
strcmp(current->next->pattern, new_node->pattern)< 0)
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
}
/* BELOW FUNCTIONS ARE JUST UTILITY TO TEST sortedInsert */
/* A utility function to create a new node */
struct node *newNode( char * pattern)
{
/* allocate node */
struct node* new_node =
(struct node*) malloc(sizeof(struct node));
new_node->pattern = (char *)malloc(sizeof(pattern));
/* put in the data */
strcpy(new_node->pattern , pattern);
new_node->next = NULL;
return new_node;
}
/* Function to print linked list */
void printList(struct node *head)
{
struct node *temp = head;
while(temp != NULL)
{
printf("\n%s", temp->pattern);
temp = temp->next;
}
}
/* Drier program to test count function*/
int main()
{
/* Start with the empty list */
struct node* head = NULL;
struct node* new_node = newNode("a.b.c.d.e.f.g.h.h.j.k.l.m.n.o");
sortedInsert(&head, new_node);
new_node = newNode("a.b.c.de.f.g.h.j.k.l.m.t.y.u.k");
sortedInsert(&head, new_node);
new_node = newNode("a.b.c.d.ef.g.h.h.k.j.l.y.u.l.p");
sortedInsert(&head, new_node);
printf("\n Created Linked List\n");
printList(head);
return 0;
}
Here is the output of above programme, where unexpected output can be seen.
Output:
Created Linked List
a.b.c.d.e.f.)
a.b.c.d.ef.g.h.h.k.j.l.y.u.l.p
a.b.c.de.f.g)
malloc(sizeof(pattern))
and then
strcpy(new_node->pattern , pattern); not correct.
better, use strlen() to get the received string length, then allocate memory, then perform strcpy() or memcpy() to copy the recived string.
Try with below code , it will work. you must pass string length instead of string itself
new_node->pattern = (char *)malloc(strlen(pattern)+1);
/* put in the data */
memcpy(new_node->pattern , pattern,strlen(pattern)+1);
Other answers are correct; however, there seems to be a dedicated function strdup to do what you want:
// Incorrect code
new_node->pattern = (char *)malloc(sizeof(pattern));
strcpy(new_node->pattern , pattern);
// Correct code, provided by user2083356
new_node->pattern = (char *)malloc(strlen(pattern)+1);
memcpy(new_node->pattern , pattern,strlen(pattern)+1);
// Does the same; seems easier to type and understand; also handles errors
new_node->pattern = strdup(pattern);
Related
I'm trying to write and use linked list. When trying to print the list to the file the first string gets chained to the last node and it causes a segfault.
I've tried debugging and it led me nowhere.
It only happens using printListToFile(...) and readstl(...).
The code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lists_c.h"
#define test "ijm digidimdimadam jjsklva /s4t\t \nmjam \nla kookaracha la kookaracha\n"
/*a method that creates a "blank" node, declares a the next node and points it to NULL, the char array is already initialized.*/
struct Node *makeNode();
struct Node *makeFullNode(struct Node *Next, char *Ptr);
struct Node *readFile(char *path);
struct Node *readstl(char*);
void printList(struct Node *head);
void insertToList(struct Node *node, char *str);
void printListToFile(char *path, struct Node *head);
int main(int argc, char *argv[])
{
struct Node *head;
head = (struct Node *)malloc(sizeof(struct Node));
printf("this is mmn 23 Q3, a func that stores a file in a linked list and then prints it.\n");/*
printf("%s\n",argv[1]);
if (argc == 2) { */
head = readFile("tester1.txt");
printList(head);
printListToFile("test.tmp", head);
insertToList(head->next, test);
printf("head");
free(head);
/*}
else if (argc > 2) {
printf("Too many arguments supplied.\n");
} else {
printf("One argument expected.\n");
}*/
return 0;
}
struct Node *makeNode()
{
struct Node *node;
node = (struct Node *)malloc(sizeof(struct Node));
if (node == NULL) {
printf("memory allocation failed\n");
return NULL;
}
node->next = NULL;
return node;
}
/*a method that creates a node with all values, declares a the next node and points it to the next node recieved
and changes the char array to the one recieved.*/
struct Node *makeFullNode(struct Node *Next, char Ptr[])
{
struct Node *node;
node = (struct Node *)malloc(sizeof(struct Node));
node->next = (struct Node *)malloc(sizeof(struct Node));
node->ptr[NICE] = Ptr[NICE];
node->next = Next;
return node;
}
/*the method that reads the file into the list into the char array of each node and returns the head of the list */
struct Node *readFile(char *path)
{
FILE *fptr;
struct Node *curr, *head;
curr = (struct Node *)malloc(sizeof(struct Node));
head = (struct Node *)malloc(sizeof(struct Node));
if (curr == NULL || head == NULL) {
printf("memory allocation failed\n");
return NULL;
}
curr = head;
fptr = fopen(path,"r");
if (fptr == NULL) {
printf("error - failed to open file\n");
exit(0);
return NULL;
}
while (fgets(curr->ptr, NICE, fptr))/*if fgets returns NULL it means that we either reached EOF or error, both a reason to end the loop*/
{
curr->next = makeNode();
curr = curr->next;
}
if(ferror(fptr))/*checking if the loop ended for the right reason*/
{
printf("error - failed to read file\nthis is what we got so far\n");
}
printf("file succesfully read\n");
fclose(fptr);
free(curr);
return head;
}
/*the method that reads the file into the list into the char array of each node and returns the head of the list */
struct Node *readstl(char *path)/*!!!problem!!!*/
{
FILE *fptr;
int i, len;
struct Node *head;
head = (struct Node *)malloc(sizeof(struct Node));
fptr = fopen("readstrtofile.tmp", "w");
if (fptr == NULL) {
printf("error - failed to open file\n");
exit(0);
return NULL;
}
len = strlen(path);
for (i = 0; i < len && fputc(*(path + i), fptr) != EOF; i++);
if (ferror(fptr))/*checking if the loop ended for the right reason*/
{
printf("error - failed to read into file\nthis is what we got so far\n");
}
fclose(fptr);
head = readFile("readstrtofile.tmp");
remove("readstrtofile.tmp");
return head;
}
/*a method that prints the recieved list depending on the list to have the equal length rows.
as specified in mmn 12 tab creating uneven rows is acceptable therefor when ever there is tab in the file
the rows will appear uneven as to tab takes a place of one char but prints to 8 blank spaces in ubuntu */
void printList(struct Node *head)
{
struct Node *curr;
curr = (struct Node *)malloc(sizeof(struct Node));
if (head == NULL) {
printf("empty list\n");
return;
}
if (curr==NULL) {
printf("memory allocation failed\n");
return;
}
printf("this is the list printed nicely\n");
curr = head;
printf("%s\n", curr->ptr);
while (curr->next != NULL) {
curr = curr->next;
printf("%s\n", curr->ptr);
}
printf("\n/********************/\n");
}
/* a method that creates a new file named path and prints a list to it */
void printListToFile(char *path,struct Node *head)/*!!!problem!!!*/
{
struct Node *curr;
char c;
int i;
FILE *fptr;
curr = (struct Node *)malloc(sizeof(struct Node));
if (curr == NULL) {
printf("memory allocation failed\n");
exit(0);
}
curr = head;
fptr = fopen(path, "w+");
if (fptr == NULL) {
printf("error - failed to open file\n");
exit(0);
}
if (head == NULL) {
printf("empty list\n");
exit(0);
}
printf("this is the file %s printed nicely\n",path);
curr = head;
while (curr->next != NULL) {
printf("new node -> ptr -> %s\n",curr->ptr);
/*if(sizeof(curr->ptr)/sizeof(char)<=NICE)
{*/
for(i=0;i<NICE && (c = fputc(curr->ptr[i],fptr)) != EOF;i++);
printf("puting %s to file %s\n",curr->ptr,path);
curr = curr->next;
printf("bolili\n");
/*}
else
{
printf("lilibo\n");
break;
}*/
}
printf("\n/********************/\n");
}
/* a method that recievs a string turns it into a list and inserts it into another list */
void insertToList(struct Node *node, char *str)
{
struct Node *tail, *head;
tail = (struct Node *)malloc(sizeof(struct Node));
head = (struct Node *)malloc(sizeof(struct Node));
if (tail == NULL || head == NULL) {
printf("memory allocation failed\n");
return;
}
head = readstl(str);/*reading the string to a node*/
printList(head);
printf("\n/***********in insert*********/\n");
tail = head;
while (tail->next) {
tail = tail->next;
}/*getting tto the last node to connect it*/
strcpy(tail->ptr, node->next->ptr);/*connecting the lists*/
tail->next = node->next->next;
strcpy(node->ptr, head->ptr);
node->next = head->next;
printf("inserted string successfully\n");
}
/* a method that returns the size of the list*/
unsigned int sizeOfList(struct Node *head)
{
struct Node *tmp;
int size;
if (!(head))
return 0;
size = 1;
tmp = (struct Node *)malloc(sizeof(struct Node));
tmp = head;
while ((tmp = tmp->next))
size++;
return size;
}
header file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NICE 80
#define debug "\n/****************/\n"
/*the node structure of a the list which contains a string the size we choose is nice
to print by and a pointer to the next node in the list. */
struct Node {
char ptr[NICE];
struct Node *next;
};
/*makeNode - a method that returns a newely created node and sets all values to NULL values.*/
struct Node *makeNode();
/*makeFullNode - a method that return a newely created node with values set to params as listed below.
#param Next - tho ptr to the next node desired.
#param Ptr - the string that will go into the node ptr.*/
struct Node *makeFullNode(struct Node *Next, char *Ptr);
/*readFile - a method that reads a file into a linked list returning the head to that list.
it reads the file using fgets and a const to decide what size the node strings should be.
#param path - the name of the file to open.
#return the head of the list.*/
struct Node *readFile(char *path);
/*readstl - a method that reads a string into a linked list returning the head to that list.
it prints the list to a tmp file then reads the file using readFile.
#param path - the string to read.
#return the head of the list.*/
struct Node *readstl(char*);
/*printList - a method that prints the list to stdout.
it goes in loop on the nodes each time printing the node->ptr.
#param head - the head of the linked list.*/
void printList(struct Node *head);
/*insertToList - a method that inserts a string into list.
it creates a new list using readstl the connects the nodes using the basic method.
#param node - the node to override.
#param str - the string to insert.*/
void insertToList(struct Node *node, char *str);
/*a method that prints the list to stdout.
it goes in loop on the nodes each time printing the node->ptr.
#param head - the head of the linked list.*/
void printListToFile(char *path,struct Node *head);
/*sizeOfList - a method that returns how many node are in the list.
it goes in a while loop incresing counter by 1 each iteration.
#param head - the head of the list to measure.
#return the size of the list.*/
unsigned int sizeOfList(struct Node *head);
I think it is this line:
for(i=0;i<NICE && (c = fputc(curr->ptr[i],fptr)) != EOF;i++);
Why would fputc ever return EOF if everything goes right? It will try to write characters behind the ptr array. From the manpage of fputc:
fputc(), putc() and putchar() return the character written as an unsigned char cast to an int or EOF on error.
This means, your loop writes as long as fputc doesn't return an error code. But what you probably want, is writing either 80 (NICE is not a nice constant name) or strlen(curr->ptr) characters. Assuming based on your readFile function, you want both things as a limit. I would recommend rewriting this line as:
int len = strnlen(curr->ptr, 80);
if (fwrite(curr->ptr, 1, len, fptr) < 0) {
printf("error writing file");
}
or if the string is always null terminated:
if (fputs(curr->ptr, fptr) < 0) {
printf("error writing file");
}
Also ptr is not a good name for an array. It might confuse people or even you after some time, trying to understand the code. A better name would be value or text (even arr would be better, because it is not a pointer).
In readFile you have a loop in which you read a line and put it in curr->ptr and then create a new curr and link it to the previous curr.
This creates an extra empty curr at the end of the list which you don't need and so you free it later. Unfortunately, the next pointer of the previous node is still pointing at the empty node you just freed.
The easiest way to fix this without restructuring the loop a bit is to keep a record of the previous node, something like this:
struct Node* prev = NULL;
while (fgets(curr->ptr, NICE, fptr))/*if fgets returns NULL it means that we either reached EOF or error, both a reason to end the loop*/
{
curr->next = makeNode();
prev = curr;
curr = curr->next;
}
free(curr);
if (prev != NULL)
{
prev->next = NULL;
}
else
{
head = NULL; // For the empty file case. head == curr in this case
}
// The other clean up stuff
So I am using an insertion sort to sort a data file of words alphabetically.
Example data file:
Ryan
John
Casey
....
Etc
When I get to line 83. printList(head); I get blank lines of data where my correct data should be.
This was originally used for integers but decided to switch it to strings to practice for my upcoming final.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/* Link list node */
struct Node
{
char data[10];
struct Node* next;
};
void sortedInsert(struct Node** head_ref, struct Node* new_node)
{
struct Node* current;
/* Special case for the head end */
if (*head_ref == NULL || (*head_ref)->data >= new_node->data)
{
new_node->next = *head_ref;
*head_ref = new_node;
}
else
{
/* Locate the node before the point of insertion */
current = *head_ref;
while (current->next!=NULL &&
current->next->data < new_node->data)
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
}
/* A utility function to create a new node */
struct Node *newNode(char new_data[])
{
/* allocate node */
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
/* put in the data */
new_node->data == new_data;
new_node->next = NULL;
return new_node;
}
/* Function to print linked list */
void printList(struct Node *head)
{
struct Node *temp = head;
while(temp != NULL)
{
printf("%s\n", temp->data);
temp = temp->next;
}
}
/* Drier program to test count function*/
int main()
{
char word[10];
/* Start with the empty list */
struct Node* head = NULL;
FILE *data;
if((data = fopen("./hw11.data","r"))==NULL){
printf("error-hw11.data could not be opened.\n");
return 0;
}
//insert words into linked list
while(1){
if(feof(data)) break;
fgets(word,10,data);
printf("%s\n",word);
struct Node *new_node = newNode(word);
sortedInsert(&head,new_node);
}
printf("\n Created Linked List\n");
printList(head);
return 0;
}
instead of assignment = , you are using == operator in newNOde()
struct Node *newNode(char new_data[])
{
/* allocate node */
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
/* put in the data */
new_node->data == new_data; // **it should = (single) NOT == to assign**
new_node->next = NULL;
return new_node;
}
I have a linked list where each node stores a word and a number. I can add nodes at the top of the list (push), at the center of the list (insertAfter) and at the end of the list (append). I now added a function to delete nodes, where it will take a char, it will search that char through the list and delete the node that stores that char.
The problem is that deleteNode will work with a normal node added at the top of the list, but when i append a node at the end or add it at the middle of the list it won't work.
Tl;dr deleteNode works with nodes created with push but not with nodes created with append or insertAfter.
The error i get is segmentation fault, so i don't have a specific error from the compiler. I'm trying to debug it by running different parts of the code but i still can't find the problem.
struct Node
{
int data;
char *word;
struct Node *next;
};
void push(struct Node** head_ref, int new_data, char *new_word)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->word= malloc(strlen(new_word));
strcpy(new_node->word, new_word);
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
/* Given a node prev_node, insert a new node after the given
prev_node */
void insertAfter(struct Node* prev_node, int new_data, char *new_word)
{
if (prev_node == NULL)
{
printf("the given previous node cannot be NULL");
return;
}
struct Node* new_node =(struct Node*) malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->word= malloc(strlen(new_word));
strcpy(new_node->word, new_word);
new_node->next = prev_node->next;
prev_node->next = new_node;
}
void append(struct Node** head_ref, int new_data, char *new_word)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
struct Node *last = *head_ref;
new_node->data = new_data;
new_node->word= malloc(strlen(new_word));
strcpy(new_node->word, new_word);
new_node->next = NULL;
if (*head_ref == NULL)
{
*head_ref = new_node;
return;
}
while (last->next != NULL)
last = last->next;
last->next = new_node;
return;
}
void deleteNode(struct Node **head_ref, char *word)
{
struct Node* temp = *head_ref, *prev;
if (strcmp(word, (*head_ref)->word)==0)
{
*head_ref = temp->next; // Changed head
free(temp); // free old head
return;
}
while (strcmp(word, (*head_ref)->word)!=0)
{
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp); // Free memory
}
This part looks strange:
while (strcmp(word, (*head_ref)->word)!=0)
{
prev = temp;
temp = temp->next;
}
In the strcmp you use head_ref but in the body you update temp to move to the next element.
Did you intend to do:
while (strcmp(word, temp->word)!=0)
{
prev = temp;
temp = temp->next;
}
Further there should probably some check for temp being NULL. Like:
while (temp && strcmp(word, temp->word)!=0)
Apart from what was stated by #4386427, you are not allocating enough space for your strings there:
new_node->word= malloc(strlen(new_word));
Notice that the C library function size_t strlen(const char *str) computes the length of the string str up to, but not including the terminating null character. So i would rather suggest:
new_node->word= malloc(strlen(new_word) + 1);
new_node->word[strlen(new_word)] = '\0';
This can cause you some problems with the memory. ;)
Or event better, use calloc, so the second line will be unnecessary:
new_node->word= calloc(strlen(new_word) + 1, sizeof(char));
The answers you have are OK, but just for the record, after enough practice it should look kinda like this:
void deleteNode(struct Node **pplist, char *word)
{
for (struct Node *n = *pplist; n; n=*(pplist = &(n->next)))
{
if (!strcmp(n->word,word))
{
*ppnode = n->next;
free(n->word);
free(n);
break;
}
}
}
The point is that you can just move the pointer to the node pointer through the list instead of treating the head as a special case.
Similarly, you can do append like this:
void append(struct Node** pplist, int new_data, char *new_word)
{
for(; *pplist; pplist=&((*pplist)->next));
push(pplist, new_data, new_word);
}
and insert_after(prev... is just push(&(prev->next)...
I am writing a program to insert data to linked list and print it.
LinkedList.c
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
struct node
{
char *data;
struct node *next;
};
void insert(struct node** head_ref,char *new_data)
{
struct node* new_node = (struct node*) malloc(sizeof(struct node));
struct node *last = *head_ref;
strcpy(new_node->data,new_data);
new_node->next = NULL;
if (*head_ref == NULL)
{
*head_ref = new_node;//assigning head node
return;
}
while (last->next != NULL)
last = last->next;//this helps to traverse to last node
last->next = new_node;
return;
}
void printList(struct node *node)//function to print the linked list
{
while (node != NULL)
{
printf(" %s ", node->data);
node = node->next;
}
}
int main() {
int t;
char datas[1000];
scanf("%d",&t);
struct node* head=NULL;
int i;
for(i=0;i<t;i++)
{
scanf("%s",datas);//this data should be added into the linkedlist
insert(&head,datas);
}
printList(head);
return 0;
}
This program works well for integer but if i use character string instead it showing that there is no response on stdout
I have been trying to debug the code for more hours.
Your code gives undefined behavior.
Have a look at the documentation of strcpy().
Long story short, strcpy() requires the destination (your new_node->data) to be an allocated char array, but you have not allocated the data for it, and you are writing to an undefined (and unallocated) memory.
To overcome it, either allocate space dynamically for the new string (and don't forget to free it when a node is released), or make data a char[] instead of a char*.
In addition, just remember buffer overflow weakness. Since it seems like educational purpose code, just think about it - don't try to solve it, IMO.
You have missed memory allocation, try this:
void insert(struct node** head_ref,char *new_data)
{
struct node* new_node = (struct node*) malloc(sizeof(struct node));
struct node *last = *head_ref;
// you should allocate memory because you use data as char *
new_node->data = malloc(strlen(new_data)+1);
/* you can use new_node->data = strdup(new_data);
instead of new_node->data = malloc(strlen(new_data)); and strcpy(new_node->data,new_data);
because strdup allocate and copy string with exact size */
strcpy(new_node->data,new_data);
new_node->next = NULL;
if (*head_ref == NULL)
{
*head_ref = new_node;//assigning head node
return;
}
while (last->next != NULL)
last = last->next;//this helps to traverse to last node
last->next = new_node;
return;
}
I am currently figuring out the implementation of double linked list. As strange as it may sound, I want repetitive items added to my linked list.
I am adding newNode to the list in sorted order.
The below function does not add the repetitive nodes.
struct Node
{
char name[42];
struct Node *next;
struct Node *prev;
};
void addSorted(struct Node **head, struct Node *newNode)
{
struct Node* current;
// Special case for the head end
if ((*head == NULL) || strcmp((*head)->name, newNode->name) >= 0)
{
newNode->next = *head;
*head = newNode;
}
else
{
// Locate the Node before the point of insertion
current = *head;
while (current->next != NULL &&
strcmp(current->next->name, newNode->name) <= 0)
{
current = current->next;
}
newNode->next = current->next;
current->next = newNode;
}
}
struct Node* GetNewNode(char *name)
{
struct Node* newNode = malloc(sizeof (struct Node));
strcpy(newNode->name, name);
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
int main(void)
{
// Some Irrelevant Code
if (strncmp(operator, "a", 1) == 0)
{
temp = GetNewNode(name);
addSorted(&head, temp);
}
}
I think the main point is that you have not taken care of the prev pointer and also for the first if, there should be two cases,
if(*head==NULL)
{
*head=newNode;
}
else if(strcmp((*head)->name, newNode->name) >= 0)
{
(*head)->prev=newNode;//ADD THIS LINE
newNode->next = *head;
*head = newNode;
}
In the else condition make the following changes
newNode->next = current->next;
current->next->prev = newNode;//CHANGE HERE
current->next=newNode;//ADD THIS LINE
newNode->prev=current;//ADD THIS LINE
In addition to manager the prev pointer as already discussed, there are some additional areas where you are asking for trouble. First it is wise to use a define to set the size of your static name array (this will become a necessity to validate the size of name):
#define MAXN
struct Node
{
char name[MAXN]; /* use a define for static allocation size */
struct Node *next;
struct Node *prev;
};
This feeds into two issues in GetNewNode. First you need to validate your memory allocation:
struct Node* newNode = malloc(sizeof (struct Node));
if (!newNode) { /* validate all memory allocations */
fprintf (stderr, "%s() memory allocation failed.\n", __func__);
exit (EXIT_FAILURE);
}
You then must also validate the length of name to prevent writing beyond the end of your array if name > 41 chars:
size_t namelen = strlen (name);
if ( namelen > MAXN - 1) { /* validate string length */
fprintf (stderr, "%s() name length (%zu) exceeds %d .\n",
__func__, namelen, MAXN);
return NULL;
}
Note: by using a define to set the length of name, the define MAXL is available to you as your length validation test.
Next, in GetNewNode you validate the length of name and returned NULL -- you must now handle the return in main() along with providing a declaration for head:
int main (void)
{
struct Node *head = NULL; /* head must be declared */
if (strncmp(operator, "a", 1) == 0)
{
temp = GetNewNode(name);
if (temp) /* validate return */
addSorted(&head, temp);
}
}
If your intent was to create a circular-list then you have several additional conditions you must test for and respond appropriately to in addSorted. Specifically, you must (1) create the list when *head = NULL.
If your earlier statement newNode->next = *head; *head = newNode; was correct, you must then (2) account for the condition when the list is self-referencial (i.e. only one-node present that refers to itself).
You then have two more conditions to test (3) whether newNode->name sorts before the current (*head)->name where you must insert newNode as the new first node in the list; and finally (4) the case where newNode->name sorts after the current (*head)->name.
Even with a linear head/tail list with you will need to address both (3) & (4) above. Let me know if you have further questions.
With a doubly linked list, it is best to first find the spot where you need to insert it.
// pseudo code
current = head;
while (current)
{
if ( strcmp( name, current -> name) ... ) // your logic for your sort order
{
}
current = current->next;
}
Once you find the spot to insert, you have one four cases to deal with when you want to insert an item into the into the list. You have to handle head/tail changing as well as pointing inward and outward or to null as needed.
Add to a completely empty list (head and tail point to the record, prev and next are null)
Add to the front (head gets a new value, new record prev is null,)
Add to end ( tail gets a new value, new record next is null)
Add to middle ( head/tail unchanged )