Removing First element of linked list in C - c

Seemingly simple C code is seemingly not allowing me to remove the first element from a linked list. I can, however, successfully remove any other individual element and can successfully delete the whole linked list.
typedef struct list{
int data;
struct list * next;
} list;
void remove_element(list * node, unsigned int index){
if (node == NULL)
exit(-1);
list *currElem = node;
if (index == 0) {
node = node->next;
currElem->next = NULL;
free(currElem);
return;
}
Produces the follwing:
"free(): invalid pointer: 0xbfabb964"
I've followed the same format for all of my other manipulation functions with no issues. Similar threads on forums don't seem to be dealing with this particular problem.

You can read the explanation in this pdf on the Push function which explains it:
http://cslibrary.stanford.edu/103/
This is where c gets funky pschologically. You instinctively want to label a pointer as a pointer, which it is. But it is a pointer value, not a pointer reference. It's like the holy spirit of the C divinty. The triumvirate. C passed arguments to functions by value, not by address/reference. So, what do you do to pass a variable by reference? Remember, the solution is so obvious, it really didn't make sense to me for a week, I swear to god.

Related

If a parameter is a pointer type, is the parameter a pointer allocated in local memory

I'm just learning C, and I have a question about pointer parameters. My code is the following:
int Length(node *head)
{
int length = 0;
while (head) {
length++;
head = head->next;
}
return length;
}
The code in the book I'm reading says to do this though:
int Length(struct node* head)
{
struct node* current = head;
int count = 0;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
Is there really a difference? The way I'm reading my code is that I get a pointer to a node struct as a parameter. The pointer itself however, is a local variable that I am free to mutate as long as I don't dereference it first. Therefore, I can change the value of the pointer to point to a different node (the next node as it may be).
Will this cause a memory leak or is there some other difference I'm not seeing?
This code is for a linked list implementation. The node struct is defined as:
// Define our linked list node type
typedef struct node {
int data;
struct node *next;
} node;
Yes, they are both doing the same. But in the second example, it is more clear what the author is trying to do because of the code. In your first example, you're using the pointer head to reference nodes other than the head. That can be confusing.
You could write your function like this and your intend would be clear:
int GetLength(node* current)
{
int length = 0;
while (current != NULL)
{
length += 1;
current = current->next;
}
return length;
}
Your solution and reasoning is correct. The node argument is a local variable: a copy of the pointer passed to your function, allocated on the stack. That's why you can modify it from within the function.
There is no difference between the two solutions, at least not in functionality, modern compilers are most likely to optimize away the extra variable in the book's solution. The only slight difference is in style, many tend to take arguments as unmodifiable values just in case to avoid mistakes.
Your understanding of the argument-passing mechanics is correct. Some people simply prefer not to modify argument values, the reasoning being that modifying an argument tends to be bug-prone. There's a strong expectation that at any point in the function, if you want to get the value the caller passed as head, you can just write head. If you modify the argument and then don't pay attention, or if you're maintaining the code 6 months later, you might write head expecting the original value and get some other thing. This is true regardless of the type of the argument.

Deleting first node of linked list

I have to print a list of a set in c using linked lists (hence pointers). However,when I delete the first element of the list and try to print the list, it just displays a lot of addresses under each other. Any suggestions of what the problem might be? Thanks!
Delete function:
int delete(set_element* src, int elem){
if (src==NULL) {
fputs("The list is empty.\n", stderr);
}
set_element* currElement;
set_element* prevElement=NULL;
for (currElement=src; currElement!=NULL; prevElement=currElement, currElement=currElement->next) {
if(currElement->value==elem) {
if(prevElement==NULL){
printf("Head is deleted\n");
if(currElement->next!=NULL){
*src = *currElement->next;
} else {
destroy(currElement);
}
} else {
prevElement->next = currElement->next;
}
// free(currElement);
break;
}
}
return 1;
}
void print(set_element* start)
{
set_element *pt = start;
while(pt != NULL)
{
printf("%d, ",pt->value);
pt = pt->next;
}
}
If the list pointer is the same as a pointer to the first element then the list pointer is no longer valid when you free the first element.
There are two solutions to this problem:
Let all your list methods take a pointer to the list so they can update it when neccesary. The problem with this approach is that if you have a copy of the pointer in another variable then that pointer gets invalidated too.
Don't let your list pointer point to the first element. Let it point to a pointer to the first element.
Sample Code:'
typedef struct node_struct {
node_struct *next;
void *data;
} Node;
typedef struct {
Node *first;
} List;
This normally happens when you delete a pointer (actually a piece of the memory) which doesn't belong to you. Double-check your function to make sure you're not freeing the same pointer you already freed, or freeing a pointer you didn't create with "malloc".
Warning: This answer contains inferred code.
A typical linked list in C looks a little something like this:
typedef struct _list List;
typedef struct _list_node ListNode;
struct _list {
ListNode *head;
}
struct _list_node {
void *payload;
ListNode *next;
}
In order to correctly delete the first element from the list, the following sequence needs to take place:
List *aList; // contains a list
if (aList->head)
ListNode *newHead = aList->head->next;
delete_payload(aList->head->payload); // Depending on what the payload actually is
free(aList->head);
aList->head = newHead;
The order of operations here is significant! Attempting to move the head without first freeing the old value will lead to a memory leak; and freeing the old head without first obtaining the correct value for the new head creates undefined behaviour.
Addendum: Occasionally, the _list portion of the above code will be omitted altogether, leaving lists and list nodes as the same thing; but from the symptoms you are describing, I'm guessing this is probably not the case here.
In such a situation, however, the steps remain, essentially, the same, but without the aList-> bit.
Edit:
Now that I see your code, I can give you a more complete answer.
One of the key problems in your code is that it's all over the place. There is, however, one line in here that's particularly bad:
*src = *currElement->next;
This does not work, and is what is causing your crash.
In your case, the solution is either to wrap the linked list in some manner of container, like the struct _list construct above; or to rework your existing code to accept a pointer to a pointer to a set element, so that you can pass pointers to set elements (which is what you want to do) back.
In terms of performance, the two solutions are likely as close so as makes no odds, but using a wrapping list structure helps communicate intent. It also helps prevent other pointers to the list from becoming garbled as a result of head deletions, so there's that.

strcmp saying that it has EXC_BAD_ACCESS

This loop will crash and give the error of EXC_BAD_ACCESS in XCode 4.6.2
Here is the loop code
for (beforeToDel = studentToChange->pFirstClass;
(int)strcmp(beforeToDel->pNext->classId, className) == 0;
beforeToDel = beforeToDel->pNext)
{}
and the different variables have these values:
Thank you so much for any help you can give!
beforeToDel->pNext->pNext is NULL. Your loop will crash on the second iteration trying to indirect through that pointer to compare to className. You need to check it before calling strcmp.
Aside: Why the typecast to int?
There is no need to cast the return value of strcmp to an int. It's already one.
What happens if beforeToDel is NULL, or if beforeToDel->pNext is NULL? If they point to nothing, then they can't have a classId or pNext member, right?
It is an error to use strcmp if you haven't included <string.h>, so make sure you have that included. I presume you're looking for the link to a node to be removed, hence the rather awkward identifier "beforeToDel". What happens if the head of the list is the node you want to remove? Why don't you start with a pointer to studentToChange->pFirstClass and iterate on the links, rather than the nodes? This will solve your head problem, and make your code more clear at the same time.
I'm going to declare my linked list like this:
struct list {
struct list *next;
char class_name[];
};
Declare a pointed to whichever type pNext is. Call it link, because this object will store a pointer to the link that the code will update. Initialise it to the head of the list. This way, when the first iteration results in a match, you'll be changing the head of your list with ease. In my function, I'll be returning the new head. You don't need to do that in your code. Just make sure link points to the head of the list (eg. link = &studentToChange->pFirstClass;).
At the end of each iteration, update link to point to (*link)->next (or pNext, in your case).
Operate on *link, rather than link (eg. strcmp(*link->classId, class_name) == 0). When the node to delete is found, assign over the top of it by using *link = *link->next; or equivalent.
struct list *list_remove_class_name(struct list *head, char *class_name) {
struct list **link = &head;
/* Did you mean != 0 here? */
while (*link != NULL && strcmp(*link->class_name, class_name) == 0) {
*link = *link->next;
}
struct list *node = *link;
if (node != NULL) {
*link = node->next;
}
free(node);
return head;
}

C: Pointer to pointer issue when I try to group a lot of things in it

I have a function that adds one item to a list that I created. If it's the first time and the list points to NULL, it allocates the list and completes it, returning the address. If it's not the first time, it adds another item and again returns the first item (by now I could disregard this return). The list and the function WORKS fine, here is the prototype:
typedef struct structTAppConsoleList {
char *text;
void (*cbFunction)(int);
int number; // This is the item number
struct structTAppConsoleList *previous;
struct structTAppConsoleList *next;
} TList;
TList *AppConsoleListAddItem(TList *p_list, const char *p_string, void (*p_funcPtr)(int));
So, somewhere in my code I have to create a lot of them and I'm trying to make it as the code below shows. Thing is, I can't make it work... I want to create something to group the lists I want to create and then use it in the function. The code below is an idea of what I'm trying to do. Consider only the part where I try to allocate the 3 lists, the rest is not important for this example.
TList *list1;
TList *list2;
TList *list3;
int main(void)
{
int i,j;
TList **groupMyLists;
TList *temp;
groupMyLists=malloc(sizeof(TList)*3);
*groupMyLists =(TList*)&list1;
*(groupMyLists+1)=(TList*)&list2;
*(groupMyLists+2)=(TList*)&list3;
for(j=0;j<3;j++) {
temp=NULL;
for(i=0;i<10;i++) {
temp=AppConsoleListAddItem(temp,"some text",someFunc);
}
**groupMyLists=temp; // my make won't let me do this
groupMyLists++;
}
}
I'm pretty sure that this would do it, but I can't compile it.
In my head, (*groupMyLists) would be the same as (&list1), (&list2), (&list3), the same way that (**groupMyLists) would be the same as (list1), (list2) and (list3). So why I can't do (**groupMyLists=temp)? Anyone?
I hope I made myself clear!! I's not easy to explain this madness I'm trying to do...
Change this line, you are using the wrong indirection.
*groupMyLists=temp;
In addition to the above two answers about the incorrect indirection of **groupMyLists you probably also want to assign the list1,list2,list3 pointers correct pointer values instead of writing garbage values into the allocated memory in groupMyLists i.e.
TList * groupMyList = malloc(sizeof(TList)*3);
list1 = &groupMyList[0];
list2 = &groupMyList[1];
list3 = &groupMyList[2];
but, this does not really match the rest of your code as it seems that AppConsoleAddListItem allocates the temp list so in that case your malloc would be incorrect as it should allocate the space for the pointers instead of space for the lists as in:
TList ** groupMyList = (TList **)malloc(sizeof(TList *)*3);
TList * temp;
if (!groupMyList) {
/* Print allocation error warning or handle in some proper fashion */
exit(1);
}
for(j=0;j<3;j++) {
temp=NULL;
for(i=0;i<10;i++) {
temp=AppConsoleListAddItem(temp,"some text",someFunc);
}
groupMyLists[j]=temp; // Here you now assign the pointer in temp to the memory for // pointers that you allocated above
}
list1 = groupMyList[0]; // Here we need to assign the list1,2,3 after the AppConsole calls
list2 = groupMyList[1]; // as these calls will changes the pointer addresses written into
list3 = groupMyList[2]; // groupMyList
Although I can not be sure exactly what you are trying to do there are several inconsistencies of pointers and indirections in your original code and the above two examples can hopefully be of some guidance
This would do the job:
**groupMyLists = *temp;
of copying one struct referenced by temp to another struct referenced by *groupMyLists.
But only if *groupMyLists would reference any valid memory, which is does not do - at least not from the source you posted.

Why do so many example linked lists put the next pointer at the end of each node instead of at the beginning?

I've seen quite a few example C implementations of linked lists on this site, and most of them place the next pointer at the end of each node like so...
struct intNode1 {
int data;
intNode1 *next;
};
Why do they implement them like that instead of like this?
struct node {
struct node *next;
};
struct intNode2 {
struct node node;
int data;
};
The latter way of implementing linked lists allows your insertion and deletion code work on any kind of node as well as allowing you to create a generic list type while the former way forces you to implement each kind of list from scratch.
For example, here is an (incomplete) implementation of a singly linked list using both kinds of nodes:
struct intList {
struct intNode1 *head;
};
struct list {
struct node *head;
};
Now, obviously any operation on a generic list that needs to compare it's nodes will need a function pointer to a comparison function, but that can often be hidden away in the implementation of a less generic interface for a list. For instance:
/* Returns zero if successful or nonzero otherwise */
int list-insertInt(struct list *list, int n) {
struct intNode2 * newNode;
if(!(newNode = malloc(sizeof *newNode)) {
return -1;
}
newNode->data = n;
return list-insertNode(list, (struct node *)newNode);
}
/* Assumes that the list contains only int nodes. */
int list-containsInt(struct list *list, int n) {
struct intNode2 *current = (intNode2 *)list->head;
while (current) {
if(current->data == n) {
return true;
}
current = current->next;
}
return false;
}
You can of course free a list without knowing what kinds of nodes it has:
void list-free(struct list *list) {
struct node *current = list->head;
struct node *next;
while(current) {
next = current->next;
free(current);
current = next;
}
}
PS. It's a bit late (i.e. it's early in the morning but I haven't slept yet) as I write this. so feel free to edit this question to be more clear.
Because textbooks on datastructures are mostly meant to teach concepts to beginners. That kind of 'optimization' just adds a lot of noise to the beginner's ear. It is what you do with your knowledge after school, that separates you from the rest...
I don't know about anyone else but I do it simply so, when I want to write the data portion to a file, I just write the bit sans the pointers at the end (including prev pointer if it's a doubly linked list).
Very rarely do I have a linked list where the types of each node can be different and almost certainly never when teaching the concepts of lists and other abstract data types to beginners.
The advantage of putting the pointer at the end is that the node and the payload have the same address. This may not seem much of an advantage now, but think back to before ANSI C. Yes I'm talking about a time when the compiler didn't even try to check the data type of pointers.
When you wanted to pass the payload to a function you could just pass the pointer, saving several bytes of typing (and valuable disk space!).
Some linked lists put the Next pointer at the end of the structure, some don't. I don't really see this as an issue.
To be honest, I'm not sure I ever ran across a case in C where a linked list maintained different node types. But doing something like you describe could be used if that's what you needed to do.
Note that most C programmers today use C++, which would allow you to use inheritance to accomplish the same thing. Using inheritance, it wouldn't matter where the Next member was placed within the class.

Resources