Code:
void find (item **hp)
{
item *q=(*hp);
item *p=(*hp)->next, *temp;
while (q->next)
{//This loop appears to loop through all elements in the list
while (p)
{//This loop also appears to loop through all elements in the list, I don't think you need both
if (q->data==p->data)
{//We found a matched value, the second copy of the value, p, should be removed
temp=q;
(*hp)=p;
//when you change the value of hp you change the head of the list
//this will effectively remove all entries before p
free(temp);
q=(*hp);
p=q->next;
}
p=p->next;
}
q=q->next;
p=p->next;
}
}
I think you are a little further from the solution on this version. When you remove a value you need to remove the value from p not q. You don't save any information on previous entries in your list so you can reset the next value in the list entry before q.
What you need to do is adjust the next value in q, then free() p, then adjust your p value and continue looping.
Code:
void find (item **hp)
{
item *q=(*hp);
item *p=(*hp)->next, *temp;
while (q->next)
{
if (q->data == p->data)
{//Remove the duplicate in p
q->next = p->next;
free(p);
}
else
{//Only advance to the next list entry if no match occurs
q = q->next;
}
//Always reset p so that you keep moving through the list
p = q->next;
}
You were OK with the delemiddle() function since thats what it did. The trouble you had was that when you advanced twice it was possible for you to try to advance past the end of the list which caused the memvory protection faults, or jump past a value that was a match.