Given the following struct:
typedef struct node_t {
int x;
struct node_t *next;
} *Node;
Please Note: the definition above is given to me as is and can't be changed.
I wrote the following function:
inline int getMin(Node *list1,Node *list2)
{
int first_value=INT_MAX,second_value=INT_MAX;
if (*list1)
{
first_value=(*list1)->x;
}
if (*list2)
{
second_value=(*list2)->x;
}
if (first_value<second_value)
{
*list1=(*list1)->next;
return first_value;
}
*list2=(*list2)->next;
return second_value;
}
It receives 2 pointers to a series of Nodes while each node has two attributes: x and next (a pointer to the next code)
My code should get the minimum value when comparing the values of the current two nodes, while it works fine with 99% of the cases it doesn't work with the case where list1 points to a node that its value is INT_MAX and next points to null and list2 is NULL
how can I fix this?
I fixed this by changing the following code:
if (first_value<second_value) to
if (first_value<=second_value)
but I have a new problem:
list2 points to a node that its value is INT_MAX and next points to null and list1 is NULL
Edit: Here is the last version of my code:
helper functions:
int advance(Node *node) {
int node_value = (*node)->x;
*node = (*node)->next;
return node_value;
}
int getMin(Node *list1, Node *list2) {
assert(*list1 || *list2);
if (!(*list1)) {
return advance(list2);
}
if (!(*list2)) {
return advance(list1);
}
if ((*list1)->x < (*list2)->x) {
return advance(list1);
}
return advance(list2);
}
main function:
ErrorCode mergeSortedLists(Node list1, Node list2, Node *merged_out) {
if (!merged_out) {
return NULL_ARGUMENT;
}
if (!list1 || !list2) {
return EMPTY_LIST;
}
if (!isListSorted(list1) || !isListSorted(list2)) {
return UNSORTED_LIST;
}
Node ptr = *merged_out;
int total_len = getListLength(list1) + getListLength(list2);
for (int i = 0; i < total_len; i++) {
int min = getMin(&list1, &list2);
if (i != 0) {
ptr->next = malloc(sizeof(*ptr));
if (!ptr->next) {
destroyList(*merged_out);
return MEMORY_ERROR;
}
ptr = ptr->next;
}
ptr->x = min;
}
ptr->next = NULL;
return SUCCESS;
}
This is the classical merge sort code where you have four cases provided that not both lists are exhausted:
a is exhausted;
b is exhausted;
a < b and
a ≥ b.
You have tried to coalesce the two first cases where one of the nodes is null with the comparison, but because your lists can have INT_MAX as value, that solution isn't robust.
Write out these cases explicitly. First a little auxiliary function that advances a node and returns the value:
static int advance(Node *nd)
{
int res = (*nd)->x;
*nd = (*nd)->next;
return res;
}
Now your actual function is very simple:
int getMin(Node *list1, Node *list2)
{
assert(*list1 || *list2);
if (*list1 == NULL) return advance(list2);
if (*list2 == NULL) return advance(list1);
if ((*list1)->x < (*list2)->x) return advance(list1);
return advance(list2);
}
See it in action on ideone.
Related
For context, I'm a new programmer to C and I wanted to make a toy implementation of a dictionary/map from a 'Person' struct to an integer. I'm using separate chaining, so I have a hash table of linked list pointers.
So far, I've been able to add one value to the linked list just fine, but when I call the function to get the value for the Person key I'm using, the memory at one of my nodes seems to get overwritten.
More info if it's helpful, using a singly linked list with one sentinel node at the head and a tail reference.
New to StackOverflow, so I can't actually embed the image, but pictured on left is the HashTable at the beginning of the function call, when nothing has been changed. The relevant stuff is the expanded part of the Variables menu, which shows that at position 58 is a pointer to 0x61f8e0, the linked list. The linked list has a head pointer to 0x61f760, which is the sentinel value, and a tail pointer to 0x61f864, currently pointing to a Node with the value (3) for a Person named Robert who's 36 years old. The tail pointer's next field points to 0x0 (not pictured), like intended. The picture follows: https://i.stack.imgur.com/F9EJ9.png
This is what happens as soon as the first statement (which hashes the Person pointer very naively) is executed: https://i.stack.imgur.com/UJvGy.png. As you'll see, the value is now some random long number, the intrinsic age is now 1 instead of 36, the saved name is now gibberish, and worst of all the next pointer now points somewhere completely random (0x61fb10).
The function in question follows.
int tableGet(HashTable t, Person key) {
int position = hash(&key) % 100;
List* listLoc = t.table[position];
if ((int) listLoc == 0) {
return -1;
}
Node curr = *(listLoc -> head);
while (curr.next != NULL) {
if (curr.savedAge == key.age && curr.savedName == key.name) {
return curr.val;
}
curr = *curr.next;
}
return -1;
}
Here is the hash function, in case that's what's causing the problems.
int hash(Person* p) {
int sum;
Person person = *p;
int i = 0;
char nameChar = person.name[i];
while (nameChar != '\0'){
sum += (int) nameChar;
i += 1;
nameChar = person.name[i];
}
return (int) (person.age + sum);
}
And just because why not, here's all of the short amount of code I've written for this.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdbool.h>
typedef struct Node {
int val;
int savedAge;
char savedName[100];
struct Node* next;
} Node;
typedef struct {
int age;
char name[100];
} Person;
typedef struct {
Node* head;
Node* tail;
} List;
typedef struct {
List* table[100];
} HashTable;
int hash(Person*);
Person person(int age, char name[]) {
Person p;
p.age = age;
strcpy(p.name, name);
return p;
}
Node node(int val, Person p, Node* next) {
Node n;
n.val = val;
strcpy(n.savedName, p.name);
n.savedAge = p.age;
n.next = next;
return n;
}
List list() {
List l;
Node head = node(-1, person(0, "SENTINEL"), NULL);
l.head = &head;
l.tail = l.head;
return l;
}
void listAdd(List* l, Node n) {
Node* newTailPtr = &n;
l -> tail -> next = newTailPtr;
l -> tail = newTailPtr;
}
HashTable table() {
int table[100] = {0};
HashTable t;
memcpy(t.table, table, sizeof table);
return t;
}
HashTable tableAdd(HashTable t, Person key, int val) {
int num = hash(&key) % 100;
List* loc = t.table[num];
if ((int) loc == 0) {
List newList = list();
t.table[num] = &newList;
}
listAdd((List*) t.table[num], node(val, key, NULL));
return t;
}
int tableGet(HashTable t, Person key) {
int position = hash(&key) % 100;
List* listLoc = t.table[position];
if ((int) listLoc == 0) {
return -1;
}
Node curr = *(listLoc -> head);
while (curr.next != NULL) {
if (curr.savedAge == key.age && curr.savedName == key.name) {
return curr.val;
}
curr = *curr.next;
}
return -1;
}
int hash(Person* p) {
int sum;
Person person = *p;
int i = 0;
char nameChar = person.name[i];
while (nameChar != '\0'){
sum += (int) nameChar;
i += 1;
nameChar = person.name[i];
}
return (int) (person.age + sum);
}
int main() {
Person bob = person(36, "Robert");
printf(bob.name);
printf("\n");
HashTable tab = table();
tab = tableAdd(tab, bob, 3);
printf("Added Robert to table as 3\n");
int val = tableGet(tab, bob);
if (val == 3) {
printf("Success!\n");
} else {
printf("Failure, val is %d\n", val);
}
return 0;
}
I'm new to C and I'm stuck with the insert function in a linked list. When I try printing the list. The result isn't what I expect. I know it has something to do with pointers but I just can't get my head around it. What am I doing wrong here?
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
typedef struct CELL_NODE CellNode;
struct CELL_NODE {
int row;
int column;
CellNode *next;
};
struct LinkedList {
CellNode *head;
};
typedef struct LinkedList LinkedList;
void printList(LinkedList *myList) {
CellNode *curr = (*myList).head;
if (curr != NULL) {
printf("(%d,%d)", (*curr).row, (*curr).column);
if ((*curr).next != NULL) {
curr = (*curr).next;
printf(" - (%d,%d)", (*curr).row, (*curr).column);
}
} else {
printf("The list is empty");
}
printf("\n");
}
void insert(LinkedList *myList, CellNode *node) {
CellNode *ref = (*myList).head;
if (ref == NULL) {
(*myList).head = node;
} else {
while ((*ref).next != NULL) {
ref = (*ref).next;
}
(*ref).next = node;
}
}
int main(int argc, char *argv[]) {
LinkedList myList = { NULL };
for (int k = 0; k < 2; k++) {
CellNode myNode = { 1, k, NULL };
insert(&myList, &myNode);
printList(&myList);
printf("\n");
}
return 1;
}
The result I get is:
(1,0)
(1,1) - (1,1)
I'm expecting:
(1,0)
(1,0) - (1,1)
You should first change every instance of (*x).y to x->y to make your code much more readable.
Then, look at this code:
int main(int argc, char *argv[])
{
LinkedList myList = {NULL};
for(int k = 0 ; k<2 ; k++) {
CellNode myNode = {1,k,NULL};
insert(&myList,&myNode);
printList(&myList);
printf("\n");
}
return 1;
}
You create myNode as a local variable inside the for loop. That means that each iteration of the loop gets a new instance of myNode, destroying the previous one. So you've connected myNode to your linked list through pointers, and then you let it get destroyed the next time through the for loop.
If you're going to let some piece of code stash a pointer to something, you must ensure that something remains valid until there is no longer any possibility of those pointers being dereferenced.
You need to make a decision -- what will own the objects that the linked list contains pointers to? When will that lifetime end? And when they end, what will destroy them?
You haven't done this. So you have objects whose lifetimes end too early.
With
CellNode myNode = {1,k,NULL};
insert(&myList,&myNode);
you are passing a pointer to a local variable. The life time of this variable is just as long as the respective iteration of the loop, i.e. in the second iteration, the object of the first iteration is out of scope. So you will access an object which's life time has already ended by the pointer you stored in your list. This yields undefined behaviour.
Use dynamically generated objects instead (and don't forget to free them later on):
CellNode *myNode = malloc(sizeof(CellNode));
myNode->row = ...
You repeatedly insert a node into the linked list from a local variable that immediately goes out of scope. The behavior is undefined, your program might fail in many unpredictable ways.
You should modify the code this way:
change the insert function to take the element data as arguments and allocate a new node with malloc().
make printList() print the full list, not just the first couple of cells.
change the clumsy (*pointer).member notation into the equivalent but more idiomatic pointer->member notation.
return 0 from main for successful operation.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct CellNode CellNode;
struct CellNode {
int row;
int column;
CellNode *next;
};
typedef struct LinkedList LinkedList;
struct LinkedList {
CellNode *head;
};
void printList(LinkedList *myList) {
CellNode *curr = myList->head;
if (curr != NULL) {
printf("(%d,%d)", curr->row, curr->column);
while (curr->next != NULL) {
curr = curr->next;
printf(" - (%d,%d)", curr->row, curr->column);
}
} else {
printf("The list is empty");
}
printf("\n");
}
CellNode *insert(LinkedList *myList, int row, int column) {
CellNode *node = malloc(sizeof(*node));
CellNode *ref = myList->head;
if (node != NULL) {
if (ref == NULL) {
myList->head = node;
} else {
while (ref->next != NULL) {
ref = ref->next;
}
ref->next = node;
}
}
return node; // return node pointer to allow the caller to detect out of memory error
}
int main(int argc, char *argv[]) {
LinkedList myList = { NULL };
CellNode *node;
for (int k = 0; k < 2; k++) {
insert(&myList, 1, k);
printList(&myList);
printf("\n");
}
// free the nodes
while ((node = myList->head) != NULL) {
myList->head = node->next;
free(node);
}
return 0;
}
I have the following code to delete elements from a list. When one of the elements of the struct is lower than the value I use it, I must delete the node.
The code is as follows:
void DeleteNode(frota** head, int MAX, int nSquareW){
int i, eliminate = 0;
frota* curr = *head;
frota* curr1 = curr;
if(*head != NULL)
{
while(curr1 != NULL)
{
if(curr1->bateria < MAX)
{
if( *head == curr1){
if(curr1->next != NULL){
(curr1->next)->prev = NULL;
}
*head = curr1->next;
}else if(curr1 -> next == NULL){
(curr1->prev)->next = NULL;
}else{
(curr1->next)->prev = curr1->prev;
(curr1->prev)->next = curr1->next;
}
eliminate = 1;
}
curr1 = curr1->next;
if(eliminate == 1){
eliminate = 0;
printf("entrei1");
for(i=0;i<nSquareW;i++){
free(curr->percorridos[i]);
}
free(curr->percorridos);
free(curr);
}
curr = curr1;
}
}
}
The code is working well when I try to delete the last and middle nodes (value head is equal to first node, unless there is none, then value is NULL), but when I try to delete the first node, I get the following error:
*** Error in './iClean': double free or corruption (!prev): 0x09bd4a20 ***
Someone has already told me that the problem is when deleting the node (the free() ) and that I can't do anything about that.
Any help would be appreciate.
EDIT
nSquareWidth is the width of the map.
This is the code which generates percorridos:
void faz_mapa(matriz *** mapa, int nSquareW, int nSquareH){
*mapa = malloc(nSquareW * sizeof(matriz*));
for (int i = 0; i < nSquareW; i++)
{
(*mapa)[i]= malloc( nSquareH * sizeof(matriz));
}
for (int i = 0; i < nSquareW; i++)
{
for (int j = 0; j < nSquareH; j++)
{
//inicializa divisao suja
(*mapa)[i][j].limpo = 0;
(*mapa)[i][j].ocupado = NULL;
}
}
}
And struct:
typedef struct robot {
int bateria;
char nome[STRING_SIZE];
int pos_x;
int pos_y;
int target_x;
int target_y;
int limpos;
matriz ** percorridos;
struct robot * next;
struct robot * prev;
}frota;
I haven't run your code, but it is apparent that there is only one spot where we can run into a double free.
for(i=0;i<nSquareW;i++){
free(curr->percorridos[i]);
}
free(curr->percorridos);
free(curr);
Either you have a case where curr->percorridos is the same as curr, or maybe curr->percorridos[i] is the same as curr->percorridos?
You could find this out by adding a print statement before each call to free. Then find out which is being called twice.
for(i=0;i<nSquareW;i++){
printf("Freeing curr->perrcorridos[i] at %p\n", curr->percorridos[i]);
free(curr->percorridos[i]);
}
printf("Freeing curr->perrcorridos at %p\n", curr->percorridos);
free(curr->percorridos);
printf("Freeing curr at %p\n", curr);
free(curr);
Since double linked list programming questions show up so often on Stack Overflow, my answer will showcase how to do a double linked list in a pretty safe way. It uses a top level list type definition and sentinel entries. There is still some room to mess up, but the code is pretty easy to test and debug as different aspects are treated locally by individual functions.
The delete() function in the original question has the problem that it is in charge of 2 different things: 1. handle the double linked list removal stuff 2. Do some application specific filtering.
My code also shows, that application code running on such a list can be separated from list management code.
#include <stdint.h>
#include <stdlib.h>
typedef struct NodeType_tag { int32_t value; NodeType_tag *Next; NodeType_tag *Prev; } NodeType;
typedef struct { NodeType sentinel; NodeType *head; NodeType *tail; } NodeList;
void NodeListInit(NodeList * nodeList)
{
nodeList->sentinel.Next = &nodeList->sentinel;
nodeList->sentinel.Prev = &nodeList->sentinel;
nodeList->head = &nodeList->sentinel;
nodeList->tail = &nodeList->sentinel;
}
int NodeListIsEmpty(NodeList * nodeList)
{
return nodeList->head == &nodeList->sentinel;
}
void NodeListAddFront(NodeList* nodeList, uintptr_t value)
{
NodeType *newNode = (NodeType*)malloc(sizeof(NodeType));
if (NULL != newNode)
{
newNode->value = value;
newNode->Prev = nodeList->head->Prev;
newNode->Next = nodeList->head;
nodeList->head->Prev = newNode;
nodeList->head = newNode;
if (nodeList->tail == &nodeList->sentinel)
nodeList->tail = newNode;
}
}
void NodeListAddBack(NodeList* nodeList, int32_t value)
{
NodeType *newNode = (NodeType*)malloc(sizeof(NodeType));
if (newNode != NULL)
{
newNode->value = value;
newNode->Prev = nodeList->tail;
newNode->Next = nodeList->tail->Next;
nodeList->tail->Next = newNode;
nodeList->tail = newNode;
if (nodeList->head == &nodeList->sentinel)
nodeList->head = newNode;
}
}
NodeType *NodeListHead(NodeList*nodeList)
{
if (&nodeList->sentinel != nodeList->head)
return nodeList->head;
return NULL;
}
NodeType *NodeListTail(NodeList* nodeList)
{
if (&nodeList->sentinel != nodeList->tail)
return nodeList->tail;
return NULL;
}
NodeType *NodeListNext(NodeList * nodeList, NodeType * current)
{
if (NULL != current)
{
if (current->Next != &nodeList->sentinel)
return current->Next;
}
return NULL;
}
NodeType *NodeListPrev(NodeList *nodeList, NodeType *current)
{
if (NULL != current)
{
if (current->Prev != &nodeList->sentinel)
return current->Prev;
}
return NULL;
}
NodeType* NodeListRemoveForward(NodeList* nodeList, NodeType *target)
{
NodeType* next = NULL;
if (target != NULL)
{
target->Prev->Next = target->Next;
target->Next->Prev = target->Prev;
if (target == nodeList->head)
nodeList->head = target->Next;
if (target == nodeList->tail)
nodeList->tail = target->Prev;
if (&nodeList->sentinel != target->Next)
next = target->Next;
free(target);
}
return next;
}
// return 1 if value passes filter.
// return 0 if value is not passing filter.
typedef int(*FilterFunction_t)(int32_t value);
size_t NodeListFilter(NodeList *nodeList, FilterFunction_t filter)
{
NodeType * current = NodeListHead(nodeList);
size_t removeCount = 0;
while (current != NULL)
{
if (filter(current->value))
{
// passed filter -> keep it.
current = NodeListNext(nodeList, current);
}
else
{
// did not pass filter - kill it!
current = NodeListRemoveForward(nodeList, current);
removeCount++;
}
}
return removeCount;
}
void NodeListClear(NodeList *nodeList)
{
NodeType *current = NodeListHead(nodeList);
while (current != NULL)
{
current = NodeListRemoveForward(nodeList, current);
}
}
void DumpNodeList(NodeList* nodeList)
{
NodeType * current = NodeListHead(nodeList);
size_t i;
for (i = 0; current != NULL; i++, current = NodeListNext(nodeList,current))
{
printf("%d: %d\n", i, current->value);
}
}
int FilterAllOddValues(int32_t value)
{
if (0 == value % 2)
return 1;
return 0;
}
void TestNodeList()
{
NodeList myNodeList;
NodeListInit(&myNodeList);
for (int32_t value = 0; value < 10; value++)
{
NodeListAddBack(&myNodeList, value);
}
DumpNodeList(&myNodeList);
size_t removeCount = NodeListFilter(&myNodeList, FilterAllOddValues);
printf("%d nodes removed by filter.\n", removeCount);
DumpNodeList(&myNodeList);
NodeListClear(&myNodeList);
}
One obvious aspect is, that the number of head/tail special handling if-branches is greatly reduced compared to a non-sentinel implementation.
Another obvious aspect is that I ran it with a c++ compiler and thusly added a cast to the malloc() statements. Please resist the urge to write comments like "Don't cast malloc()", all you hardcore c-programmers ;)
I did a brief smoke test with the test code given below. There still might be errors in functions not covered by the test code.
I'm trying to implement sequence_insert_at using the add_to_front function here
Everything before
typedef struct sequence *Sequence;
is pasted from another c file.
void sequence_insert_at(Sequence s, int pos, int item)
{
struct node* temp = s->lst;
for(; pos > 0; --pos)
{
temp = temp->rest;
}
add_to_front(&temp, item);
++s->length;
if(!temp->rest)
{
s->end = temp;
}
//s->lst = temp;
}
I don't know why I keep getting a runtime error. if I clone s->lst and traverse the clone, I'm not modifying the pointer to the node in s, but if I change temp, s->lst should have the reflected changes since the nodes are all linked still. Any ideas as to how to fix this? I tried creating another node that is one before the temp after traversal, and then setting it->rest = temp, but that failed as well.
following mistakes a could spot but only so far to get the main function run
new_sequence does not initialize anything in Sequence it creates. lst is not initialized when you access it in sequence_insert_at
struct node* temp = s->lst;
here how it should look like
Sequence new_sequence()
{
Sequence s = malloc(sizeof(struct sequence));
if(!s)
{
printf("Out of memory. Can't allocate s\n");
exit(EXIT_FAILURE);
}
s->lst = malloc(sizeof(struct node));
if(! s->lst) {
printf("Out of memory. Can't allocate lst\n");
}
s->lst->rest = NULL;
s->length = 0;
return s;
}
also s->lst->rest has to be set to NULL, this is what tells that the list has no more elements an not end witch turns obsolete.
struct sequence
{
struct node* lst;
int length;
};
You should be passing the sequence itself to your functions not a pointer to some internal data in the sequence.
add_to_front(&temp, item);
Your sequence_insert_at function should be the one that can handle any position not add_to_front() so it is easier to call with the position 0 from add_to_front() and your having the the hole work done in one function, not a half here and a half there.
void sequence_insert_at(Sequence s, int pos, int item)
{
if(s && pos <= s->length) {
print_sequence(s);
struct node *newnode = malloc(sizeof(struct node));
if (newnode == NULL) {
printf("ERROR! add_to_front ran out of memory!\n");
exit(EXIT_FAILURE);
}
newnode->first = item;
struct node* temp = s->lst;
struct node* prv = NULL;
for(int i = 0; i < pos; i++) {
printf("skip %d\n", temp->first);
prv = temp;
temp = temp->rest;
}
newnode->rest = temp;
if(pos == 0) {
printf("insert as first\n");
s->lst = newnode;
} else {
printf("insert before %d\n", temp->first);
prv->rest = newnode;
}
++s->length;
}
}
and in add_to_front only one statement is needed
void add_to_front(Sequence s, int item) {
sequence_insert_at(s, 0, item);
}
as for inserting at the back of the list
void add_to_back(Sequence s, int item) {
sequence_insert_at(s, s->length, item);
}
A small test with the main function
void print_sequence(Sequence s)
{
struct node* temp = s->lst;
for(int i = 0; i < s->length; temp = temp->rest) {
printf("%d ", temp->first);
i++;
}
printf("\n");
}
int main()
{
Sequence derp = new_sequence();
sequence_insert_at(derp, 0, 14);
add_to_front(derp, 16);
sequence_insert_at(derp, 0, 17);
sequence_insert_at(derp, 2, 15);
add_to_back(derp, 13);
print_sequence(derp);
delete_sequence(derp);
return 0;
}
output is:
17 16 15 14 13
You'll have to go trough the other functions and fix them.
Finally i should note that variable names you have choosen are little bit confusing if not misleading, i would name them this way
typedef struct node {
int data; /* the data that a node holds */
struct node* next; /* the pointer to the next node */
} Node_t;
typedef struct sequence {
struct node* head; /* head or first element of the sequence/list */
int length; /* length is ok but size is better */
} Sequence_t;
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.