C list->data doesnt show on terminal - c

The console doesnt show the data from my list node.I filled it with chars that i took from a text File.
#include<stdio.h>
#include<stdlib.h>
struct list_node{
char data;
struct list_node* next;
};
typedef struct list_node* node;
node insert_right(node list,char data)
{
node new_node = (node) malloc(sizeof(struct list_node));
new_node->data = data;
new_node->next = list->next;
list->next = new_node;
return new_node;
}
int main()
{
FILE *fr = fopen("dat1.txt","r");
node list = (node) malloc(sizeof(struct list_node));
int i;
while((i = fgetc(fr)) != EOF){
insert_right(list,i);
}
printf("%c",list->data);
}
The main problem i think would be in the insert method.

You are creating a linked list. Each node you create needs to point to either NULL or the next node. You were not quite making the links. Also you were not getting the new_node you you were returning. Also when printing out a list you have to go through each node (like an array).
#include<stdio.h>
#include<stdlib.h>
struct list_node{
char data;
struct list_node* next;
};
typedef struct list_node* node;
node insert_right(node list,char data)
{
node new_node = (node) malloc(sizeof(struct list_node));
new_node->data = data;
list->next = new_node;
new_node->next = NULL;
return new_node;
}
int main()
{
FILE *fr = fopen("dat1.txt","r");
node list = (node) malloc(sizeof(struct list_node));
int i;
node next = list;
while((i = fgetc(fr)) != EOF){
next = insert_right(next,i);
}
node print = list;
while(print != NULL){
printf("%c",print->data);
print = print->next;
}
}

You are allocating memory to a node called list, but yet you do not initialize any value for data, it can be garbage or any character that does not show up in the console.
When you insert a new value, a new node is created and the first one, the "head" so to speak, is still uninitialized even though it is pointing to a second node that has a meaningful data there.
This is your list:
// Node Y (X) indicates the Y-th node that has a X value.
Node1 (garbage) -> Node2 (value) -> Node3 (value) -> garbage
The last node of your list (which is also the first when you create it) should be pointing to NULL instead of being uninitialized.
I am also pretty sure that your list is poor-implemented because the new elements are always being pointed by list, so you lose track of the ones you created before.
Here is a better version, in my opinion:
#include<stdio.h>
#include<stdlib.h>
struct list_node{
char data;
struct list_node* next;
};
typedef struct list_node* node;
void insert_right(node list,char data)
{
node new_node = (node) malloc(sizeof(struct list_node));
node temp = list;
// It runs through the list until it reaches the last node
while(temp->next != NULL) temp = temp->next;
temp->data = data;
temp->next = new_node;
new_node->next = NULL;
}
int main()
{
FILE *fr = fopen("dat1.txt","r");
// List points to only the first element of the list.
node list = (node) malloc(sizeof(struct list_node));
list->next = NULL;
int i;
while((i = fgetc(fr)) != EOF){
insert_right(list,i);
}
while(list != NULL) {
printf("%c",list->data);
list = list->next;
}
}

#include <stdio.h>
#include <stdlib.h>
struct list_node {
char data;
struct list_node* next;
};
int main()
{
FILE *fr = fopen("dat1.txt","r");
struct list_node *list = malloc(sizeof(*list)), *pos = list;
int i;
while ((i = fgetc(fr)) != EOF) {
pos->data = i;
pos->next = malloc(sizeof(*list->next));
pos = pos->next;
}
pos->next = NULL;
while (list->next) {
printf("%c ", list->data);
free(list); /* important!!!! */
list = list->next;
}
putchar('\n');
return 0;
}

Related

Removing element from linked list (if found) without deleting it from memory

I have understood how deletion works in linked list, however the implementation is harder than I thought.
I have written this below but it is not working sadly
My node:
struct DLinkedList
{
double sensorData;
struct DLinkedList *prev;
struct DLinkedList *next;
};
And this is my delete function:
void delete(struct DLinkedList **first, struct DLinkedList *el)
{
struct DLinkedList* temp = *first;
if (temp != NULL && temp->sensorData == el->sensorData)
{
(*first) = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->sensorData == el->sensorData)
{
temp->prev = temp;
temp = temp->next;
}
if (temp == NULL)
{
return;
}
free(temp);
}
Is there something wrong with the code itself? The compiler is not giving me any errors but the function doesn't seem to work properly, the way I call it in main() is delete(&first, el);
Here is my main, I have added 3 elements excluding el so that I can see the list more clearly:
int main()
{
//Adding 3 nodes
struct DLinkedList* first = NULL;
struct DLinkedList* second = NULL;
struct DLinkedList* last = NULL;
struct DLinkedList* el = NULL;
//Allocating 3 nodes
first = malloc(sizeof(struct DLinkedList));
second = malloc(sizeof(struct DLinkedList));
last = malloc(sizeof(struct DLinkedList));
el = malloc(sizeof(struct DLinkedList));
first->sensorData = 1; //Assigning data for 'first' node
first->next = second; //Link first node with second node
first->prev = NULL;
second->sensorData = 2;
second->next = last;
second->prev = first;
last->sensorData = 3;
last->next = NULL;
last->prev = second;
el->sensorData = 10;
el->next = first;
el->prev = NULL;
insertFirst(&first, el);
printList(first);
isMember(&first, el);
delete(&first, el);
return 0;
}
//Printing contents of the linked list starting from the 'first' node
void printList(struct Node* first)
{
while (first != NULL)
{
printf(" %f ", first->data);
first = first->next;
}
}
Here below is my minimal example, I have made some changes in the names and main in order to be more readable
#include <stdio.h>
#include <stdlib.h>
//A linked list node
struct Node
{
double data;
struct Node* prev;
struct Node* next;
};
void delete(struct Node** first, struct Node* el)
{
if (*first == el)
{
*first = el->next;
}
if (el->prev)
{
el->prev->next = el->next;
}
if (el->next)
{
el->next->prev = el->prev;
}
free(el);
}
int main()
{
struct Node* first = NULL;
struct Node* el = NULL;
el = malloc(sizeof(struct Node));
el->data = 10;
el->next = NULL;
el->prev = NULL;
delete(&first, el);
print(first);
return 0;
}
You're complicating it much more than necessary. If you have a doubly linked list, use it's abilities.
void delete(struct DLinkedList **first, struct DLinkedList *el) {
// We only need to change the pointer to the first element
// if that's the element we're deleting
if(*first == el)
*first = el->next;
// The old switcheroo
if(el->prev)
el->prev->next = el->next;
if(el->next)
el->next->prev = el->prev;
// Free and we're done. Skip this line if you want to keep the node
// and only remove it from the list.
free(el);
}
This could be combined with a convenient find function:
struct DLinkedList *find(struct DLinkedList **first, double val) {
struct DLinkedList ret = *first;
while(ret && ret->sensorData != val)
ret = ret->next;
return ret;
}
However, you should be careful comparing float numbers. Read more here: What is the most effective way for float and double comparison?
It seems you're trying to reuse an "element" struct as the "list" struct for a doubly linked list.
Although you can reuse next/prev as head/tail, I recommend a separate header struct:
Here's what I mean. Note that I renamed the struct slightly to be more descriptive of purpose:
// element of list
typedef struct element Element;
struct element {
double sensorData;
Element *next;
Element *prev;
};
// list header
typedef struct list List;
struct list {
Element *head;
Element *tail;
};
void
delete(List *list,Element *el)
{
Element *next;
Element *prev;
next = el->next;
prev = el->prev;
if (next != NULL)
next->prev = prev;
if (prev != NULL)
prev->next = next;
if (list->head == el)
list->head = next;
if (list->tail == el)
list->tail = prev;
}

In my Singly linked List implementation why is it even though I allocated memory for the node to be freed, the pointer to the Node isn't NULL?

Using the delete_SLL function I want to delete the head of this singly linked list(head = 4). Although I get the correct output, the var struct Node* "temp" holding the value of the head isn't NULL. What is it about the variable "temp" that the free function not like? Is the node temp not Malloc-ed when setting it equal to the list head?
Source:Deleting a Node
Code:
#include <stdio.h>
#include <stdlib.h>
struct Node{
int item;
struct Node* next;
};
struct List{
struct Node* head;
struct Node* tail;
};
int SLL_empty(struct List* lst){
return lst->head == NULL ;
}
//newLst work
struct List newLst(){
struct List lst;
lst.head = NULL;
lst.tail = NULL;
return lst;
}
//Inserts a node to the front of the list[WORKS]
void insert_SLL(struct List* lst, int x){
struct Node* nde = (struct Node*)malloc(sizeof(struct Node));
nde->next = lst->head;
nde->item = x;
if (SLL_empty(lst))
lst->tail=nde;
lst->head = nde;
}
//Deletes a given Node
void delete_SLL(struct List* lst, int x){
struct Node* temp = (struct Node*)malloc(sizeof(struct Node));;
temp = lst->head;
struct Node* prev = NULL;`enter code here`
//If the head has the key
if (temp != NULL && temp->item == x){
lst->head = temp->next;
temp->next = NULL;
free(temp);
}
// stops once the key is found
while(temp != NULL && temp->item != x){
prev = temp;
temp= temp->next;
}
//If not in list
if (temp == NULL) return;
//If middle
if (temp != NULL && temp->item == x){
prev->next = temp->next;
temp->next = NULL;
}
//if at the end
if (temp != NULL && temp->item == lst->tail->item){
lst->tail= prev;
prev->next = NULL;
}
free(temp);
}
int SLL_pop(struct List *list){
struct Node* nde = list->head;
int item = nde->item;
list->head = nde->next;
free(nde);
if (SLL_empty(list))
list->tail = NULL;
return item;
}
int main(int argc, const char * argv[]) {
int i;
struct List list = newLst();
for (i = 0; i < 5; ++i)
insert_SLL(&list, i);
// printf("The length of the linkedLst is: %d\n",SLL_length(&list));
delete_SLL(&list, 4);
while ( list.head != NULL )
printf("Node: %d\n", SLL_pop(&list));
return 0;
}
The main purpose of free() is to ask the OS take the allocated memory back to the system. You might not be able to "see" that but if you try to access any element at the "temp" afterward, you should get an error.
While the "temp" in the program is only a variable. C doesn't require to, and can't change the given pointer to NULL due to pass-by-value sense. It's the programmer's work to remember that this pointer is no longer valid.
Or you can set it to NULL manually each time you free a pointer.

Why does one element stays in original list when selection sorting?

#include <stdio.h>
#include <stdlib.h>
struct node {
int val;
struct node* next;
} ;
struct node* largest(struct node** first)
{
struct node* largest = *first;
struct node* prev = NULL;
struct node* temp_prev = NULL;
for(;first != NULL; first = first -> next)
{
if (first -> val > largest -> val)
{
largest = first;
prev = temp_prev;
}
temp_prev = first;
}
if(prev != NULL)
prev -> next = largest -> next;
largest -> next = NULL;
return largest;
}
struct node* sel_sort(struct node** list)
{
struct node* head = NULL;
struct node* temp_largest = NULL;
while (*list)
{
head = largest(list);
head->next=temp_largest;
temp_largest = head;
}
*list = head; // note sets the input pointer to the new list.
return head;
}
void print_list(struct node* first)
{
struct node* temp;
for (temp = first; temp != NULL; temp = temp->next)
{
printf("%d\n", temp->val);
}
}
void main() {
struct node* r = malloc(sizeof(struct node));
struct node* s = malloc(sizeof(struct node));
struct node* t = malloc(sizeof(struct node));
struct node* w = malloc(sizeof(struct node));
struct node* q = malloc(sizeof(struct node));
r->val = 2;
r->next = s;
s->val = 10;
s->next = t;
t->next = w;
t->val = 3;
w->val = 1;
w->next = q;
q->val = 6;
q->next = NULL;
printf("\nBefore Sort:\n");
print_list(r);
printf("\nSorted:\n");
struct node* sorted = sel_sort(&r);
print_list(sorted);
}
In short, the above is selection sort for a singly linked list. I'm having an issue where an infinite loops occurs in the sel_sort method, because no matter how many times I call the largest method, one node will be left in the original list. Other then that my code seems to work, but how do I get around this small problem?
So, what do you expect will ever modify the variable list in this while-loop:
struct node* temp = *list;
struct node* head;
struct node* temp_largest = NULL;
while (list != NULL) // <<=== infinite loop
{
head = largest(temp);
head->next=temp_largest;
temp_largest = head;
}
return head;
I question your use of temp. Technically your largest() function should take a list head by address (pointer to pointer), extract the largest node, returning that node after removal from the list, and updating the passed-in list head on the off-chance it was the first node in the list (therefore the head has to be moved):
struct node* head = NULL;
struct node* temp_largest = NULL;
while (*list)
{
head = largest(list);
head->next=temp_largest;
temp_largest = head;
}
*list = head; // note sets the input pointer to the new list.
return head;
And have largest() take a list pointer by address (a double pointer)
struct node* largest(struct node** first)
{
struct node *prev = NULL;
struct node *lprev = NULL;
struct node *cur = NULL;
struct node *largest = NULL;
if (!(first && *first))
return NULL;
// assume the first node is the largest node
largest = lprev = prev = *first;
cur = largest->next;
for(; cur; prev = cur, cur = cur->next)
{
if (cur->val > largest->val)
{
largest = cur;
lprev = prev;
}
}
// go with the simple stuff first. was `largest`
// the first item in the list?
if (largest == *first)
{
// yes it was, so move the list head.
*first = largest->next;
}
else
{ // no it was not, so link `lprev` to be
// the node following `largest`
lprev->next = largest->next;
}
// regardless. always unlink the largest node.
largest->next = NULL;
return largest;
}
Using this in combination with the updated sort, I get this for output:
Output
Before Sort:
2
10
3
1
6
Sorted:
1
2
3
6
10

trouble updating tail pointer in queue adt using singly linked list

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?

C: How to free nodes in the linked list?

How will I free the nodes allocated in another function?
struct node {
int data;
struct node* next;
};
struct node* buildList()
{
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
return head;
}
I call the buildList function in the main()
int main()
{
struct node* h = buildList();
printf("The second element is %d\n", h->next->data);
return 0;
}
I want to free head, second and third variables.
Thanks.
Update:
int main()
{
struct node* h = buildList();
printf("The element is %d\n", h->next->data); //prints 2
//free(h->next->next);
//free(h->next);
free(h);
// struct node* h1 = buildList();
printf("The element is %d\n", h->next->data); //print 2 ?? why?
return 0;
}
Both prints 2. Shouldn't calling free(h) remove h. If so why is that h->next->data available, if h is free. Ofcourse the 'second' node is not freed. But since head is removed, it should be able to reference the next element. What's the mistake here?
An iterative function to free your list:
void freeList(struct node* head)
{
struct node* tmp;
while (head != NULL)
{
tmp = head;
head = head->next;
free(tmp);
}
}
What the function is doing is the follow:
check if head is NULL, if yes the list is empty and we just return
Save the head in a tmp variable, and make head point to the next node on your list (this is done in head = head->next
Now we can safely free(tmp) variable, and head just points to the rest of the list, go back to step 1
Simply by iterating over the list:
struct node *n = head;
while(n){
struct node *n1 = n;
n = n->next;
free(n1);
}
One function can do the job,
void free_list(node *pHead)
{
node *pNode = pHead, *pNext;
while (NULL != pNode)
{
pNext = pNode->next;
free(pNode);
pNode = pNext;
}
}
struct node{
int position;
char name[30];
struct node * next;
};
void free_list(node * list){
node* next_node;
printf("\n\n Freeing List: \n");
while(list != NULL)
{
next_node = list->next;
printf("clear mem for: %s",list->name);
free(list);
list = next_node;
printf("->");
}
}
You could always do it recursively like so:
void freeList(struct node* currentNode)
{
if(currentNode->next) freeList(currentNode->next);
free(currentNode);
}

Resources