output linked list to txt file - c

Hello I am trying to export a linked list to a text file but somehow all the time the text file reaches to very big size(5gb)and not opened.
I would be happy if you could see what the problem is and offer me a way to repair her thanks
My code -
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} node;
node* insert(node* head, int num);
void free_list(node *head);
void fprintfList(node *head);
int main()
{
int num;
int temp;
node *head, *p;
head = NULL;
FILE * MyFile;
do
{
printf("Enter numbers\n");
scanf("%d",&num);
if(num)
{
head = insert(head, num);
}
} while(num);
p = head;
MyFile = fopen("New_File.txt","w");
while(head)
{
fprintf(MyFile, "%d\n",head->next);
}
//fprintfList(head);
free_list(head);
fclose(MyFile);
return 0;
}
node* insert(node* head, int num)
{
node *temp, *prev, *next;
temp = (node*)malloc(sizeof(node));
temp->data = num;
temp->next = NULL;
if(!head){
head=temp;
} else{
prev = NULL;
next = head;
while(next && next->data<=num){
prev = next;
next = next->next;
}
if(!next){
prev->next = temp;
} else{
if(prev) {
temp->next = prev->next;
prev-> next = temp;
} else {
temp->next = head;
head = temp;
}
}
}
return head;
}
void free_list(node *head)
{
node *prev = head;
node *cur = head;
while(cur)
{
prev = cur;
cur = prev->next;
free(prev);
}
}

while(head)
{
fprintf(MyFile, "%d\n",head->next);
}
Your problem lies here. You loop until head is NULL, but never actually change the head pointer, hence you'll just loop forever writing the same data out until you run out of disk space. In addition, you're printing the value of the next pointer, not actually the data stored in the node.
You first need print the actual data, so change the fprintf to:
fprintf(MyFile, "%d\n",head->data);
Secondly, you actually need to iterate over the list, like follows
while(head)
{
fprintf(MyFile, "%d\n",head->data);
head = head->next;
}

Related

Element deletion in single linked list at head not working

#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head = NULL;
struct node *second = NULL;
struct node *third = NULL;
void insertAtBeg(struct node *n, int data) {
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = data;
temp->next = head;
head = temp;
}
void insertAtEnd(struct node *n, int data) {
struct node *temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = data;
temp->next = NULL;
while (n->next != NULL) {
n = n->next;
}
n->next = temp;
}
void deleteElement(struct node *head, int data) {
if (head->data == data) {
struct node *temp;
temp = head;
head = head->next;
free(temp);
printf("after deletion at head in function\n");
printList(head);
}
}
void printList(struct node *n) {
while (n != NULL) {
printf("%d\n", n->data);
n = n->next;
}
}
void main() {
head = (struct node*)malloc(sizeof(struct node));
second = (struct node*)malloc(sizeof(struct node));
third = (struct node*)malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
printList(head);
insertAtBeg(head, 0);
printf("after insertion at beginning\n");
printList(head);
insertAtEnd(head, 4);
printf("after insertion at End\n");
printList(head);
deleteElement(head, 0);
printf("after deletion at head in main\n");
printList(head);
}
output of the code is
1
2
3
after insertion at beginning
0
1
2
3
after insertion at End
0
1
2
3
4
after deletion at head in function
1
2
3
4
after deletion at head in main
0
1
2
3
4
Why is there a difference in output of the function called in main and the function called in another function.ie.after deletion at head in function and after deletion at head in main, when both are supposed to be deleting element from the same list
The problem is you need a way to modify the head of the list when inserting and/or deleting elements from the list.
A simple way to do this is for these functions to return a potentially updated value of the head pointer and for the caller to store this return value into it's head variable.
Here is a modified version of your code with these semantics:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insertAtBeg(struct node *head, int data) {
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
// should test for memory allocation failure
temp->data = data;
temp->next = head;
return temp;
}
struct node *insertAtEnd(struct node *head, int data) {
struct node *temp;
struct node *n;
temp = (struct node*)malloc(sizeof(struct node));
// should test for memory allocation failure
temp->data = data;
temp->next = NULL;
if (head == NULL)
return temp;
n = head;
while (n->next != NULL) {
n = n->next;
}
n->next = temp;
return head;
}
struct node *deleteElement(struct node *head, int data) {
// delete the first node with a given data
if (head->data == data) {
struct node *temp = head;
head = head->next;
free(temp);
} else {
struct node *n = head;
while (n->next != NULL) {
if (n->next->data == data) {
struct node *temp = n->next;
n->next = temp->next;
free(temp);
break;
}
}
}
return head;
}
void printList(const struct node *n) {
while (n != NULL) {
printf("%d\n", n->data);
n = n->next;
}
}
int main() {
struct node *head = NULL;
head = insertAtBeg(head, 1);
head = insertAtEnd(head, 2);
head = insertAtEnd(head, 3);
printList(head);
head = insertAtBeg(head, 0);
printf("after insertion at beginning\n");
printList(head);
head = insertAtEnd(head, 4);
printf("after insertion at End\n");
printList(head);
head = deleteElement(head, 0);
printf("after deletion at head in main\n");
printList(head);
// should free the list
return 0;
}
An alternative is to pass the address of the list head pointer so the function can modify it if needed.
Here is a modified version of your code with this alternative approach:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insertAtBeg(struct node **headp, int data) {
struct node *temp = malloc(sizeof(*temp));
if (temp != NULL) {
temp->data = data;
temp->next = *headp;
*headp = temp;
}
return temp;
}
struct node *insertAtEnd(struct node **headp, int data) {
struct node *temp = malloc(sizeof(*temp));
if (temp != NULL) {
temp->data = data;
temp->next = NULL;
if (*headp == NULL) {
*headp = temp;
} else {
struct node *n = *headp;
while (n->next != NULL) {
n = n->next;
}
n->next = temp;
}
}
return temp;
}
int deleteElement(struct node **headp, int data) {
// delete the first node with a given data
struct node *head = *headp;
if (head->data == data) {
*headp = head->next;
free(temp);
return 1; // node was found and freed
} else {
struct node *n = head;
while (n->next != NULL) {
if (n->next->data == data) {
struct node *temp = n->next;
n->next = temp->next;
free(temp);
return 1; // node was found and freed
}
}
return 0; // node not found
}
}
void printList(const struct node *n) {
while (n != NULL) {
printf("%d\n", n->data);
n = n->next;
}
}
int main() {
struct node *head = NULL;
insertAtBeg(&head, 1);
insertAtEnd(&head, 2);
insertAtEnd(&head, 3);
printList(head);
insertAtBeg(&head, 0);
printf("after insertion at beginning\n");
printList(head);
insertAtEnd(&head, 4);
printf("after insertion at End\n");
printList(head);
deleteElement(&head, 0);
printf("after deletion at head in main\n");
printList(head);
// free the list
while (head != NULL) {
deleteElement(&head, head->data);
}
return 0;
}
This alternative approach uses double pointers, so it is a bit more difficult for beginners to comprehend, but it has a strong advantage: the functions can update the list pointer and provide a meaningful return value that can be tested to detect errors. For example insertAtBeg() and insertAtEnd() return NULL if the new node could not be allocated but preserve the list. Similarly deleteElement() can return an indicator showing whether the element was found or not.
With this approach, you can write functions to pop the first or last element of the list, or the one at a given index, or one with a given data, while updating the list pointer as needed.
In the function void deleteElement(struct node *head,int data) you are passing a pointer to the head node. If you make changes to the node, then that works because you are pointing to the actual node. However, the variable head is a local copy of the pointer, which is not the one in main. When you change head to head->next that is only changing the local copy, so it has no effect outside deleteElement.
ADVANCED LEVEL POINTERS
To actually change head you have to pass a pointer to it, making a double pointer:
void deleteElement(struct node **phead,int data) {
struct node *temp;
temp = *phead;
*phead = (*phead)->next;
this means you have to pass the address of head &head as the parameter.

Linked List elements not getting displayed

This is my program in C which always inserts into a linked list at the end. But when I try to print the list elements, nothing is displayed. Here is the code :
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void insert(struct Node *, int);
int main(void)
{
struct Node *head = NULL, *current;
int n, i, x, data;
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &data);
insert(head, data);
}
current = head;
while(current != NULL)
{
printf("%d ", current->data);
current = current->next;
}
}
void insert(struct Node *head, int data)
{
struct Node *newnode, *current = head;
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = data;
newnode->next = NULL;
if(head == NULL)
{
head = newnode;
}
else
{
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
}
I cannot understand what might be the issue. Please help.
Your insert cannot modify head. Change it to
void insert(struct Node **head, int data)
and change it by
*head = newnode;
and call it like this
insert(&head, data);
Here, while you are passing the head pointer to your insert() function, it is not being updated in your main() function.
So, either declare your head pointer as global or return your head pointer and update it in your main() function.
In the below code I had taken the head pointer as global and removed the head pointer as your parameter from the insert() function.
Here is the code :-
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Node *head=NULL;
void insert(int);
int main(void)
{
struct Node *current;
int n, i, x, data;
clrscr();
scanf("%d", &n);
for(i = 0; i < n; i++)
{
scanf("%d", &data);
insert(data);
}
current = head;
while(current != NULL)
{
printf("%d \n", current->data);
current = current->next;
}
getch();
return 0;
}
void insert(int data)
{
struct Node *newnode, *current = head;
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = data;
newnode->next = NULL;
if(head == NULL)
{
head = newnode;
}
else
{
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
}
You need to pass the reference of the head pointer, then only the changes made to it will be visible.
You must declare your function like
void insert(struct Node **, int);
and also call it like
insert(&head, data);
also, make changes to function definition
void insert(struct Node **head, int data)
{
struct Node *newnode, *current = *head;
newnode = (struct Node *)malloc(sizeof(struct Node));
newnode->data = data;
newnode->next = NULL;
if(*head == NULL)
{
*head = newnode;
}
else
{
while(current->next != NULL)
{
current = current->next;
}
current->next = newnode;
}
}
You need to pass the head by reference as you are making changes to it that should be visible.
insert(head, data);
should become
insert(&head, data);
Also the function signature will change.
void insert(struct Node *head, int data)
should become
void insert(struct Node **head, int data)
Also make appropriate changes in the function.
Like,
current = *head;
Because you are passing the pointer by value. The function operates on a copy of the pointer, and never modifies the original.
Either pass a pointer to the pointer (i.e. a struct head **), or instead have the function return the pointer.
You can try running the following code which will give the output as null
printf("%s",head);
while(current != NULL)
{
printf("%d", current->data);
current = current->next;
}

Reversing The Last 5 Nodes In A Linked List

I want to reverse the last 5 nodes in a linked list as follows:
Input: 2->4->6->8->10->12->14->16->NULL
Output: 2->4->6->16->14->12->10->8->NULL
I have written the following code to perform the above task but my reverse() function is not working.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
int n;
void insert(struct node **headref, int data) {
struct node *new_node;
new_node = malloc(sizeof(struct node));
new_node->data = data;
new_node->next = *headref;
*headref = new_node;
}
struct node* create() {
struct node dummy;
struct node *new_node = &dummy;
dummy.next = NULL;
int i,num;
printf("Enter The Number Of Data: ");
scanf("%d", &n);
for(i = 1; i <= n; i++) {
printf("Enter Data %d: ", i);
scanf("%d", &num);
insert(&(new_node->next), num);
new_node = new_node->next;
}
return dummy.next;
}
void display(struct node *head) {
struct node *current;
for(current = head; current != NULL; current = current->next) {
printf("%d ", current->data);
}
printf("\n");
}
void reverse(struct node *head) {
struct node *current, *next, *prev, *temp;
current = head;
next = current->next;
prev = NULL;
int i;
for(i = 0; i < n-5; i++) {
temp = current;
current = next;
next = next->next;
}
while(current != NULL) {
current->next = prev;
prev = current;
current = next;
next = next->next;
}
temp->next = prev;
}
int main() {
struct node *start = create();
display(start);
reverse(start);
display(start);
}
Is there any error in my logic in the reverse() function? I tried the dry run on paper and it should have worked but it isn't working. Please point out the mistake that I made or even better suggest some alternative code to solve this problem.
The problem is in the line:
next = next->next;
in this part of the code:
while(current != NULL) {
current->next = prev;
prev = current;
current = next;
next = next->next;
}
In the last element, when current becomes the last node current->next is NULL and you try to get next->next->next which gives segmentation fault.
You need to change the above line simply by adding an if statement:
while(current != NULL) {
current->next = prev;
prev = current;
current = next;
if (next!=NULL) next = next->next;
}
I tried with your given input and it works!!

Reversing a Singly Linked List

I know there are multiple questions on the same problem on SO. But somewhere, I am not able to get the logic.
The function that reverses the Linked List is as follows:
void reverse()
{
struct node *curr=head, *prev=NULL;
while(curr!=NULL)
{
curr->next = prev;
prev = curr;
curr = curr->next;
}
head = prev;
}
I am using a global head pointer and the structure of a node in the linked list is:
struct node
{
int data;
struct node *next;
};
struct node *head = NULL;
Here, every time the curr node will point to the prev node and at the end when the list is traversed by the curr node, prev node will point to the last node in the list which I make as the head pointer.
But, this logic doesn't reverse the list and only prints the first node. So, I think the code is executed only once but I am not able to catch the mistake.
The other functions to make the program complete:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node *head = NULL;
void add(int n)
{
struct node *temp = (struct node*)malloc(sizeof(struct node));
temp->data = n;
temp->next = NULL;
if(head == NULL)
{
head = temp;
return;
}
temp->next = head;
head = temp;
}
void print()
{
struct node *temp = head;
printf("\n The List is : ");
while(temp!=NULL)
{
printf(" %d ",temp->data);
temp = temp->next;
}
}
void reverse()
{
struct node *curr=head, *prev=NULL;
while(curr!=NULL)
{
curr->next = prev;
prev = curr;
curr = curr->next;
}
head = prev;
}
int main(void)
{
add(1);
add(2);
add(3);
add(4);
add(5);
print();
reverse();
print();
return 0;
}
You are overwriting the curr->next pointer which is then used to iterate the list. Code should be more like this:
void reverse()
{
struct node *curr=head, *prev=NULL;
struct node *next;
while(curr!=NULL)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
}

What's with the program why is it not printing any result?

struct node{
int data; struct node *next;
};
void push(struct node* head, struct node* n){
if(n!= NULL){
if(head==NULL)
head = n;
else {
n->next = head;
head = n;
}
} else printf("Cannot insert a NULL node");
}
struct node* pop(struct node* head){
if(head!=NULL){
struct node *n = head;
head = head->next;
return n;
} else {
printf("The stack is empty");
return NULL;
}
}
int main(){
int i;
struct node *head = NULL, *n;
for(i=15;i>0;i--){
struct node *temp = malloc(sizeof(struct node));
temp -> data = i;
temp->next = NULL;
push(head,temp);
}
n = head;
while(n!=NULL){
printf("%d ",n->data);
n=n->next;
}
return 0;
}
You need to pass the address of the pointer head to the function push. I your case the head is not getting modified because you are only passing the value in the head.
void push(struct node** head, struct node* n){
if(n!= NULL){
if(*head==NULL)
*head = n;
else {
n->next = *head;
*head = n;
}
} else printf("Cannot insert a NULL node");}
int main(){
int i;
struct node *head = NULL, *n;
for(i=15;i>0;i--){
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp -> data = i;
temp->next = NULL;
push(&head,temp);
}
n = head;
while(n!=NULL){
printf("%d ",n->data);
n=n->next;
}
return 0;}
You are passing the head pointer by value to the function push(head,temp);. The changes to head done inside push will not be reflected in the main() function.
You should pass address of head to push().
push(&head, temp);
and inside push():
*head = n;
Similar change will be required for pop(). You can verify what I am saying by adding a printf inside the loop in main() as: printf("%p\n", head);. The value of head will remain unchanged.
BTW, it is good practice to add a \n at the end of statement inside printf, it flushes the stdout stream immmediately hence your output is printed immediately on stdout (your computer screen).

Resources