loop for insertion in linked list not working - c

I'm trying to insert some nodes at the end of the linked list but something is not right in this code.
Here I'm trying to make a loop and with the help of this loop I want the user to enter all numbers for the list but I guess I'm missing something.
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
struct node* next;
};
void insert(struct node** ref)
{ int n,i=0 ;
printf("how many numers:\n");
scanf("%d",&n);
fflush(stdin);
for(i=0;i<n;i++)
{
struct node* temp = (struct node*)malloc(sizeof(struct node));
struct node* last = *ref;
printf("enter the number:\n");
scanf("%d",&(temp->data));
fflush(stdin);
temp->next = NULL;
if(*ref==NULL)
{
*ref = temp;
return;
}
while(last->next != NULL)
last = last->next;
last->next = temp;
}
return;
}
int main()
{
struct node* head=NULL;
insert(&head);
return 0;
}

When the function is called for an empty list then it inserts only one element in the list and exits.
if(*ref==NULL)
{
*ref = temp;
return;
}
Also pay attention to that calling fflush for stdin has undefined behavior.
fflush(stdin);
The function can be defined the following way
size_t insert( struct node **ref )
{
printf( "how many numbers: " );
size_t n = 0;
scanf( "%zu", &n );
if ( n != 0 )
{
while ( *ref != NULL )
{
ref = &( *ref )->next;
}
}
size_t i = 0;
for ( ; i < n && ( *ref = malloc( sizeof( struct node ) ) ) != NULL; i++ )
{
( *ref )->data = 0;
( *ref )->next = NULL;
printf( "enter the number: " );
scanf( "%d", &( *ref )->data );
ref = &( *ref )->next;
}
return i;
}
Here is a demonstrative program
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* next;
};
size_t insert( struct node **ref )
{
printf( "how many numbers: " );
size_t n = 0;
scanf( "%zu", &n );
if ( n != 0 )
{
while ( *ref != NULL )
{
ref = &( *ref )->next;
}
}
size_t i = 0;
for ( ; i < n && ( *ref = malloc( sizeof( struct node ) ) ) != NULL; i++ )
{
( *ref )->data = 0;
( *ref )->next = NULL;
printf( "enter the number: " );
scanf( "%d", &( *ref )->data );
ref = &( *ref )->next;
}
return i;
}
void display( struct node *head )
{
for ( ; head != NULL; head= head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
int main(void)
{
struct node *head = NULL;
size_t n = insert( &head );
printf( "There are %zu nodes in the list. They are\n", n );
display( head );
return 0;
}
Its output might look like
how many numbers: 5
enter the number: 1
enter the number: 2
enter the number: 3
enter the number: 4
enter the number: 5
There are 5 nodes in the list. They are
1 -> 2 -> 3 -> 4 -> 5 -> null

Related

C rotate linked list by user choice

I wrote a program that get from a user numbers to linked list and number for how much to rotate each node in lust for the left. and I was only succeeded to do that but not in a circle. and my program need to be abale to move the node more left then the lenght of the list in circles.
someone know how can i fix my program??. (the function that need to be fixed is the "RotateALinkedList" function). i mean if the user want to move the list 4 times left the first node gonna start from the last node.
#include<stdio.h>
#include<stdlib.h>
typedef struct numbers_list
{
int data;
struct numbers_list* next;
}number;
void RotateALinkedList(number** head, int node); //the function that rotate the linked list
int CreateLinkedList(number** head, int iNumberofNode);
int attachToEnd(number** head, int k);
void PrintTheList(number* pNode);
void FreeAllocatedMemory(number** head);
int main(void)
{
int list_len = 0;
int data = 0;
number* head = NULL;
printf("How many nodes in list? ");
scanf("%d", &list_len);
getchar();
CreateLinkedList(&head, list_len);
printf("Choose a number k, and the list will be rotated k places to the left: ");
scanf("%d", &data);
getchar();
if (data <= list_len)
{
RotateALinkedList(&head, data);
PrintTheList(head);
}
else
{
printf("Please Enter Valid number of node\n");
}
FreeAllocatedMemory(&head);
getchar();
return 0;
}
void RotateALinkedList(number** head, int node)
{
int count = 0;
number* p = *head;
number* tempNode = NULL;
for (count = 1; ((count < node) && (p != NULL)); count++)
{
p = p->next;
}
if (p == NULL)
{
return;
}
else
{
tempNode = p;
}
while (p->next != NULL)
{
p = p->next;
}
p->next = *head;
*head = tempNode->next;
tempNode->next = NULL;
}
int CreateLinkedList(number** head, int iNumberofNode)
{
int data = 0;
int iRetValue = -1;
int count = 0;
number* pNewNode = NULL;
for (count = 0; count < iNumberofNode; count++)
{
printf("Enter number: ");
scanf("%d", &data);
getchar();
if ((*head) == NULL)
{
pNewNode = (number*)malloc(sizeof(number));
if (pNewNode != NULL)
{
pNewNode->data = data;
pNewNode->next = NULL;
*head = pNewNode;
iRetValue = 0;
}
}
else
{
iRetValue = attachToEnd(head, data);
}
}
return iRetValue;
}
int attachToEnd(number** head, int k)
{
int iRetValue = -1;
number* pLastNode = NULL;
number* pNewNode = NULL;
pLastNode = *head;
pNewNode = (number*)malloc(sizeof(number));
if (pNewNode != NULL)
{
pNewNode->data = k;
pNewNode->next = NULL;
iRetValue = 0;
}
if (pLastNode == NULL)
{
*head = pNewNode;
}
else
{
while (pLastNode->next != NULL)
{
pLastNode = pLastNode->next;
}
pLastNode->next = pNewNode;
}
return iRetValue;
}
void PrintTheList(number* pNode)
{
printf("the rotated list:\n");
while (pNode != NULL)
{
printf("%d ", pNode->data);
pNode = pNode->next;
}
}
void FreeAllocatedMemory(number** head)
{
number* ptempNode = NULL;
number* pFirstNode = NULL;
pFirstNode = *head;
while (pFirstNode != NULL)
{
ptempNode = pFirstNode;
pFirstNode = pFirstNode->next;
free(ptempNode);
}
*head = NULL;
}
For starters the name number of the alias in this typedef declaration
typedef struct numbers_list
{
int data;
struct numbers_list* next;
}number;
is confusing.
It will be better to define two structures instead
struct Node
{
int data;
struct Node *next;
};
struct List
{
size_t size;
struct Node *head;
};
and define in main a list like
struct List numbers = { .size = 0, .head = NULL };
You will simplify your task if the list contains a data member that specifies the number of nodes in the list.
The function CreateLinkedList should do one task: create a list from an array specified by the user. It should ask the user to enter numbers that will be stored in the list.
I can suggest the following solution shown in the demonstrative program below.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct List
{
size_t size;
struct Node *head;
};
void clear( struct List *list )
{
while ( list->head )
{
struct Node *tmp = list->head;
list->head = list->head->next;
free( tmp );
}
list->size = 0;
}
size_t create( struct List *list, const int a[], size_t n )
{
clear( list );
for ( struct Node **current = &list->head;
n-- && ( *current = malloc( sizeof( struct Node ) ) ) != NULL; )
{
( *current )->data = *a++;
( *current )->next = NULL;
current = &( *current )->next;
++list->size;
}
return list->size;
}
FILE * display( const struct List *list, FILE *fp )
{
fprintf( fp, "There is/are %zu items: ", list->size );
for ( struct Node *current = list->head; current != NULL; current = current->next )
{
fprintf( fp, "%d -> ", current->data );
}
fputs( "null", fp );
return fp;
}
void rotate( struct List *list, size_t n )
{
if ( ( list->size != 0 ) && ( ( n %= list->size ) != 0 ) )
{
struct Node **current = &list->head;
while ( n-- ) current = &( *current )->next;
struct Node *tmp = list->head;
list->head = *current;
*current = NULL;
struct Node *last = list->head;
while ( last->next != NULL ) last = last->next;
last->next = tmp;
}
}
int main(void)
{
struct List numbers = { .size = 0, .head = NULL };
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
create( &numbers, a, sizeof( a ) / sizeof( *a ) );
fputc( '\n', display( &numbers, stdout ) );
rotate( &numbers, 1 );
fputc( '\n', display( &numbers, stdout ) );
rotate( &numbers, 2 );
fputc( '\n', display( &numbers, stdout ) );
rotate( &numbers, 3 );
fputc( '\n', display( &numbers, stdout ) );
rotate( &numbers, 4 );
fputc( '\n', display( &numbers, stdout ) );
clear( &numbers );
return 0;
}
The program output is
There is/are 10 items: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
There is/are 10 items: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 0 -> null
There is/are 10 items: 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 0 -> 1 -> 2 -> null
There is/are 10 items: 6 -> 7 -> 8 -> 9 -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> null
There is/are 10 items: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null

A C function that inserts number into a linked list in ascending order

This is my function:
void IntListInsertInOrder (IntList L, int v)
{
struct IntListNode *n = newIntListNode (v);
if (L->first == NULL) { //case a, empty list
L->first = L->last = n;
L->size ++;
return;
}
else if (v <= L->first->data) { // case b, smallest value
n->next = L->first;
L->first = n;
}
else if (v >= L->last->data) { // case c, largest value
L->last->next = n;
L->last = n;
}
else if (v > L->first->data && v <= L->first->next->data) { // case d, second-smallest value
n->next = L->first->next;
L->first->next = n;
}
else { //case f, value in the middle
struct IntListNode *curr = L->first;
while (curr->next->data < v) {
curr = curr->next;
}
n->next = curr->next;
curr->next = n;
}
L->size ++;
return;
}
when i put random lists of 10 numbers into it, 3/10 sorted correctly. the errors seem to be in the last part but it looks exactly like solutions i found online.
OK I figured it out. I forgot to add&& curr-> != NULLin the condition of the last while loop. After I added that all the test cases passed.
Your function is too complicated, has many if conditions and as a result it is error-prone and unreadable.
You did not show the list definition but I can guess that you have a two-sided singly-linked list because nowhere in the code there is a reference to a data member named prev.
Here is a demonstrative program that shows how the function can be simply defined.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct Node
{
int data;
struct Node *next;
} Node;
typedef struct List
{
Node *head;
Node *tail;
size_t size;
} List;
int insert_in_order( List *list, int data )
{
Node *new_node = malloc( sizeof( Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
Node **current = &list->head;
while ( *current != NULL && !( data < ( *current )->data ) )
{
current = &( *current )->next;
}
new_node->next = *current;
if ( *current == NULL )
{
list->tail = new_node;
}
*current = new_node;
++list->size;
}
return success;
}
void clear( List *list )
{
while ( list->head != NULL )
{
Node *current = list->head;
list->head = list->head->next;
free( current );
}
}
void display( const List *list )
{
printf( "There are %zu nodes in the list\n", list->size );
printf( "They are: " );
for ( const Node *current = list->head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "null" );
}
int main(void)
{
List list = { .head = NULL, .tail = NULL, .size = 0 };
srand( ( unsigned int )time( NULL ) );
const size_t N = 10;
for ( size_t i = 0; i < N; i++ )
{
insert_in_order( &list, rand() % ( int )N );
}
display( &list );
clear( &list );
return 0;
}
The program output might look like
There are 10 nodes in the list
They are: 1 -> 2 -> 3 -> 3 -> 6 -> 6 -> 7 -> 8 -> 8 -> 9 -> null

How to delete multiple occurrences of multiple variables in a linked list in c

I am a beginner in c programming and i have been trying for several days to solve the following question:
how to remove numbers that appear at least 3 times in the following list:
3→3→1→2→4→3→5→3→5→4
which makes the result:
1→2→4→5→5→4.
Now i know how to delete multiple occurrences of "one" key in a linked list, for example deleting all occurrences of "1" in the linked list, but can't seem to understand how to delete multiple occurrences of multiple variables. It's just killing me. I would really appreciate it if anyone could help. thanks in advance.
It seems nobody hurries to help you.:)
It is simpler to write the function if to pass the pointer head to the function by reference.
Here is a demonstrative program that shows how the function can be implemented.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
int insert( struct Node **head, int data )
{
struct Node *node = malloc( sizeof( struct Node ) );
int success = node != NULL;
if ( success )
{
node->data = data;
node->next = *head;
*head = node;
}
return success;
}
void out( struct Node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
void remove_repetitive( struct Node **head )
{
const size_t LIMIT = 3;
while ( *head != NULL )
{
size_t count = 1;
int data = ( *head )->data;
for ( struct Node *node = ( *head )->next;
count < LIMIT && node != NULL; node = node->next )
{
if ( node->data == data ) ++count;
}
if ( count == LIMIT )
{
for ( struct Node **node = head; *node != NULL; )
{
if ( ( *node )->data == data )
{
struct Node *tmp = *node;
*node = ( *node )->next;
free( tmp );
}
else
{
node = &( *node )->next;
}
}
}
else
{
head = &( *head )->next;
}
}
}
int main(void)
{
struct Node *head = NULL;
int a[] = { 4, 5, 3, 5, 3, 4, 2, 1, 3, 3 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
insert( &head, a[i] );
}
out( head );
remove_repetitive( &head );
out( head );
return 0;
}
The program output is
3 -> 3 -> 1 -> 2 -> 4 -> 3 -> 5 -> 3 -> 5 -> 4 -> null
1 -> 2 -> 4 -> 5 -> 5 -> 4 -> null
The function remove_repetitive can be splitted out into two functions as it is shown below.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
int insert( struct Node **head, int data )
{
struct Node *node = malloc( sizeof( struct Node ) );
int success = node != NULL;
if ( success )
{
node->data = data;
node->next = *head;
*head = node;
}
return success;
}
void out( struct Node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
void remove_all( struct Node **head, int data )
{
while ( *head != NULL )
{
if ( ( *head )->data == data )
{
struct Node *tmp = *head;
*head = ( *head )->next;
free( tmp );
}
else
{
head = &( *head )->next;
}
}
}
void remove_repetitive( struct Node **head )
{
const size_t LIMIT = 3;
while ( *head != NULL )
{
size_t count = 1;
int data = ( *head )->data;
for ( struct Node *node = ( *head )->next;
count < LIMIT && node != NULL; node = node->next )
{
if ( node->data == data ) ++count;
}
if ( count == LIMIT )
{
remove_all( head, data );
}
else
{
head = &( *head )->next;
}
}
}
int main(void)
{
struct Node *head = NULL;
int a[] = { 4, 5, 3, 5, 3, 4, 2, 1, 3, 3 };
const size_t N = sizeof( a ) / sizeof( *a );
for ( size_t i = 0; i < N; i++ )
{
insert( &head, a[i] );
}
out( head );
remove_repetitive( &head );
out( head );
return 0;
}
The program output is the same as shown above.

Delete Node - Linked List - C

I am trying to delete a node from a linked list but I am still new to the concept of double pointers so I tried using a global variable to hold the head pointer instead. However, I get the wrong results when I try to print my list after deleting the middle node.
I saw this question
deleting a node in the middle of a linked list and I don't know how is my delete node function different from the answer.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char u8;
typedef struct Node node;
void addfirstnode( u8 );
void addnode( u8 );
void print( void );
void deletenode( u8 key );
void deleteonlynode();
void deletefirstnode();
struct Node
{
u8 x;
node *next;
};
node *head;
u8 length = 0;
void main( void )
{
u8 x;
printf( "\nTo add node enter 0\nTo print linked list enter 1\nTo exit press 2\nTo delete node press 3\nYour Choice:" );
scanf( "%d", &x );
if ( x == 2 )
{
printf( "\nThank You\nGood Bye" );
}
while ( x != 2 )
{
switch ( x )
{
u8 n;
u8 key;
case 0: //Add node
printf( "\nPlease enter first value:" );
scanf( "%d", &n );
if ( length == 0 )
{
addfirstnode( n );
//printf("%d",head->x);
}
else
{
addnode( n );
}
printf( "\nNode added , Thank you\n" );
break;
case 1: //Print
print();
break;
case 3: //DeleteNode
printf( "\nPlease enter value to be deleted:" );
scanf( "%d", &key );
deletenode( key );
//deletefirstnode();
break;
default:
printf( "\nInvalid Choice please try again\n" );
}
printf( "\nTo add node enter 0\nTo print linked list enter 1\nTo exit press 2\nTo delete node press 3\nYour Choice:" );
scanf( "%d", &x );
if ( x == 2 )
{
printf( "\nThank You\nGood Bye" );
}
}
//where do I use free();
}
void addfirstnode( u8 n )
{
head = ( node * ) malloc( sizeof( node ) );
head->next = NULL;
head->x = n;
length++;
}
void addnode( u8 n )
{
node *last = head;
while ( ( last->next ) != NULL )
{
last = last->next;
}
last->next = ( node * ) malloc( sizeof( node ) );
( last->next )->next = NULL;
( last->next )->x = n;
length++;
}
void print( void )
{
node *last = head;
u8 count = 1;
printf( "\n---------------------" );
if ( last == NULL )
{
printf( "\nList is empty" );
}
while ( last != NULL )
{
printf( "\nNode Number %d = %d", count, last->x );
last = last->next;
count++;
}
printf( "\n---------------------" );
printf( "\n" );
}
void deletenode( u8 key )
{
node *last = head;
//node*postlast = NULL;
if ( ( last->x == key ) && ( last->next == NULL ) )
{
deleteonlynode();
}
else
{
while ( last != NULL )
{
if ( ( last->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = last->next;
last->next = last->next->next;
free( temp );
length--;
}
last = last->next;
}
}
}
void deleteonlynode()
{
printf( "\n Deleting the only node" );
free( head );
head = NULL;
length--;
}
void deletefirstnode()
{
printf( "\n Deleting the first node" );
node *temp = head;
head = head->next;
free( temp );
length--;
}
The code is removing the wrong item from the linked list:
See:
if ( ( last->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = last->next; // last->next? No, just last.
last->next = last->next->next;
free( temp );
length--;
}
last is pointing at the element to be removed. But then the code assigns temp to point at last->next (NOT last), and then cuts that from the list.
So by looking at node->next rather than the current node, it's possible to trim it out since you're starting from the pointer before the one to remove. Basically your code was almost there already.
void deletenode( u8 key )
{
node *ptr = head;
if ( ( ptr->x == key ) )
{
// Delete the first/head element
node *temp = ptr;
head = head->next;
free( temp );
length--;
}
else
{
while ( ptr->next != NULL )
{
if ( ( ptr->next->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = ptr->next;
ptr->next = ptr->next->next;
free( temp );
length--;
}
ptr = ptr->next;
}
}
}
Also I took the liberty of renaming last to ptr because it was confusing me.
EDIT: Updated to remove the head cleanly too.
Your code seems to be deleting last->next while last should be the node that matches the key.
I guess the following code may be shorter and do the deletion
node* head;
/* returns the node* the previous_node->next should be after the deletion */
node* delete_node(node* current, u8 key) {
if (current == NULL) return NULL; // deletion comes to end
if (head->x == key) {
node* temp = current->next;
free(current);
return delete_node(temp, key);
}
current->next = delete_node(current->next, key);
return current;
}
int main() {
// build the linked list
// ...
head = delete_node(head, key);
return 0;
}
However, this implement (which uses recursion instead of loop) may cause StackOverFlow if the list is too long. I had not tested if gcc would optimize the recursion out.

c program to remove elements from given linked list and print the entire list after removing

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <ctype.h>
struct Stud
{
char name[20];
struct Stud *next;
};
struct Stud *hptr=NULL,*tptr;
//char data[20];
void deleteKey(struct Stud *hptr,char data[20])
{
struct Stud * temp = hptr, *prev;
while (temp != NULL && temp->name == data)
{
hptr = temp->next;
free(temp);
temp = hptr;
}
while (temp != NULL)
{
while (temp != NULL && temp->name != data)
{
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp);
temp = prev->next;
}
}
void createList(char *s)
{
struct Stud *nptr;
nptr=(struct Stud *)malloc(sizeof(struct Stud));
strcpy(nptr->name,s);
if(hptr==NULL)
hptr=tptr=nptr;
else
tptr->next=nptr;
tptr=nptr;
nptr->next=NULL;
}
void display(){
while(hptr!=NULL) {
printf("%s ",hptr->name);
hptr=hptr->next;
}
}
void main(){
int i,n;
char str1[20];
char s[20];
scanf("%d",&n);
for(i = 0; i < n; i++) {
scanf("%s",str1);
createList(str1);
}
scanf("%s",s);
display();
deleteKey(hptr, s);
display();
}
I am not getting the desired output.please correct me in passing the arguments to deleteKey and suggest me if there is anything wrong in the code.
for example:
input:
5
kmit
jntu
snist
cbit
ngit
cbit
output:
kmit
jntu
snist
ngit
You have to pass the head node to the function by reference because it can be changed within the function.
Also you have to use the standard function strcmp to compare strings.
In this expression
temp->name == data
there are compared addresses of the first characters of two arrays and it is obvious that they are unequal.
Here is a demonstrative program that shows how the function can be implemented.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Stud
{
char name[20];
struct Stud *next;
};
int deleteKey( struct Stud **head, const char *name )
{
while ( *head && strcmp( ( *head )->name, name ) != 0 )
{
head = &( *head )->next;
}
int success = *head != NULL;
if ( success )
{
struct Stud *node = *head;
*head = ( *head )->next;
free( node );
}
return success;
}
int push_front( struct Stud **head, const char *name )
{
struct Stud *node = malloc( sizeof( *node ) );
int success = node != NULL;
if ( success )
{
strncpy( node->name, name, sizeof( node->name ) );
node->name[sizeof( node->name ) - 1] = '\0';
node->next = *head;
*head = node;
}
return success;
}
void display_list( struct Stud **head )
{
for ( struct Stud *current = *head; current != NULL; current = current->next )
{
printf( "%s ", current->name );
}
}
int main(void)
{
struct Stud *head = NULL;
push_front( &head, "Bob" );
push_front( &head, "Peter" );
push_front( &head, "Margarite" );
display_list( &head );
putchar( '\n' );
deleteKey( &head, "Margarite" );
display_list( &head );
putchar( '\n' );
deleteKey( &head, "Bob" );
display_list( &head );
putchar( '\n' );
deleteKey( &head, "Peter" );
display_list( &head );
putchar( '\n' );
return 0;
}
The program output is
Margarite Peter Bob
Peter Bob
Peter

Resources