This is a continuation of a problem I posted yesterday, which I thought was solved, but turns out another problem has been encountered with the way I iterate through the loop and its exit condition. I felt a new question thread might be more appropriate.
The following freeAllListMembers() function seems to be working, up until the last iteration of the loop because it is trying to free "temp" but temp has already been freed, what method can I use to exit this loop and keep it from running once more, everything I have tried doesn't seem to be working.
thanks for any insight
int main() {
struct node *head = NULL;
createList(&head);
//do stuff with list
freeAllListMembers(&head);
return 0;
}
int createList(struct node **head) {
struct node *newNode= NULL;
for(int I = 0; I < 100; I++)
{
struct node *node = (struct node*)malloc(sizeof(struct node));
node->data = someData;
node->next = NULL;
//if we havent created an initial start node, create it
if (*head == NULL)
{
*head = node;
}
//otherwise, navigate to the end of the list to add a new node
else
{
newNode = *head;
while (newNode->next != NULL){
newNode = newNode->next;
}
newNode->next = node;
}
}
return 0;
}
void freeAllListMembers(struct node **head){
struct node *temp;
while (*head != NULL) {
temp = *head;
*head = (*head)->next;
free(temp);
}
return;
}
Cleaning up the example given to remove some small human errors, the program compiles OK, and I can step through OK in GDB. It basically ran after it compiled without errors
#include <malloc.h>
#define someData 12345
struct node
{
int data;
struct node* next;
};
int createList(struct node **head )
{
struct node *newNode= NULL;
int i;
for( i = 0; i < 100; i++)
{
struct node *node = (struct node*)malloc(sizeof(struct node));
node->data = someData;
node->next = NULL;
//if we havent created an initial start node, create it
if (*head == NULL)
{
*head = node;
}
//otherwise, navigate to the end of the list to add a new node
else
{
newNode = *head;
while (newNode->next != NULL){
newNode = newNode->next;
}
newNode->next = node;
}
}
return 0;
}
void freeAllListMembers(struct node **head)
{
struct node *temp;
while (*head != NULL) {
temp = *head;
*head = (*head)->next;
free(temp);
}
return;
}
int main()
{
struct node *head = NULL;
createList(&head);
//do stuff with list
freeAllListMembers(&head);
return 0;
}
I can only guess that you lost whatever your bug was in the 'abstraction' process
Related
#include <stdlib.h>
#include <stdio.h>
struct node {
int data;
struct node *next;
};
void addLast(struct node **head, int value);
void printAll(struct node *head);
struct node *head1 = NULL;
int main() {
addLast(&head1, 10);
addLast(&head1, 20);
addLast(&head1, 30);
addLast(&head1, 40);
printAll(head1);
return 0;
}
void addLast(struct node **head, int value) {
struct node *newNode = (struct node*)malloc(sizeof(struct node));
newNode->data = value;
if (*head == NULL) {
*head = newNode;
(*head)->next = NULL;
} else {
struct node **temp = head;
while ((*temp)->next != NULL) {
*temp = (*temp)->next;
}
(*temp)->next = newNode;
newNode->next = NULL;
}
}
void printAll(struct node *head) {
struct node *temp = head;
while (temp != NULL) {
printf("%d->", temp->data);
temp = temp->next;
}
printf("\n");
}
addLast() will append the new node at the end of the list, with printAll(), I am printing entire list.
Every time when I am printing the list, I can only see the last two nodes.
Can anyone please help, why loop is not iterating over entire list ?
The function addLast is too complicated and as result is wrong due to this statement
*temp = (*temp)->next;
in the while loop. It always changes the head node.
Define the function the following way
int addLast( struct node **head, int value )
{
struct node *newNode = malloc( sizeof( struct node ) );
int success = newNode != NULL;
if ( success )
{
newNode->data = value;
newNode->next = NULL:
while( *head ) head = &( *head )->next;
*head = newNode;
}
return success;
}
Take into account that there is no need to declare the variable head1 as global. It is better to declare it inside the function main.
Also all the allocated memory should be freed before exiting the program.
Below I have written a program to detect and and remove a loop from list using C. I am getting a runtime error, but I am not able to find it?
#include <stdio.h>
#include <stdlib.h>
//node definition
struct node {
int key;
struct node *next;
};
// This function will make a new node
struct node *newNode(int key) {
struct node *temp = (struct node*)(malloc)(sizeof(struct node));
temp->key = key;
temp->next = NULL;
}
//This function will detect and remove a loop from linked list
void detect(struct node *head) {
struct node *slow = head;
struct node *fast = head->next;
while (fast && fast->next) {
if (slow == fast)
break;
slow = slow->next;
fast = fast->next->next;
}
if (slow == fast) {
slow = head;
while (slow != fast->next) {
slow = slow->next;
fast = fast->next;
}
fast->next = NULL;
}
}
//This function will print list
void print(struct node *head) {
struct node *temp = head;
while (temp != NULL) {
printf("%d ", temp->key);
temp = temp->next;
}
}
//This function is driver method
int main() {
struct node *head = newNode(10);
head->next = newNode(20);
head->next->next = newNode(30);
head->next->next->next = newNode(40);
head->next->next->next->next = newNode(50);
head->next->next->next->next->next = head->next->next;
detect(head);
print(head);
return 0;
}
The function newNode does not return anything, which is not consistent with the prototype.
Looking at your code, you should add return temp at the end of the function.
Hi I wish to implement a simple linked list and all the values to the end of the list. As simple as that but I am not able to do so. Can you please tell me where I am doing it wrong ? Initially I am declaring a pointer and assigning NULL value to it. Later in each iteration I am allocating memory to the pointer that was initially NULL.
#include <stdio.h>
#include <malloc.h>
struct node{
int a;
struct node* next;
};
struct node* insert(struct node* start,int value);
void print(struct node* head);
int main()
{
int a;
struct node* head = NULL;
while(scanf("%d",&a) != EOF)//taking input
{
head = insert(head,a);
print(head);
}
return 0;
}
struct node* insert(struct node* start,int value)
{
struct node* head = start;
while(start != NULL)
{
start = start->next;//getting upto the end of the linked list
}
start = (struct node*)malloc(sizeof(struct node));//allocating memory at the end
start->a = value;
start->next = NULL;
if(head == NULL)
{
return start;//for the base case when list is initally empty
}
return head;
}
void print(struct node* head)
{
while(head != NULL)
{
printf("%d\n",head->a);
head = head->next;
}
return;
}
You're losing your linkage between your tail and your new node, try this instead
struct node* insert(struct node* head,int value)
{
struct node* tail = head;
while(tail != NULL && tail->next != NULL)
{
tail= tail->next;//getting upto the end of the linked list
}
struct node* start = (struct node*)malloc(sizeof(struct node));//allocating memory at the end
start->a = value;
start->next = NULL;
if(head == NULL)
{
return start;//for the base case when list is initally empty
}
else
{
tail->next = start;
}
return head;
}
struct node* insert(struct node* start,int value){
struct node* head = start;
struct node* np = (struct node*)malloc(sizeof(struct node));
np->a = value;
np->next = NULL;
if(head == NULL)
return np;
while(start->next != NULL){
start = start->next;
}
start->next = np;
return head;
}
What makes the approach I am using buggy ?
nodeX
|
+a
|
+next(address to OtherX)
nodeX.next = new_node;//update link(case of OK)
tempPointer = nodeX.next;//address to OtherX set to tempPointer
tempPointer = new_node;//contents of tempPointer changed, but orignal (nodeX.next not change)
i am trying to make a queue library that is based on a linked list library i already made. specifically i am having troubles updating the tail pointer in the queue structure after i add a new node to the linked list.
linked list structure:
struct listNode {
int nodeLength;
int nodeValue;
struct listNode *next;
};
typedef struct listNode node;
queue structure:
struct QueueRecord {
node *list;
node *front;
node *back;
int maxLen;
};
typedef struct QueueRecord queue;
so here is my add function in the queue library
void add(queue currentQueue, int data){
addTail(currentQueue.list, data, data+5);
currentQueue.back = currentQueue.back->next;
}
and the addTail function from the linked list library
void addTail (node *head, int value, int length) {
node *current = head;
node *newNode = (struct listNode *)malloc(sizeof(node));
newNode = initNode(value, length);
while (current->next != NULL)
current = current->next;
newNode->next = NULL;
current->next = newNode;
}
so again my problem is the tail pointer is not getting set to the last node in the list. it is remaining in the same place as the head pointer. ive been researching this for hours trying to see if im just missing something small but i cant find it. if more code or explanation is needed to understand my problem i can provide it.
how a queue is created:
queue createQueue(int maxLen){
queue newQueue;
newQueue.list = createList();
newQueue.front = newQueue.list;
newQueue.back = newQueue.list;
newQueue.maxLen = maxLen;
return newQueue;
}
node *createList (){
node *head = NULL;
head = (struct listNode *)malloc(sizeof(node));
head->next = NULL;
return head;
}
node *initNode (int value, int length){
node *newNode = NULL;
newNode = (struct listNode *)malloc(sizeof(node));
newNode->nodeValue = value;
newNode->nodeLength = length;
newNode->next = NULL;
return newNode;
}
void add(queue currentQueue, int data){
You are passing a copy of the queue struct to add, so only the copy's members are changed. You need to pass a queue* to the function to be able to change the members of the queue itself.
void add(queue *currentQueue, int data){
if (currentQueue == NULL) {
exit(EXIT_FAILURE);
}
addTail(currentQueue->list, data, data+5);
currentQueue->back = currentQueue->back->next;
}
and call it as add(&your_queue);
In your addTail function, you should check whether head is NULL too.
And with
node *newNode = (struct listNode *)malloc(sizeof(node));
newNode = initNode(value, length);
in addTail, you have a serious problem. With the assignment newNode = initNode(value, length);, you are losing the reference to the just malloced memory.
If initNode mallocs a new chunk of memory, it's "just" a memory leak, then you should remove the malloc in addTail.
Otherwise, I fear initNode returns the address of a local variable, à la
node * initNode(int val, int len) {
node new;
new.nodeValue = val;
new.nodeLength = len;
new.next = NULL;
return &new;
}
If initNode looks similar to that, that would cause a problem since the address becomes invalid as soon as the function returns. But your compiler should have warned you, if initNode looked like that.
Anyway, without seeing the code for initNode, I can't diagnose the cause.
But if you change your addTail to
void addTail (node *head, int value, int length) {
if (head == NULL) { // violation of contract, die loud
exit(EXIT_FAILURE);
}
node *current = head;
node *newNode = malloc(sizeof(node));
if (newNode == NULL) {
exit(EXIT_FAILURE); // or handle gracefully if possible
}
newNode->nodeValue = value;
newNode->nodeLength = length;
newNode->next = NULL;
while (current->next != NULL)
current = current->next;
current->next = newNode;
}
it should work.
However, since you have pointers to the first and the last node in the list, it would be more efficient to use the back pointer to append a new node,
void add(queue *currentQueue, int data){
node *newNode = malloc(sizeof *newNode);
if (newNode == NULL) {
exit(EXIT_FAILURE); // or handle gracefully if possible
}
newNode->nodeValue = data;
newNode->nodeLength = data+5;
newNode->next = NULL;
currentQueue->back->next = newNode;
currentQueue->back = newNode;
}
since you needn't traverse the entire list to find the end.
A simple sample programme
#include <stdlib.h>
#include <stdio.h>
struct listNode {
int nodeLength;
int nodeValue;
struct listNode *next;
};
typedef struct listNode node;
struct QueueRecord {
node *list;
node *front;
node *back;
int maxLen;
};
typedef struct QueueRecord queue;
node *createList (){
node *head = NULL;
head = (struct listNode *)malloc(sizeof(node));
head->next = NULL;
return head;
}
void addTail (node *head, int value, int length) {
if (head == NULL) { // violation of contract, die loud
exit(EXIT_FAILURE);
}
node *current = head;
node *newNode = malloc(sizeof(node));
if (newNode == NULL) {
exit(EXIT_FAILURE); // or handle gracefully if possible
}
newNode->nodeValue = value;
newNode->nodeLength = length;
newNode->next = NULL;
while (current->next != NULL)
current = current->next;
current->next = newNode;
}
queue createQueue(int maxLen){
queue newQueue;
newQueue.list = createList();
newQueue.front = newQueue.list;
newQueue.back = newQueue.list;
newQueue.maxLen = maxLen;
return newQueue;
}
void add(queue *currentQueue, int data){
if (currentQueue == NULL) {
exit(EXIT_FAILURE);
}
addTail(currentQueue->list, data, data+5);
currentQueue->back = currentQueue->back->next;
}
int main(void) {
queue myQ = createQueue(10);
for(int i = 1; i < 6; ++i) {
add(&myQ, i);
printf("list: %p\nfront: %p\nback: %p\n",
(void*)myQ.list, (void*)myQ.front, (void*)myQ.back);
}
node *curr = myQ.front->next;
while(curr) {
printf("Node %d %d, Back %d %d\n", curr->nodeValue,
curr->nodeLength, myQ.back->nodeValue, myQ.back->nodeLength);
curr = curr->next;
}
while(myQ.list) {
myQ.front = myQ.front->next;
free(myQ.list);
myQ.list = myQ.front;
}
return 0;
}
works as expected, also with the alternative add implementation.
i think you never initialized back, so back->next is some random pointer?
This is my code. I made three functions for adding a new node, inserting a new node between two others, and one deleting, but I dont know how to delete the first node. I dont even have any idea.
#include <stdlib.h>
#include <stdio.h>
struct Node
{
int data;
struct Node *next;
};
void insert(Node* insertafter, Node* newNode);
void add(Node* llist,Node* newNode);
void deleteafter(Node *llist);
void deletefirts();
int main()
{
struct Node *llist;
struct Node *newNode;
newNode = (Node*)malloc(sizeof(struct Node));
newNode->data = 13;
struct Node *newNode2;
newNode2 = (Node*)malloc(sizeof(struct Node));
newNode2->data = 14;
llist = (Node*)malloc(sizeof(struct Node));
llist->data = 10;
llist->next = (Node*)malloc(sizeof(struct Node));
llist->next->data = 15;
llist->next->next = NULL;
insert(llist,newNode);
add(llist,newNode2);
if(llist->next == NULL)
printf("shecdoma");
struct Node *cursor = llist;
while (cursor != NULL)
{
printf("%d\n", cursor->data);
cursor = cursor->next;
}
system("pause");
return 0;
}
void insert(Node* insertafter, Node *newNode)
{
newNode->next = insertafter->next;
insertafter->next = newNode;
}
void add(Node* llist,Node *newNode)
{
if(llist->next == NULL)
{
llist->next = newNode;
newNode->next = NULL;
}
else
{
while(llist->next != NULL)
{
llist = llist->next;
}
add(llist,newNode);
}
void deleteafter(Node *llist)
{
if(llist->next != NUll)
llist->next = llist->next->next;
}
void deletefirst();
{
}
You can use something like:
void deletefirst (struct Node **head) {
struct Node *tmp = *head; // save old head for freeing.
if (tmp == NULL) return; // list empty? then do nothing.
*head = tmp->next; // advance head to second node.
free (tmp); // free old head.
}
You pass in the pointer to the head so that you can change it. Deleting nodes other than the first does not require this but deleting the first node does.
You set up a temporary pointer to the head so you free it, then you change the head to point to its next element. Then you free the old head and return.
void deleteFirst(Node** list)
{
Node* temp = *list;
if (*list != NULL)
{
*list = (*list)->next;
free(temp);
}
}