Doubly linked list in C- delete node function - c

Doubly linked list nodes are created at the main function. Ender and header defined. Breaks at the delete node function- ender is null.
What's the best way to free the memory of the last and first input, i.e.: delete: 233,A and 888,F?
#include <stdafx.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
typedef struct record {
int idnumber;
char initial;
struct record *prevStudent;
struct record *nextStudent;
} STUDENT;
STUDENT *header = NULL; //pointer to the start of linked list
STUDENT *ender = NULL; //pointer to the end of the linked list
void Makenode(int x, char y);
void deletenode();
int main() {
Makenode(233, 'A');
Makenode(456, 'H');
Makenode(746, 'G');
Makenode(888, 'F');
deletenode();
fflush(stdin);
getchar();
return 0;
}
void Makenode(int x, char y) {
STUDENT *ptr;
ptr = (STUDENT *)malloc(sizeof(STUDENT));
if (ptr != NULL) {
ptr->idnumber = x;
ptr->initial = y;
ptr->nextStudent = header;
ptr->prevStudent = NULL;
if (header == NULL)
ender = ptr;
else
header->prevStudent = ptr;
header = ptr;
} else {
printf("Memory not allocated\n");
}
}
void deletenode() {
//delete the first and the last node of the linked list
STUDENT *p = header, *q = ender;
char c;
printf("Are you sure you want to delete Y/N:\n");
fflush(stdin); c=getchar();
while (c == 'Y' || c == 'y') {
ender=ender->nextStudent;
header=header->prevStudent;
free(p); free(q);
}
}

Your delete function leaves the linked list in an ilegal state. At all times (except temporarily inside your insert and delete functions), the following must be true:
If the header is null, the ender must also be null and the list is empty.
If a node p has a non-null link to p->next, then p->next->prev == p.
Likewise, if a node p has a non-null link to p->prev, then p->prev->next == p.
The header has no previous node; the ender has no next node.
These are the invariants of your linked list.
If you check your code for deleting:
void deletenode()
{
STUDENT *p = header, *q = ender;
ender=ender->nextStudent;
header=header->prevStudent;
free(p); free(q);
}
you can see that you just set the header and ender to NULL, because that's what ender->nextStudent and header->prevStudent are. But even reversing that won't help, because you must update the adjacent nodes' links.
Here are two functions - one for each task - that work:
void delete_first()
{
STUDENT *p = header;
if (p) {
if (p->nextStudent == NULL) {
header = ender = NULL;
} else {
p->nextStudent->prevStudent = NULL;
header = p->nextStudent;
}
free(p);
}
}
void delete_last()
{
STUDENT *p = ender;
if (p) {
if (p->prevStudent == NULL) {
header = ender = NULL;
} else {
p->prevStudent->nextStudent = NULL;
ender = p->prevStudent;
}
free(p);
}
}

Related

Can you tell me why my function to select a random string from a linked list isn't working?

I am building a program for a project. One of the requirements for the project is a function that selects a random node from my linked list of 3000 words.
I tried to do this by creating a function that generates a random number from 0 to 2999. After this, I created another function that follows a for loop starting from the head and moving to the next node (random number) times.
My random number generator is working fine, but my chooseRand() function is not.
Please help, the random number generator and the chooseRand() function are the last two functions above main. Also, my code is a bit messy, sorry.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int nodeNum;
int chances;
char* secret;
/*Node of linked list*/
typedef struct node {
char *data;
struct node *next;
} node;
node *start = NULL;
node *current;
/*Void function to print list*/
void printList(struct node *node)
{
while (node != NULL) {
printf("%s ", node->data);
node = node->next;
}
}
/*Appending nodes to linked list*/
void add(char *line) {
node *temp = malloc(sizeof(node));
temp->data = strdup(line);
temp->next = NULL;
current = start;
if(start == NULL) {
start = temp;
} else {
while(current->next != NULL) {
current = current->next;
}
current->next = temp;
}
}
void readfile(char *filename) {
FILE *file = fopen(filename, "r");
if(file == NULL) {
exit(1);
}
char buffer[512];
while(fgets(buffer, sizeof(buffer), file) != NULL) {
add(buffer);
}
fclose(file);
}
node *listSearch(node* start, char *nodeSearched){
node *p;
for (p = start; p != NULL; p = p->next)
if (strcmp(p->data, nodeSearched) == 0)
printf("%s", p->data);
return NULL;
}
node *letterSearch(node* start, int i){
node *p;
for (p = start; p != NULL; p = p->next)
if (strlen(p->data) == i)
{
printf("\n %s", p->data);
free(p);
p = NULL;
}
return NULL;
}
void chooseRand(struct node* start)
{
node* p;
int n;
p = start;
for(n = 0; n != nodeNum; n++)
{
p = p->next;
}
printf("%s", p->data);
}
void randNum(int lower, int upper)
{
srand(time(0));
nodeNum = (rand() % (upper - lower + 1)) + lower;
}
int main(){
randNum(0, 2999);
chooseRand(start);
return 0;
}
As others has said, the problem is that you don't have initialized the linked list yet, because of what your are getting a segmentation fault. So, in addition to initializing the list first, you must also introduce checks in the implementation of the chooseRand function, to check that if you reach the end of the list, without reaching the desired index, you stop executing the foor loop, otherwise you will be potentially exposed to segmentation faults.
Improve chooseRand implementation, to prevent segmentation fault either, when the linked list is empty, or when the randomly generated nodeNum is grater than the the index of the list's last item:
void chooseRand(struct node* start)
{
node* p;
int n;
p = start;
if(p == NULL){
printf("The list is empty!");
return;
}
// Also, we must stop the iteration, if we are going to pass the end of the list, you don't want a segmentation fault because trying to access a NULL pointer:
for(n = 0; n != nodeNum && p->next != NULL; n++)
{
p = p->next;
}
// If p == NULL, the list was not big enough to grab an item in the `nodeNum` index:
printf("%s", (n != nodeNum) ? "Not found!" : p->data);
}
Initialize the linked list, with the content of some file on disk:
int main(){
randNum(0, 2999);
// Fill the linked list with the content of a file in disk, calling your method:
char fileName[] = "PutYourFileNameHere.txt";
readfile(fileName);
chooseRand(start);
return 0;
}
There is another fix that you must do, and it is free the memory being hold by the pointer field data of your structure, in the implementation of your method letterSearch. Inside the if statement, you're de-allocating the memory hold by the p pointer, but you aren't de-allocating the memory assigned to the pointer p->data, this will cause a memory leak. When you in the function add, initialized p->data with the result of the call to the function strdup(line), what this function does is allocate enough memory in the heap, copies to it the buffer pointed by the line argument, and give to you back a pointer to the new allocated memory, that you're storing in the p.data field; a pointer that you should free when you're done with it, otherwise your program will have potential memory leaks. So I will modify your function letterSearch as folollows:
node *letterSearch(node* start, int i){
node *p;
for (p = start; p != NULL; p = p->next)
if (strlen(p->data) == i)
{
printf("\n %s", p->data);
// Free p->data before free p:
free(p->data);
free(p);
p = NULL;
}
return NULL;
}
References:
strdup

Linked list insertion doesn't work as expected

I'm writing a function that places new nodes alphabetically into a linked list structure by sorting them by the name field. Here is my program, intended to test that it can successfully insert a new node into an existing structure:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 100
#define MAX_JOB_LENGTH 100
struct Employee
{
/* Employee details */
char name[MAX_NAME_LENGTH+1]; /* name string */
char sex; /* sex identifier, either ’M’ or ’F’ */
int age; /* age */
char job[MAX_JOB_LENGTH+1]; /* job string */
/* pointers to previous and next employee structures in the linked list
(for if you use a linked list instead of an array) */
struct Employee *prev, *next;
};
void place_alpha(struct Employee *new, struct Employee **root);
int main(){
struct Employee *a;
struct Employee *c;
struct Employee *b;
a = malloc(sizeof(struct Employee));
c = malloc(sizeof(struct Employee));
b = malloc(sizeof(struct Employee));
strcpy(a->name, "A");
a->sex = 'F';
a->age = 42;
strcpy(a->job, "Optician");
a->prev = NULL;
a->next = c;
strcpy(c->name, "C");
c->sex = 'F';
c->age = 22;
strcpy(c->job, "Nurse");
c->prev = a;
c->next = NULL;
strcpy(b->name, "B");
b->sex = 'M';
b->age = 34;
strcpy(b->job, "Rockstar");
b->prev = NULL;
b->next = NULL;
place_alpha(b, &a);
if(a->prev == NULL)
{
printf("a->prev is correct\n");
}else{
printf("a->prev is INCORRECT\n");
}
if(a->next == b)
{
printf("a->next is correct\n");
}else{
printf("a->next is INCORRECT");
}
if(b->prev == a)
{
printf("b->prev is correct\n");
}else{
printf("b->prev is INCORRECT\n");
}
if(b->next == c)
{
printf("b->next is correct\n");
}else{
printf("b->next is INCORRECT\n");
}
if(c->prev == b)
{
printf("c->prev is correct\n");
}else{
printf("c->prev is INCORRECT\n");
}
if(c->next == NULL)
{
printf("c->next is correct\n");
}else{
printf("c->next is INCORRECT\n");
}
}
void place_alpha(struct Employee *new, struct Employee **root) //Places a new node new into the database structure whose root is root.
{
if(*root==NULL) //If there is no database yet.
{
*root = new;
(*root)->prev = NULL;
(*root)->next = NULL;
}
else
{
if(strcmp(new->name, (*root)->name)<=0) // if the new node comes before root alphabetically
{
new->next = *root;
new->prev = (*root)->prev;
if((*root)->prev != NULL)
{
(*root)->prev->next = new;
}
(*root)->prev = new;
*root = new;
return;
}
else if((*root)->next == NULL) // If the next node is NULL (we've reached the end of the database so new has to go here.
{
new->prev = *root;
new->next = NULL;
(*root)->next = new;
return;
}
else if(strcmp(new->name, (*root)->name)>0) // If the new node comes after root alphabetically
{
place_alpha(new, &(*root)->next);
return;
}
}
}
Sadly, the program is unsuccessful, as showcased by the output:
a->prev is correct
a->next is correct
b->prev is INCORRECT
b->next is correct
c->prev is INCORRECT
c->next is correct
Program ended with exit code: 0
I can't figure out why, as I've clearly set b->next to c and c->prev to b.
This was tricky: there is a subtile bug in your place_alpha() function: you update *root even if it is not the root node of the list. This causes the pointer b to be updated erroneously. place_alpha() should only be called with a pointer to the actual root node.
I modified your code to make it more readable and reliable:
I wrote a function to create a new node
I protected the string copies from overflow using calloc() and strncat(). Read about these functions in the manual.
I use place_alpha() to insert all 3 nodes into the list in the same order you do.
I use newp instead of new to avoid C++ keywords in C code.
Note that place_alpha() must be called with a pointer to the head pointer of the list, if you pass a pointer to an intermediary node, chaining back along the prev links would locate the first node, but if the new employee should be inserted at the head of the list, you would not have the address of the root node to update in the caller's scope. This is the reason many programmers prefer to use a specific structure for the list head.
Here is the updated code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 100
#define MAX_JOB_LENGTH 100
struct Employee {
/* Employee details */
char name[MAX_NAME_LENGTH + 1]; /* name string */
char sex; /* sex identifier, either 'M' or 'F' */
int age; /* age */
char job[MAX_JOB_LENGTH + 1]; /* job string */
/* pointers to previous and next employee structures in the linked list
(for if you use a linked list instead of an array) */
struct Employee *prev, *next;
};
void place_alpha(struct Employee *new, struct Employee **root);
struct Employee *new_employee(const char *name, char sex, int age, const char *job) {
struct Employee *newp = calloc(1, sizeof(*newp));
if (!newp) {
fprintf(stderr, "cannot allocate employee\n");
exit(1);
}
strncat(newp->name, name, MAX_NAME_LENGTH);
newp->sex = sex;
newp->age = age;
strncat(newp->job, job, MAX_JOB_LENGTH);
newp->next = newp->prev = NULL;
return newp;
}
int main(void) {
struct Employee *list = NULL;
struct Employee *a = new_employee("A", 'F', 42, "Optician");
struct Employee *b = new_employee("B", 'M', 34, "Rockstar");
struct Employee *c = new_employee("C", 'F', 22, "Nurse");
place_alpha(a, &list);
place_alpha(c, &list);
place_alpha(b, &list);
if (a->prev == NULL) {
printf("a->prev is correct\n");
} else {
printf("a->prev is INCORRECT\n");
}
if (a->next == b) {
printf("a->next is correct\n");
} else {
printf("a->next is INCORRECT");
}
if (b->prev == a) {
printf("b->prev is correct\n");
} else {
printf("b->prev is INCORRECT\n");
}
if (b->next == c) {
printf("b->next is correct\n");
} else {
printf("b->next is INCORRECT\n");
}
if (c->prev == b) {
printf("c->prev is correct\n");
} else {
printf("c->prev is INCORRECT\n");
}
if (c->next == NULL) {
printf("c->next is correct\n");
} else {
printf("c->next is INCORRECT\n");
}
return 0;
}
void place_alpha(struct Employee *newp, struct Employee **root) {
// Insert a new node newp into the database structure whose root is root.
struct Employee *ep;
if (*root == NULL) { // if there is no database yet.
newp->next = newp->prev = NULL;
*root = newp;
return;
}
if ((*root)->prev) {
// invalid call, should only pass the root node address
fprintf(stderr, "invalid call: place_alpha must take a pointer to the root node\n");
return;
}
if (strcmp(newp->name, (*root)->name) <= 0) {
// if the new node comes before root alphabetically
newp->next = *root;
newp->prev = NULL;
newp->next->prev = newp;
*root = newp;
return;
}
for (ep = *root;; ep = ep->next) {
if (ep->next == NULL) {
// If the next node is NULL, we've reached the end of the list
// so newp has to go here.
newp->prev = ep;
newp->next = NULL;
newp->prev->next = newp;
return;
}
if (strcmp(newp->name, ep->next->name) <= 0) {
// The new node comes between ep and ep->next alphabetically
newp->prev = ep;
newp->next = ep->next;
newp->prev->next = newp->next->prev = newp;
return;
}
}
}
EDIT: place_alpha was a bit redundant, so I cleaned it and got a much simpler version:
void place_alpha(struct Employee *newp, struct Employee **root) {
//Places a new node newp into the database structure whose root is root.
struct Employee **link = root;
struct Employee *last = NULL;
while (*link && strcmp(newp->name, (*link)->name) > 0) {
last = *link;
link = &last->next;
}
newp->prev = last;
newp->next = *link;
if (newp->next) {
newp->next->prev = newp;
}
*link = newp;
}

Array of linked lists added to from directory

I've been trying to create an array of linked lists. The array being size 26 each part corresponding to a letter of the alphabet. The user inputs a directory of the PC and the name of any folders or files in that directory are then added to the a linked list in the array based on what letter they start with.
How i've been trying to do it->
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
My node and its declaration:
struct node{
char data[50];
struct node *next;
};
struct node* nodeArray[26];
My alphabet:
const char* basis[26] = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
A string comparing function to check which linkedlist in the array my word goes(compares to alphabet)
int StartsWith(const char *a, const char *b)
{
if(strncasecmp(a, b, strlen(b)) == 0) return 1;
return 0;
}
Where I add the node and also where the problem is(the printf("1") is there to stop my computer from basically crashing):
void addNode(struct node **q,const char *d){
if(((*q)->data)==NULL){
*q = malloc(sizeof(struct node));
strncpy((*q)->data,d,50);
(*q)->next = NULL;
} else {
(*q)->next = malloc(sizeof(struct node));
*q = (*q)->next;
printf("1");
addNode(q,d);
}
}
The function that calls addNode, directory is a computer directory that's already been checked to exist:
void returner(char* directory){
int i;
DIR *dp;
struct dirent *ep;
char* tempD;
dp = opendir (directory);
struct node **z;
while ((ep = readdir(dp))){
tempD = (char*)malloc(50);
if ( !strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..") ){
} else {
strncpy(tempD, ep->d_name, 50);
for(i=0; i<26 ; i++){
if(StartsWith(tempD, basis[i])){
z = &nodeArray[i];
addNode(z,tempD);
print();
}
}
}
free(tempD);
}
closedir (dp);
}
Print function:
void print(){
int i;
struct node *temp;
for(i=0 ; i < 26; i++){
temp = malloc(sizeof(struct node));
temp = nodeArray[i];
while(temp != NULL){
printf("%s\n",temp->data);
temp = temp->next;
}
}
}
The program seems fine when adding the first node to a spot on the array such as "aaa.txt" "bbb.txt" "ccc.txt" "ddd.txt", but once a second is attempted to be added like a "ccd.txt" after a "ccc.txt" exists when it keeps going forever or until the pc crashes
You're not checking the right value in your addNode for finding the list insertion point.
Pointer-to-pointer enumeration through a linked list is frequently used to walk from the head pointer to the last next pointer in the list, each time holding the address of the said-pointer. When you reach one that is NULL (which will be head in the case of an empty list), you stop, and you can use your pointer-to-pointer via dereference to assign your new node address.
If you want to insert on the tail, the way to do it would be something like this:
#define DATA_MAX_LEN 50
void addNode(struct node **q,const char *d)
{
// assumes a null-terminated linked list
while (*q)
q = &(*q)->next;
*q = malloc( sizeof **q );
// ensures truncation and termination
strncpy((*q)->data,d,DATA_MAX_LEN-1);
(*q)->data[ DATA_MAX_LEN-1] = 0;
// make sure we terminate the list at our new node
(*q)->next = NULL;
}
Invoked from your updated returner function like this:
void returner(char* directory)
{
DIR *dp = opendir (directory);
if (dp)
{
struct dirent *ep;
while ((ep = readdir(dp)))
{
// skip parent and self symbolic links
if (ep->d_name[0] == '.' && (ep->d_name[1] == 0 || (ep->d_name[1] == '.' && ep->d_name[2] == 0)))
continue;
for(int i=0; i<26 ; i++)
{
if(StartsWith(ep->d_name, basis[i]))
addNode(nodeArray+i, ep->d_name);
}
}
closedir (dp);
}
}

Single linked list delete function with recursion in C

I am trying to make a students list for a project in c
the functions inside the program are 3
insert = inserts students to the list
print = prints out the students available
delete = deletes a student from the list
I have created the program and it works fine using all three functions
and now I would like to make the same list using recursion.
I have made the print function recursive and it is working
now I am trying to make the delete function work the same way
unfortunately I am failing to make it work
In the code below if you run it you will see that it works only if you do not attempt to delete the last node on the list and if you do not tell it to delete a node that it does not exists.
#include <stdio.h>
#include <stdlib.h>
typedef struct tf *tp;
struct tf{
int am;
double gr;
tp next;
};
tp head, tail, temp, aux;
void insert1 (tp *h, tp t);
void print1(tp h);
void delete1(tp *h,int da);
int main()
{
char fry, fry2;
int am;
fry = 'a';
head = NULL;
tail = NULL;
while (fry != 'q')
{
printf("\n character given is %c\n", fry);
if (fry != 'q')
{
printf("new choice\n");
fry = 'a';
fflush(stdin);
fry = getchar();
getchar();
if (fry == 'q')
printf("quit\n");
if (fry == 'i')
{
fry2 = fry;
printf(" insert new student number am\n");
insert1(&head,tail);
fry = fry2;
}
if (fry == 'd')
{printf(" delete \n");
printf(" am number of student to be deleted\n");
scanf("%d", &am);
delete1(&head,am);
}
if (fry == 'p')
{
printf("\n printing\n");
print1(head);
}
}
}
}
void insert1 (tp *h, tp t)
{
tp te, a;
int da;
te = (tp)malloc(sizeof(struct tf));
printf(" am number for the new insert\n");
scanf("%d", &da);
getchar();
te->am = da;
te->next = NULL;
printf("am number is %d",te->am);
if ((*h != NULL) && (te->am < (*h)->am))
{
te->next = *h;
*h = te;
}
if((*h != NULL) && ((*h)->next != NULL) && (te->am > (*h)->am))
{
a=*h;
while((a->next != NULL) && (a->next->am < te->am))
{
a= a->next;
}
te->next = a->next;
a->next = te;
}
if((*h != NULL) && ((*h)->next == NULL) && (te->am > (*h)->am))
{
(*h)->next = te;
}
if(*h == NULL)
{
printf("\n head is null");
*h = te;
t = te;
}
}
void print1(tp h)
{
tp a;
a=h;
if (a==NULL)
return;
printf("%d\n",a->am);
print1(a->next);
}
void delete1(tp *h,int da)
{
tp a= *h,t= *h,temp = NULL;
if ((*h) != NULL)
{
if ((*h)->am!=da)
{
if (a->next->am != da && a->next!=NULL)
{
delete1(a->next,da);
}
else
{
if (a->next==NULL)
{
printf("am not found\n");
return;
}
else
{
temp = a->next;
a->next = a->next->next;
free(temp);
}
}
}
else
{
a = (*h);
(*h)= (*h)->next;
free(a);
}
}
else
{
printf("empty list");
}
}
As you can see I want the delete function to delete the node by looking for the am number given,so it will first search the list to find if the am number is there or not.
If anyone can give me a tip on how to make the delete function to work I would be grateful.
There are several things going on. This line:
if (a->next->am != da && a->next!=NULL) ...
should have the conditions swapped, otherwise you might access a->next withot verifying that it isn't NULL first. The auxiliary variable a and the other temporaries are confusing rather than helpful.
You pass the head to the delete1 function as pointer to pointer, so that the head can be updated. But this doesn't affect only the head: This adds a level of indirection thoughout your iteration.
For your iterative calls, this means that you must pass the address of the pointer that stores the reference to the current node, (*h)->next. At the beginning, this is the address of the head. On subsequent iterations, this is the address of the next pointer of the previous node.
There's also no need to consider various cases. The code can be as simple as:
void delete1(tp *h, int da)
{
if (*h != NULL) {
if ((*h)->am == da) {
tp next = (*h)->next;
free(*h);
*h = next;
return;
}
delete1(&(*h)->next, da);
}
}
The recursive call happens at the end of the function or it doesn't happen at all. This means that you can rewrite the code as a loop:
void delete1(tp *h, int da)
{
while (*h != NULL) {
if ((*h)->am == da) {
tp next = (*h)->next;
free(*h);
*h = next;
return;
}
h = &(*h)->next;
}
}
This will save you some stack space on large lists. Your insert1 function could also be cleaned up and simplified.

Deleting items from a structure

I have the following linked list:
struct scoreentry_node {
struct scoreentry_node *next;
int score;
char name[1];
}
;
typedef struct scoreentry_node *score_entry;
I'm trying to write a function that removes all nodes that contain a certain name. Here is what I have so far but I'm not sure I'm right:
score_entry disqualify(score_entry a, char* name)
{
score_entry tmp = a;
while (tmp != NULL){
if (strcmp(tmp->name, name) == 0)
{
score_entry trash = tmp;
tmp = tmp->next;
free(trash);
}
else { tmp = tmp->next; }
}
return a;
}
It gives me heap error's .. Any suggestions?
score_entry disqualify(score_entry a, char* name)
{
score_entry new_front = a, tmp;
// delete "wrong" entries from the front
while (new_front != NULL){
if (strcmp(new_front->name, name) == 0)
{
score_entry trash = new_front;
new_front = new_front->next;
free(trash);
}
else
{
// first list entry is valid
// delete "wrong" entries from inside the list
tmp = new_front;
while ( tmp->next != NULL )
{
if ( strcmp(tmp->next->name,name)==0 )
{
score_entry trash = tmp->next;
tmp->next = tmp->next->next;
free(trash);
} else
{
tmp = tmp->next;
}
}
}
}
return new_front;
}
You should also obtain some book related to common data structures - you seem to be interested in the stuff, and it could be a great help for you.
If you delete a member from the list you must fix the gap this creates by linking the 'next' pointer of the previous entry to the following entry. The code below does that. Note that I have changed score_entry so that the typedef no longer contains the pointer - I prefer not to disguise types. Notice that the function returns the head which might have changed if we deleted the first entry in the list.
typedef struct scoreentry_node score_entry;
static score_entry *
disqualify(score_entry *head, const char *name)
{
score_entry *se = head;
score_entry *prev = head;
while (se) {
if (!strcmp(se->name, name)) {
score_entry *next = se->next;
if (head == se) {
head = next;
} else {
prev->next = next;
}
free(se);
se = next;
} else {
prev = se;
se = se->next;
}
}
return head;
}
You're using strcmp on a non-null-terminated string (tmp->name). I'm assuming it's not null-terminated as it's only of length 1. Seems like you're really comparing a character, not a string, so a simple character equality operator would be the right thing to do.

Resources