C infinite loop with linked list - c

I am trying to make a program that initialize a singular linked list and then ask user for more data and add them at the end of current linked list. However, my programming is trapped in infinite loop.
#include <stdio.h>
#include <stdlib.h>
typedef struct linked_list
{
int data;
struct linked_list *next;
}element;
typedef element *elementptr;
void addend(elementptr *,int);
void traverse(elementptr);
int main()
{
// create a linked list
elementptr first = NULL,
last = NULL;
int input,num;
printf("Please enter first integer data: \n");
scanf("%d",&input);
//Create a linked list with user initialized data
first = (elementptr)malloc(sizeof(element));
last = first;
last -> data = input;
last -> next = NULL;
printf("Please enter number of data you want to add in the end of linked list\n");
scanf("%d",&num);
addend(&last,num);
traverse(first);
return 0;
}
void addend(elementptr *l, int num)
{
int i = 0,extradata;
while(i<num)
{
i++;
printf("Please enter a data: \n");
scanf("%d",&extradata);
(*l) -> next = (elementptr)malloc(sizeof(element));
*l = (*l) ->next;
(*l) -> data = extradata;
(*l) -> next = NULL;
}
printf("The data sets are added\n");
}
void traverse(elementptr f)
{
elementptr current;
int count = 0;
current = f;
while (current != NULL)
{
count++;
printf("The data is %d \n", current->data);
}
printf("The linked list has %d elements \n",count);
}

In your code
while (current != NULL)
{
count++;
printf("The data is %d \n", current->data);
}
you never change the value of current. Either it starts as NULL and the loop never executes, or it starts non-NULL and the loop runs forever.
You should add
current = current->next
after your printf to advance to the next element in the linked list.

current = current -> next; you are missing this statement in the while loop. Although I would suggest :
#include<stdio.h>
#include<stdlib.h>
struct linked_list
{
int number;
struct linked_list *next;
struct linked_list *prev;
};
typedef struct linked_list node;
void create(node *p);
void print(node *p);
int main()
{
node *head;
printf("---Start of the list ---\n");
printf("enter -1 to exit\n");
head = (node*)malloc(sizeof(node));
create(head);
print(head);
}
void create(node *list)
{
printf("enter the data");
scanf(" %d",&list->number);
if(list->number == -1)//Enter -1 to exit untill then keep on taking values
{
list->next=NULL;
}
else
{
list->next = (node*)malloc(sizeof(node));
create(list->next);
}
}
void print(node *list)
{
if(list->next != NULL)
{
printf("%d-->",list->number);
if((list->next->next == NULL) && (list->next->number!=-1))
printf("%d -->End of the List",list->next->number);
print(list->next);
}
}

In your traverse function, the current node is not pointing to next node. So the while condition while (current != NULL) will not be true and hence the while loop is running infinitely.
To fix it, current node should point to the next node (current = current->next) in the list after printing the data.
For example:
void traverse(elementptr f)
{
elementptr current;
int count = 0;
current = f;
while (current != NULL)
{
count++;
printf("The data is %d \n", current->data);
// Fix
current = current->next; // Point to next node in link list
}
}

Related

Freeing memory after returning from a function

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//defined a data structure "node" which stores an int and a pointer to a node
typedef struct node
{
int number;
struct node *next;
}
node;
//defining functions
node* create(int number);
node* insert(node *new_linked_list, int number);
void print(node *new_linked_list);
void delete_list(node *new_linked_list);
int main(void)
{
//create new linked list with function
node *new_linked_list = NULL;
//get input to update list
for (int i = 0; i < 10; i++)
{
int temp;
if (i == 0)
{
scanf(" %i", &temp);
printf("\n");
new_linked_list = create(temp);
continue;
}
//will insert new nodes in the linked lists
scanf(" %i", &temp);
printf("\n");
new_linked_list = insert(new_linked_list, temp);
}
//prints node number values out
print(new_linked_list);
//delete/free list
delete_list(new_linked_list);
}
//function will return a pointer to the first node in the list
node* create(int number)
{
node *firstnode = malloc(sizeof(node));
firstnode -> number = number;
firstnode -> next = NULL;
return firstnode;
}
//function that will update the linked list and return a pointer to the new head of the linked list
node* insert(node *new_linked_list, int number)
{
node* new_node = malloc(sizeof(node));
if (new_node == NULL)
{
return new_linked_list;
}
//new node will point to the old first node and updates new_nodes number
new_node -> number = number;
new_node -> next = new_linked_list;
//returns a pointer to the new first node
return new_node;
}
void print(node *new_linked_list)
{
//temporary node for reversal
node *trav = new_linked_list;
for (int i = 0; i < 10; i++)
{
printf("%i ",trav -> number);
trav = trav -> next;
if (i == 9)
{
printf("\n");
}
}
}
void delete_list(node *new_linked_list)
{
//base case: at null pointer
if (new_linked_list -> next == NULL)
{
//frees memory previously allocated to a pointer
free(new_linked_list);
return;
}
//else delete the rest of the list
else
{
delete_list(new_linked_list -> next);
}
}
Hi so I was experimenting with a linked list and came across a problem. My program leaks memory because I am not freeing the "new node". However, I'm confused on how to free it as it is being return to be used in main. How would I go about freeing "new node" while still being able to use it in the main function. Thank you for any help in advance.
The issue seems to be related to the recursive behaviour of 'delete_list'
It could be implemented like the following:
void delete_list(node *new_linked_list)
{
node *next;
while(new_linked_list != NULL)
{
next = new_linked_list->next;
free(new_linked_list);
new_linked_list = next;
}
}

Storing data Using Linked List

I am trying to write a c program that ask user some information about a brand and store it into linked list. But whenever user enters data it always overwrites the previous data, instead I wanted it to create new node and store it there. This is what I manage so far. How can I do it without using any temporary nodes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int count = 1;
struct modelNode{
char name[50];
int year;
int amount;
struct modelNode *next;
};
struct modelNode * addModel(struct modelNode *p);
void getBestModel(struct modelNode *p);
int main(){
int command;
struct modelNode * modelList = NULL;
do
{
printf("1. Add a model\n");
printf("2. Display the model with the highest selling amount\n");
printf("3. Exit\n");
printf("Enter command: ");
scanf("%d", &command);
switch(command)
{
case 1:
addModel(modelList);
printf("test %s\n", modelList->name);
//printf("test %s\n", modelList->next->name);
break;
case 2:
printf("45\n");
break;
case 3:
puts("Bye");
break;
default:
printf("default\n");
}
}while(command != 3);
return 0;
}
struct modelNode * addModel(struct modelNode *p){
int iter = 0;
while(iter<count)
{
p = (struct modelNode*)malloc(sizeof(struct modelNode));
p->next=NULL;
iter++;
}
printf("test %s\n", p->name);
printf("Enter the name: ");
scanf("%s", &p->name);
printf("Enter the release year: ");
scanf("%d", &p->year);
printf("Enter the selling amount: ");
scanf("%d", &p->amount);
p->next=NULL;
printf("test %s\n", p->name);
count++;
}
}
This looks like a school exercise, so i doubt anyone here will solve it for you.
But you should try to insert "at the head" , you don't need temp nodes.
Pass the [head] as a param of function addNodes:
Inside addNodes:
Create [new-node]
Set the "next" pointer from [new-node] to the [head]:
[new-node]->next = [head]
Return [new-node]
Resulting linked list (head is the old-head) :
[new-node] ----> [head]
If you do this twice you'll get this:
[newer-node] -----> [new-node] ----> [head]
And so on....
If you want to insert as "tail" , you just need to traverse the linked list recursively, this way you don't use temp nodes.
If i missed the point, please leave a comment explaining further.
The generic functions for adding a node to a linked list would be
typedef struct node_t {
struct node_t* next;
} node_t;
node_t* add(node_t* list, node_t* new_node) {
if (list == NULL) {
return new_node;
} else {
node_t* tmp = list;
while (tmp->next != NULL) {
tmp = tmp->next;
}
tmp->next = new_node;
return list;
}
}
and you could use it like
node_t* list = NULL;
list = add(list, malloc(sizeof(node_t)));
list = add(list, malloc(sizeof(node_t)));
list = add(list, malloc(sizeof(node_t)));
list = add(list, malloc(sizeof(node_t)));
// list would now be a list of 4 nodes
and if you really don't want to use a tmp variable to walk the list, you can do it like this
void add_without_tmp(node_t* list, node_t* new_node) {
if (list == NULL) {
// some error handling
} else {
while(list->next != NULL) {
list = list->next;
}
list->next = new_node;
}
}
node_t* list = malloc(sizeof(node_t));
add_without_tmp(list, malloc(sizeof(node_t)));
add_without_tmp(list, malloc(sizeof(node_t)));
add_without_tmp(list, malloc(sizeof(node_t)));
// list would now be a list of 4 nodes
Edit: fixed the error with the declaration of node_t and added the missing * to the statement node_t* tmp = list;.

How to pass a linked list to a function in C

So I have made a working program for getting data from a file and printing out the file according to which part of the file you want all within main. But my goal is to make this modular, by creating a user interface and either appending to the linked list from the file or printing out a part of that linked list (if any) as requested.
There's just one problem: I can't seem to figure out a way to successfully pass a linked list to the function so that when you create new nodes in the function (Append), it will also work in main and then back again in (Print).
Here's the working code:
#include <stdio.h>
#include <stdlib.h> /* has the malloc prototype */
#define TSIZE 100 /* size of array to hold title */
struct book {
char title[TSIZE], author[TSIZE],year[6];
struct book * next; /* points to next struct in list */
};
//typedef struct book ITEM;
typedef struct book * Node; // struct book *
void Append(Node *List, Node *Lcurrent,char filename[]);
void ClearGarbage(void);
int main(void){
Node head=NULL;
Node current;
current=head;
char fname[]="HW15Data.txt";
char op;
do{
puts("Select operation from the following list:");
puts("a. Append p. Print q. quit");
op = getchar();
ClearGarbage();
if (op=='a'){
/* Gather and store information */
Append(&head,&current,fname);
}
else if (op=='q'){
/* User quit, so free allocated memory */
current = head;
while (current != NULL)
{
free(current);
current = current->next;
}
printf("Bye!\n");
return 0;
}
else{
/* Program done, so free allocated memory */
current = head;
while (current != NULL)
{
free(current);
current = current->next;
}
printf("Invalid characted entered. Bye!\n");
return 0;
}
} while (op!='q');
return 0;
}
void Append(Node *List, Node * Lcurrent,char filename[TSIZE]){
FILE * fp;
Node head=*List;
Node current=*Lcurrent;
int loops=0;
fp=fopen(filename,"r");
if (head==NULL){
head=(Node) malloc(sizeof(struct book));
current=head;
current->next=NULL;
}
do{
current->next = (Node) malloc(sizeof(struct book));
current=current->next;
loops++;
} while(fgets(current->title,sizeof(current->title),fp) && fgets(current->author,sizeof(current->title),fp) && fgets(current->year,sizeof(current->year),fp));;
free(current);
printf("Number of records written: %d\n",loops);
//Same as Print function in the nonworking code
int num;
int i=0;
if (head == NULL){
printf("No data entered. ");
}
else{
printf("Enter record # to print: ");
scanf("%d",&num);
ClearGarbage();
num=num+1;
current = head;
while (current != NULL && i<num)
{
for (i=0;i<num;i++)
current = current->next;
printf("Book: %sAuthor: %sYear: %s\n",
current->title, current->author, current->year);
}
}
}
void ClearGarbage(void){
while (getchar()!='\n');
}
Okay cool that works, but my guess is that as soon as Append is done, the nodes made in Append are useless in main because they are now gone. So when I try to make a Print function in the following code, there's nothing to print.
#include <stdio.h>
#include <stdlib.h> /* has the malloc prototype */
#define TSIZE 100 /* size of array to hold title */
struct book {
char title[TSIZE], author[TSIZE],year[6];
struct book * next; /* points to next struct in list */
};
//typedef struct book ITEM;
typedef struct book * Node; // struct book *
void Append(Node *List, Node *Lcurrent,char filename[]);
int Print(Node *List,Node *Lcurrent);
void ClearGarbage(void);
int main(void){
Node head=NULL;
Node current;
current=head;
char fname[]="HW15Data.txt";
char op;
do{
puts("Select operation from the following list:");
puts("a. Append p. Print q. quit");
op = getchar();
ClearGarbage();
if (op=='a'){
/* Gather and store information */
Append(&head,&current,fname);
}
else if (op=='p'){
/*Print book record of user's choice*/
Print(&head,&current);
}
else if (op=='q'){
/* User quit, so free allocated memory */
current = head;
while (current != NULL)
{
free(current);
current = current->next;
}
printf("Bye!\n");
return 0;
}
else{
/* Program done, so free allocated memory */
current = head;
while (current != NULL)
{
free(current);
current = current->next;
}
printf("Invalid characted entered. Bye!\n");
return 0;
}
} while (op!='q');
return 0;
}
void Append(Node *List, Node * Lcurrent,char filename[TSIZE]){
FILE * fp;
Node head=*List;
Node current=*Lcurrent;
int loops=0;
fp=fopen(filename,"r");
if (head==NULL){
head=(Node) malloc(sizeof(struct book));
current=head;
current->next=NULL;
}
do{
current->next = (Node) malloc(sizeof(struct book));
current=current->next;
loops++;
} while(fgets(current->title,sizeof(current->title),fp) && fgets(current->author,sizeof(current->title),fp) && fgets(current->year,sizeof(current->year),fp));
free(current);
printf("Number of records written: %d\n",loops);
}
int Print(Node *List,Node *Lcurrent){
int num;
int i=0;
Node head=*List;
Node current=*Lcurrent;
if (head == NULL){
printf("No data entered.\n");
return -1;
}
printf("Enter record # to print: ");
scanf("%d",&num);
ClearGarbage();
num=num+1;
current = head;
while (current != NULL && i<num)
{
for (i=0;i<num;i++){
current = current->next;
}
printf("Book: %sAuthor: %sYear: %s\n",
current->title, current->author, current->year);
}
return 0;
}
void ClearGarbage(void){
while (getchar()!='\n');
}
Thanks anyone for any help!
EDIT: Got rid of an unused typedef for clarity
It seems like most of the people are focusing the lack of organization (it bother me a lot too) instead of your actual issue.
Seems like the source of your issue is where you assign the variable head.
when you define "Node head = *List" and List is NULL, as it's first initialized, it loses the connection it had to the original list you sent from main, and you just create a linked list with a local reference only.
I just changed the uses of "head" to "*List" within the Append and Print functions and it seems to sort it out.
This is your code after my changes:
#include <stdio.h>
#include <stdlib.h> /* has the malloc prototype */
#define TSIZE 100 /* size of array to hold title */
struct book {
char title[TSIZE], author[TSIZE], year[6];
struct book * next; /* points to next struct in list */
};
//typedef struct book ITEM;
typedef struct book * Node; // struct book *
void Append(Node *List, Node *Lcurrent, char filename[]);
int Print(Node *List, Node *Lcurrent);
void ClearGarbage(void);
int main(void) {
Node head = NULL;
Node current;
current = head;
char fname[] = "HW15Data.txt";
char op;
do {
puts("Select operation from the following list:");
puts("a. Append p. Print q. quit");
op = getchar();
ClearGarbage();
if (op == 'a') {
/* Gather and store information */
Append(&head, &current, fname);
}
else if (op == 'p') {
/*Print book record of user's choice*/
Print(&head, &current);
}
else if (op == 'q') {
/* User quit, so free allocated memory */
current = head;
while (current != NULL)
{
free(current);
current = current->next;
}
printf("Bye!\n");
return 0;
}
else {
/* Program done, so free allocated memory */
current = head;
while (current != NULL)
{
free(current);
current = current->next;
}
printf("Invalid characted entered. Bye!\n");
return 0;
}
} while (op != 'q');
return 0;
}
void Append(Node *List, Node * Lcurrent, char filename[TSIZE]) {
FILE * fp;
Node head = *List;
Node current = *Lcurrent;
int loops = 0;
char line[256];
fp = fopen(filename, "r");
if (*List == NULL) {
*List = (Node)malloc(sizeof(struct book));
current = *List;
current->next = NULL;
}
do {
current->next = (Node)malloc(sizeof(struct book));
current = current->next;
loops++;
} while (fgets(current->title, sizeof(line), fp) && fgets(current->author, sizeof(line), fp) && fgets(current->year, sizeof(line), fp));
free(current);
printf("Number of records written: %d\n", loops);
}
int Print(Node *List, Node *Lcurrent) {
int num;
int i = 0;
Node head = *List;
Node current = *Lcurrent;
if (*List == NULL) {
printf("No data entered.\n");
return -1;
}
printf("Enter record # to print: ");
scanf("%d", &num);
ClearGarbage();
num = num + 1;
current = *List;
while (current != NULL && i<num)
{
for (i = 0; i<num; i++) {
current = current->next;
}
printf("Book: %sAuthor: %sYear: %s\n",
current->title, current->author, current->year);
}
return 0;
}
void ClearGarbage(void) {
while (getchar() != '\n');
}
There are still many logical errors, and some bugs, but it fixes the problem you asked help for.

how to print out a singly linked list in reverse order?

struct node
{
int info;
struct node *next;
};
typedef struct node node;
void *printRev(node *head){
int count=0;
int i;
node *beforeFin;
node *tempHead;
tempHead = head;
while(tempHead->next != NULL){
count++;
tempHead->next = tempHead->next->next; //LAST ITERATION SHOULD BE AT THE END OF LIST
}
printf("COUNT IS: %d\n", count);
for(i = 0; i <= count; i++){
beforeFin = Prev(head, tempHead->next);
printf("%d", beforeFin->info);
}
printf("\n");
}
As of now this prints out:
COUNT IS: 3
Segmentation fault (core dumped)
Prev returns a pointer to the node before the given pointer (tempHead->next) my intention was for this to print out the singly linked list in reverse order using the for loop above. So the ->info of the given node should return 5 in the example below (after the first iteration).
Before the printf that prints the count, tempHead->next should point to the final node.
Right now I am passing in 2 3 5 4 and this is giving me the count before the 4. Id like for this to print out 4 5 3 2
I would appreciate any help given, I am a beginner as you might be able to tell. Thank you all in advance!
I could do this using recursion but I'd like to learn figure out this method.
To print a single linked list in reverse order you can use a recursive function. You have to step into the recursion to the end and print the elements of the list right before you leave the recursion function:
void printReverse(node *act)
{
if ( act == NULL ) // terminate if end of list is reached
return;
printRev( act->next ); // print next node
printf( "%d ", act->info ); // print this node
}
If you do not want to use recursion, you can of course reverse the list, then print the list and finally reverse it again.
Reversing a list is not difficult. Traverse through the list, take each element and reorder it in front of the head of the list.
node * reverse(node *head)
{
node *act, *prev;
if ( head == NULL )
return;
prev = head;
act = head->next;
while ( act != NULL )
{
prev->next = act->next;
act->next = head;
head = act;
act = prev->next;
}
return head;
}
void printReverse(node *head)
{
node *act;
act = reverse(head);
while ( act != NULL )
{
printf( "%d ", act->info ); // print this node
act = act->next;
}
reverse(head);
}
As you want to avoid recursion, you need to reverse the list first. I see some attempt in the original code but it doesn't look correct. Try the following:
node *current = head;
if (current != NULL) {
node *prev = NULL;
for (node *next = current->next; ; next = (current = next)->next) {
current->next = prev;
prev = current;
if (next == NULL)
break;
}
}
Then current will point to the head of the list and you can traverse using the next link over the list. Note that it will modify your original list but this is expected as I understood the original requirement.
The issue with the recursive algorithm is that, if you're a bit paranoid like me, the list could be large enough to cause the recursive calls to sum up and overflow the stack. If the list is from some user input then this could be used for a denial of service attack. Thus I see two reasonable choices:
Create a reversed copy of the list and print that.
Reverse the list in place, print it, possibly reverse it back.
The later is interesting if you're working in a memory constrained setting or with large lists.
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
struct node {
int value;
struct node * next;
};
void reverse_inplace (struct node ** list) {
assert(list != NULL);
struct node * follow = NULL, * lead = *list;
while (lead != NULL) {
struct node * next = lead->next;
lead->next = follow;
follow = lead;
lead = next;
}
*list = follow;
}
void print (struct node const * head) {
printf("( ");
while (head) {
printf("%d ", head->value);
head = head->next;
}
printf(")");
}
void link (struct node * array, size_t count) {
struct node * follow = NULL;
while (count-->0) {
array[count].next = follow;
follow = &(array[count]);
}
}
void fill (struct node * list, int value, int const step) {
while (list != NULL) {
list->value = value;
value += step;
list = list->next;
}
}
int main () {
size_t const sizes[] = {1, 2, 6};
size_t const num =
sizeof(sizes) / sizeof(sizes[0]);
size_t caseId = 0;
for (; caseId < num; ++caseId) {
struct node * head =
malloc(sizeof(*head) * sizes[caseId]);
printf("Case %zu: List of size %zu\n",
caseId, sizes[caseId]);
link(head, sizes[caseId]);
fill(head, caseId, caseId);
printf(" initial: ");
print(head);
printf(" \n");
reverse_inplace(& head);
printf(" reversed: ");
print (head);
printf(" \n");
reverse_inplace(& head);
free(head);
}
printf("Case %zu: empty list \n", caseId);
struct node * head = NULL;
printf(" initial: ");
print(head);
printf(" \n");
reverse_inplace(& head);
printf(" reversed: ");
print(head);
printf(" \n");
return 0;
}
(Live on ideone)

Linked List from Linked List

I am trying to create an (ordered) linked list of (ordered) linked lists. The list-of-list links are carried by the first nodes of its member lists. I am trying to achieve this via the following code, but my program crashes when I try displaying the second list. First list displays perfectly.
Here's a schematic of the data structure I am trying to construct:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node{
int number;
struct node*next;
struct node*lsnext;
};
typedef struct node Node;
Node* insertValue(Node * list, int value);
void display(Node*);
Node* insertArr(Node * list, int value);
Node* addNodeBottom(int val, Node *start);
int main()
{
Node *globalList = NULL, *lists,*start,*save;
int nbrOfLists, listNo, nbrOfVal, valNo, val;
start=NULL;
printf("\n Enter the number of lists:");
scanf("%d", &nbrOfLists);
if(nbrOfLists < 0)
return -1;
for(listNo = 0; listNo < nbrOfLists; listNo++)
{
printf("\n\n Enter the number of inputs to the list %d: \n ",listNo+1);
scanf("%d", &nbrOfVal);
lists = NULL;
for(valNo = 0; valNo < nbrOfVal; valNo++)
{
printf("Enter node value %d:", valNo+1);
scanf("%d", &val);
// Here we insert the value in both lists
lists= insertValue(lists, val);
globalList = insertValue(globalList, val);
}
start=addNodeBottom(val,lists);
if(listNo==0){
save=start;
}
printf("\n The list %d is: ",listNo+1);
display(lists);
}
printf("\n\n The final list is: ");
display(globalList);
printf("The first list is");
display(save);
printf("The second list is");
display(save->lsnext); //crashes here
return 0;
}
Node* insertValue(Node * list, int value) //to insert node at the end
{
Node *newNode, *m;
newNode = malloc(sizeof(Node));
newNode->number=value;
if(list == NULL)
{
newNode->next=NULL;
return newNode;
}
if(value < list->number)
{
newNode->next = list;
return newNode;
}
m = list;
while(m->next)
{
if(value < m->next->number)
break;
m = m->next;
}
newNode->next = m->next;
m->next = newNode;
return list;
}
Node* addNodeBottom(int val, Node *start)
{
Node*rear;
Node* node1=(Node*) malloc(sizeof(Node));
node1->number=val;
node1->lsnext=NULL;
if(start==NULL){
start=rear=node1;
}
else{
rear->lsnext=node1;
rear=node1;
}
return start;
}
void display(Node*nodex){
while(nodex)
{
printf("%d ->",nodex->number);
nodex=nodex->next;
}
}
This code invokes undefined behaviour. In particular, your function addNodeBottom is buggy: If invoked with start not NULL, it modifies the member rear->lsnext, but rear is uninitialised at that point. I assume, you intended to modify start instead. Here, you return start unmodified, so it's member lsnext is not set to anything useful, which probably eventually leads to a segmentation fault. However, in principle already the offending function call to addNodeBottom could lead to unexpected program termination.

Resources