Displaying polynomials with linked list in C - c

I am trying to write a code creating and displaying polynomials. My first question is: "Did I use linked list correctly?". Second is: "Why can't I display poynomials?" I want them displayed like: If there are 2 monomials, poynomial should be displayed as; -->(1.0 X 0) -->(1.0 X 3)--E First one is coefficient second one is the exponent.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//this will be the structure named node
struct node
{
int exp; //this line represents the exponent/power b for a*x^b
int coeff; //this line represents the coefficient a for a*x^b
struct node *next; //this line represents the pointer which will point to the next node
};
struct node *create_new_nodes(struct node *m);
struct node *insert(struct node *ptr, struct node *k);
void display(char const *tag, struct node *ptr);
struct node *create_new_nodes(struct node *m)
{
int i;
int n;
printf("Enter the number of nodes: ");
scanf("%d", &n);
for (i = 0; i < n; i++)
{
struct node *ptr = malloc(sizeof(struct node));
printf("Enter the coefficient (a for a*x^b): ");
scanf("%d", &ptr->coeff);
printf("Enter the exponent/power (b for a*x^b): ");
scanf("%d", &ptr->exp);
ptr->next = NULL;
}
return m;
}
void display(char const *tag, struct node *ptr)
{
struct node *temp;
temp = ptr;
printf("%s: ", tag);
while (temp != NULL)
{
printf("-->(%d X %d)--E", temp->coeff, temp->exp);
temp = temp->next;
}
putchar('\n');
}
int main(void)
{
struct node *p1 = NULL, *p2 = NULL;
p1 = create_new_nodes(p1);
p2 = create_new_nodes(p2);
display("p1", p1);
display("p2", p2);
return 0;
}
My output for this code:
Enter the number of nodes: 2
Enter the coefficient (a for a*x^b): 1
Enter the exponent/power (b for a*x^b): 2
Enter the coefficient (a for a*x^b): 2
Enter the exponent/power (b for a*x^b): 3
Enter the number of nodes: 2
Enter the coefficient (a for a*x^b): 3
Enter the exponent/power (b for a*x^b): 4
Enter the coefficient (a for a*x^b): 6
Enter the exponent/power (b for a*x^b): 5
p1:
p2:
As you can see p1 and p2 are not displayed.
I have to mention that I took help from internet while writing some parts of this code. So, there are parts that I didn't understand. If possible, I would like to be clarified for those too.
void display(char const *tag, struct node *ptr)
{
struct node *temp;
const char *pad;
temp = ptr;
printf("%s: ", tag);
while (temp != NULL)
{
printf("-->(%d X %d)--E", temp->coeff, temp->exp);
temp = temp->next;
pad = " + ";
}
putchar('\n');
}
In this part of code, I didn't get why I use temp and tag function.

Let's get you sorted out. Rather than a full general linked-list implementation, you simply need the create, display, and delete functions. Since your lists are just links of structs with exp and coeff, you can simply build a new list each time you call your create function. You do NOT need to provide a parameter to your create function, just declare your list pointer local to the function and then return a pointer to the first node in the allocated list when done.
As noted in the comment, you are headed for a lot of grief unless you check the return for every input function used (and not mentioned, but equally important, check the return of EVERY allocation)
You were not terribly far off where you were headed with your create function, you just never linked the nodes together in your list. You do want to initialize the next pointer NULL following allocation, but you also have to set any existing end node in your list next pointer to point to the new node. That is how you create the "link" in the "linked-list".
Let's take your create function, (I've renamed it create_poly_list()) and essentially you can declare both head and tail list pointers local to the function (the tail pointer is temporary used to build the list) and then return head when done for assignment back in the caller (main() here). So all you really needed would be to declare your list pointers, and then add each node in-order, e.g.
struct node *head = NULL, *tail = NULL; /* temporary list pointers */
...
if (head == NULL) /* add first node */
head = tail = ptr;
else {
tail->next = ptr; /* set last node ->next to new node */
tail = ptr; /* update tail to new node */
}
...
return head; /* return pointer to start of list */
Then in main() you would simply call create_poly_list() for each polynomial, e.g.
p1 = create_poly_list();
p2 = create_poly_list();
Now let's tidy it up so you validate each input and allocation, returning NULL on either input or allocation failure (and remembering to free() all memory if memory was allocated prior to the failure to prevent a memory leak), e.g.
struct node *create_poly_list (void) /* no parameter required */
{
int i, n;
struct node *head = NULL, *tail = NULL; /* temporary list pointers */
fputs ("\nEnter the number of nodes: ", stdout);
if (scanf("%d", &n) != 1)
return NULL;
for (i = 0; i < n; i++)
{
struct node *ptr = malloc (sizeof *ptr);
if (!ptr) { /* validate EVERY allocation */
while (head) { /* if nodes in list */
struct node *victim = head; /* free all nodes (or leak) */
head = head->next;
free (victim);
}
return NULL; /* now return NULL on error */
}
ptr->next = NULL; /* initialize next ptr NULL */
fputs ("\nEnter the coefficient (a for a*x^b) : ", stdout);
if (scanf ("%d", &ptr->coeff) != 1) {
fputs ("error: invalid integer input.\n", stderr);
/* you would likewise need to free prior nodes here */
return NULL;
}
fputs ("Enter the exponent/power (b for a*x^b): ", stdout);
if (scanf("%d", &ptr->exp) != 1) {
fputs ("error: invalid integer input.\n", stderr);
/* you would likewise need to free prior nodes here */
return NULL;
}
if (head == NULL) /* add first node */
head = tail = ptr;
else {
tail->next = ptr; /* set last node ->next to new node */
tail = ptr; /* update tail to new node */
}
}
return head; /* return pointer to start of list */
}
Your display() function was good, but you should check if ptr is NULL (e.g. list empty) to inform the user of the list state in case an attempt is made to display an empty list, e.g.
void display (char const *tag, struct node *ptr)
{
if (!ptr) { /* validate list not NULL */
puts ("(list-empty)");
return;
}
struct node *temp = ptr;
printf("%s: ", tag);
while (temp) {
printf("-->(%d X %d)--E", temp->coeff, temp->exp);
temp = temp->next;
}
putchar('\n');
}
Here you need to free the memory of each list when you are done with it. (yes, the memory will be freed on program exit, but presumably you won't always be writing simple programs that create all lists in main()). Build good memory management habits early. A simple delete list function is all you need, e.g.
void del_list (struct node *list)
{
while (list) {
struct node *victim = list;
list = list->next;
free (victim);
}
}
Putting it altogether, you would have:
#include <stdio.h>
#include <stdlib.h>
struct node {
int exp;
int coeff;
struct node *next;
};
struct node *create_poly_list (void) /* no parameter required */
{
int i, n;
struct node *head = NULL, *tail = NULL; /* temporary list pointers */
fputs ("\nEnter the number of nodes: ", stdout);
if (scanf("%d", &n) != 1)
return NULL;
for (i = 0; i < n; i++)
{
struct node *ptr = malloc (sizeof *ptr);
if (!ptr) { /* validate EVERY allocation */
while (head) { /* if nodes in list */
struct node *victim = head; /* free all nodes (or leak) */
head = head->next;
free (victim);
}
return NULL; /* now return NULL on error */
}
ptr->next = NULL; /* initialize next ptr NULL */
fputs ("\nEnter the coefficient (a for a*x^b) : ", stdout);
if (scanf ("%d", &ptr->coeff) != 1) {
fputs ("error: invalid integer input.\n", stderr);
/* you would likewise need to free prior nodes here */
return NULL;
}
fputs ("Enter the exponent/power (b for a*x^b): ", stdout);
if (scanf("%d", &ptr->exp) != 1) {
fputs ("error: invalid integer input.\n", stderr);
/* you would likewise need to free prior nodes here */
return NULL;
}
if (head == NULL) /* add first node */
head = tail = ptr;
else {
tail->next = ptr; /* set last node ->next to new node */
tail = ptr; /* update tail to new node */
}
}
return head; /* return pointer to start of list */
}
void display (char const *tag, struct node *ptr)
{
if (!ptr) { /* validate list not NULL */
puts ("(list-empty)");
return;
}
struct node *temp = ptr;
printf("%s: ", tag);
while (temp) {
printf("-->(%d X %d)--E", temp->coeff, temp->exp);
temp = temp->next;
}
putchar('\n');
}
void del_list (struct node *list)
{
while (list) {
struct node *victim = list;
list = list->next;
free (victim);
}
}
int main(void)
{
struct node *p1 = NULL, *p2 = NULL;
p1 = create_poly_list();
p2 = create_poly_list();
putchar ('\n');
display("p1", p1);
display("p2", p2);
del_list (p1);
del_list (p2);
return 0;
}
(note: why you have included string.h is a bit bewildering...)
Example Use/Output
$ ./bin/poly_list
Enter the number of nodes: 2
Enter the coefficient (a for a*x^b) : 2
Enter the exponent/power (b for a*x^b): 6
Enter the coefficient (a for a*x^b) : 3
Enter the exponent/power (b for a*x^b): 7
Enter the number of nodes: 3
Enter the coefficient (a for a*x^b) : 1
Enter the exponent/power (b for a*x^b): 3
Enter the coefficient (a for a*x^b) : 3
Enter the exponent/power (b for a*x^b): 5
Enter the coefficient (a for a*x^b) : 5
Enter the exponent/power (b for a*x^b): 7
p1: -->(2 X 6)--E-->(3 X 7)--E
p2: -->(1 X 3)--E-->(3 X 5)--E-->(5 X 7)--E
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to ensure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/poly_list
==23402== Memcheck, a memory error detector
==23402== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==23402== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==23402== Command: ./bin/poly_list
==23402==
Enter the number of nodes: 2
Enter the coefficient (a for a*x^b) : 2
Enter the exponent/power (b for a*x^b): 6
Enter the coefficient (a for a*x^b) : 3
Enter the exponent/power (b for a*x^b): 7
Enter the number of nodes: 3
Enter the coefficient (a for a*x^b) : 1
Enter the exponent/power (b for a*x^b): 3
Enter the coefficient (a for a*x^b) : 3
Enter the exponent/power (b for a*x^b): 5
Enter the coefficient (a for a*x^b) : 5
Enter the exponent/power (b for a*x^b): 7
p1: -->(2 X 6)--E-->(3 X 7)--E
p2: -->(1 X 3)--E-->(3 X 5)--E-->(5 X 7)--E
==23402==
==23402== HEAP SUMMARY:
==23402== in use at exit: 0 bytes in 0 blocks
==23402== total heap usage: 7 allocs, 7 frees, 2,128 bytes allocated
==23402==
==23402== All heap blocks were freed -- no leaks are possible
==23402==
==23402== For counts of detected and suppressed errors, rerun with: -v
==23402== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.

I might be wrong, but in the function
struct node *create_new_nodes(struct node *m)
it looks like both the return type and the parameter are pointers. So really, you are returning
struct node **m
Not sure if that's what's wrong, but if it is, the same issue might appear when you do
printf("-->(%d X %d)--E", temp->coeff, temp->exp);
when temp is ptr which is struct node*. So really you are saying (**node).coeff. But this is just my tired observation, if it works just ignore me.

Related

Why does the function named "traverse" not work on my code?

In the example below, I created a linked list and I can add numbers successfully. However, at the
end of the execution, the function named "traverse" does not work. How can I fix this error?
Here is my code:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
struct node
{
int data;
struct node*prev;
struct node*next;
};
void add( node*head,int number )
{
node*ptr = NULL;
if( head == NULL )
{
head = (node*)malloc(sizeof(node));
head->data = number;
head->next = NULL;
head->prev = NULL;
ptr = head;
}
else
{
ptr->next = (node*)malloc(sizeof(node));
ptr->next->prev = ptr;
ptr = ptr->next;
ptr->data = number;
ptr->next = NULL;
}
}
void traverse( node* head )
{
while( head != NULL )
{
printf("%d ",head->data);
head = head->next;
}
}
int main( void )
{
node *head = NULL;
int number;
char response;
printf("%s\n","Do you want to enter a number in linked list(y/n)?" );
scanf("%c",&response);
while( response == 'y' || response == 'Y' )
{
printf("\nEnter num..> ");
scanf("%d",&number);
add(head,number);
printf("%s\n","Do you want to continue(y/n)?" );
response = getche();
}
printf("\nYour doubly linked list\n");
traverse(head);
getch();
return 0;
}
when "traverse" is called, the console print space like the following image.
If you have decided on C, then continuing from the comments, you are attempting to update a local copy of the pointer head in add(). As mentioned, you have two option, either change the return type of add() to node *add() so you can return ptr and assign as the new head back in main(), or pass the address of head as the first parameter and update the node stored at the original pointer address in add().
You can pass the address of head to add() as follows:
void add (node **head, int number)
{
node *ptr = malloc (sizeof *ptr);
if (!ptr)
return;
ptr->data = number; /* initialized new node data */
ptr->prev = ptr->next = NULL; /* initialized both pointers NULL */
if ( *head != NULL ) { /* if not 1st node */
(*head)->prev = ptr; /* Forward-Chain new node */
ptr->next = *head;
}
*head = ptr; /* set head = new node */
}
(note: since you pass the address of head as a parameter, you must remove one level of indirection from the pointer-to-pointer in add() by dereferncing head (e.g. *head) in order to update the node at the original pointer address. You also need to use the (*head) when further derferencing the pointer with -> due to C operator precedence -- so you get the original pointer address before -> is applied)
Note, the add() function uses a method call Forward-Chaining to add each node to the list in O(1) time. This also means the list will hold the numbers in the reverse order they were entered (last first). You have two options to insert in-order, (1) iterate to the end of the list each time and add a new end node (highly inefficient for large lists, no longer O(1) time, or (2) use another tail pointer that always points to the last node to allow in-order insertions in O(1) time.
You would then call your add() function in main() with
add (&head, number);
Do NOT make things difficult on yourself when testing your list implementation. There is no reason to have to type 'y' then a number and 'y' again before every number you add to your list (that would drive me nuts...). Just add numbers to your list with a loop, you can do input later, e.g.
int main (void)
{
node *head = NULL; /* list pointer initialized NULL */
for (int i = 0; i < 20; i++) /* just add 20 nodes to list */
add (&head, i + 1);
traverse (head);
delete_list (head);
head = NULL;
/* hold terminal open on windows only */
#if defined (_WIN32) || defined (_WIN64)
getchar();
#endif
}
(note: conio.h has been removed and getchar() used to hold the terminal open on windows. Since I'm on Linux, the final getchar() is not compiled as part of my executable)
Your traverse() function will work, but get in the habit of using a separate separate pointer to iterate over you list. This isn't always required, and isn't needed in traverse() since you can use the local copy of head, but always using a temporary pointer to iterate with leave you with the original head address if you need it for use later in your function, e.g.
void traverse (const node *head)
{
const node *iter = head; /* optional, but good practice */
while (iter) {
printf ("%d ", iter->data);
iter = iter->next;
}
putchar ('\n');
}
Notice also the delete_list() function added to free() all memory added for your list. You won't always be declaring lists in main() where the memory is freed on exit. Get in the habit of keeping track of the memory you allocate and freeing the memory before your pointer goes out of scope (otherwise, you will create a memory leak)
The full program would be:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *prev, *next;
} node;
void add (node **head, int number)
{
node *ptr = malloc (sizeof *ptr);
if (!ptr)
return;
ptr->data = number; /* initialized new node data */
ptr->prev = ptr->next = NULL; /* initialized both pointers NULL */
if ( *head != NULL ) { /* if not 1st node */
(*head)->prev = ptr; /* Forward-Chain new node */
ptr->next = *head;
}
*head = ptr; /* set head = new node */
}
void traverse (const node *head)
{
const node *iter = head; /* optional, but good practice */
while (iter) {
printf ("%d ", iter->data);
iter = iter->next;
}
putchar ('\n');
}
void delete_list (node *head)
{
node *iter = head;
while (iter) {
node *victim = iter;
iter = iter->next;
free (victim);
}
}
int main (void)
{
node *head = NULL; /* list pointer initialized NULL */
for (int i = 0; i < 20; i++) /* just add 20 nodes to list */
add (&head, i + 1);
traverse (head);
delete_list (head);
head = NULL;
/* hold terminal open on windows only */
#if defined (_WIN32) || defined (_WIN64)
getchar();
#endif
}
Example Use/Output
$ ./bin/llmess
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to ensure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/llmess
==16661== Memcheck, a memory error detector
==16661== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16661== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16661== Command: ./bin/llmess
==16661==
20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
==16661==
==16661== HEAP SUMMARY:
==16661== in use at exit: 0 bytes in 0 blocks
==16661== total heap usage: 21 allocs, 21 frees, 1,504 bytes allocated
==16661==
==16661== All heap blocks were freed -- no leaks are possible
==16661==
==16661== For counts of detected and suppressed errors, rerun with: -v
==16661== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.

How do I avoid a segmentation fault while inserting nodes into a singly linked list?

The nodes get inserted when I insert them in order on the console
How do I make sure that I take care of all boundary conditions? For example, what if the user enters a position greater than the size of the list? Also, I get a segmentation fault when I try to insert after a node but it works just fine before a node. Here's a picture to help explain my problem better
Also, I get a segmentation fault when I try to insert after a node but it works just fine before a node.
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Node *head = NULL;
struct Node *insert(int x,int pos)
{
if(head == NULL)
{
struct Node *temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = x;
temp->next = head;
head = temp;
return head;
}
else
{
int len = 0;
struct Node *temp = head;
while(temp!=NULL)
{
++len;
temp = temp->next;
}
if(pos == 1)
{
struct Node *temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = x;
temp->next = head;
head = temp;
return head;
}
else
{
struct Node *temp = (struct Node*)malloc(sizeof(struct Node));
temp->data = x;
temp->next = NULL;
struct Node *temp1 = head;
for(int i = 2; i<pos; i++)
{
temp1 = temp1->next;
}
temp->next = temp1->next;
temp1->next= temp;
}
}
}
void print()
{
struct Node *temp = head;
while(temp!=NULL)
{
printf("%d ",temp->data);
temp = temp->next;
}
printf("\n");
}
int main()
{
int n,i,x,pos;
printf("How many elements?\n");
scanf("%d",&n);
for(i = 0; i<n; i++)
{
printf("enter the value and the position: \n");
scanf("%d %d",&x,&pos);
insert(x,pos);
print();
}
printf("Linked list is: \n");
print();
}
Output 1
How many elements?
3
enter the value and the position:
3 2
List is: 3
enter the value and the position:
4 3
Segmentation fault (core dumped)
Output 2
How many elements?
3
enter the value and the position:
3 2
List is: 3
enter the value and the position:
4 1
List is: 4 3
enter the value and the position:
5 3
List is: 4 3 5
Linked list is:
4 3 5
You are making your insert much harder than it needs to be. You simply need to iterate with 2 conditions (1) pos times or less, and (2) while the next pointer is not NULL. You can greatly simplify the insert by iterating using both the address of and a pointer to the next node. You maintain the current node using the address and your pointer always points to the next node. When you have iterated pos times or your next pointer is NULL you insert your node. See Linus on Understand Pointers
Further, you are not making use of any return, from insert(), so your function prototype should simply be void insert (int x, int pos). While you should avoid using a global pointer to your list, for your purposes of this limited example, that is fine. Know that your list should normally be declared in the scope it is needed and a pointer (or pointer to pointer) to the beginning of the list should be passed as a parameter to make the list available to any function that operates on it rather than it being global.
Putting the pieces together, your insert() function reduces to:
void insert (int x, int pos)
{
struct Node **ppn = &head, /* pointer to pointer to node */
*pn = head, /* pointer to node */
*node = malloc (sizeof *node); /* allocate for new node */
if (!node) { /* validate allocation */
perror ("malloc-node");
exit (EXIT_FAILURE);
}
node->data = x; /* initialize members values */
node->next = NULL;
while (pos-- && pn) { /* iterate pos times && while pn != NULL */
ppn = &pn->next;
pn = pn->next;
}
node->next = pn; /* set next to pointer to node */
*ppn = node; /* set node at address to node */
}
Adding that to the remainder of your example, your complete example would be:
#include<stdio.h>
#include<stdlib.h>
struct Node {
int data;
struct Node *next;
};
struct Node *head = NULL;
void insert (int x, int pos)
{
struct Node **ppn = &head, /* pointer to pointer to node */
*pn = head, /* pointer to node */
*node = malloc (sizeof *node); /* allocate for new node */
if (!node) { /* validate allocation */
perror ("malloc-node");
exit (EXIT_FAILURE);
}
node->data = x; /* initialize members values */
node->next = NULL;
while (pos-- && pn) { /* iterate pos times && while pn != NULL */
ppn = &pn->next;
pn = pn->next;
}
node->next = pn; /* set next to pointer to node */
*ppn = node; /* set node at address to node */
}
/** print all nodes in list */
void print (void)
{
if (!head) {
puts ("list-empty");
return;
}
for (struct Node *n = head; n; n = n->next)
printf (" %d", n->data);
putchar ('\n');
}
/** delete all nodes in list */
void del_list (void)
{
struct Node *n = head;
while (n) {
struct Node *victim = n;
n = n->next;
free (victim);
}
}
int main()
{
int n,i,x,pos;
printf ("How many elements?\n");
if (scanf ("%d",&n) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
for (i = 0; i < n; i++)
{
printf ("enter the value and the position: \n");
if(scanf("%d %d",&x, &pos) == 2) {
insert (x, pos);
fputs ("list is: ", stdout);
print();
}
}
puts ("\nLinked list is:");
print();
del_list(); /* free all memory allocated to list */
}
(note: a del_list() function was added to free() the memory associated with your list.)
Example Use/Output
Continuing with your example where you were SegFaulting, you can now complete your inserts, e.g.:
$ ./bin/llatpos
How many elements?
3
enter the value and the position:
3 2
list is: 3
enter the value and the position:
4 3
list is: 3 4
enter the value and the position:
1 0
list is: 1 3 4
Linked list is:
1 3 4
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to ensure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/llatpos
==16615== Memcheck, a memory error detector
==16615== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16615== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16615== Command: ./bin/llatpos
==16615==
How many elements?
3
enter the value and the position:
3 2
list is: 3
enter the value and the position:
4 3
list is: 3 4
enter the value and the position:
1 0
list is: 1 3 4
Linked list is:
1 3 4
==16615==
==16615== HEAP SUMMARY:
==16615== in use at exit: 0 bytes in 0 blocks
==16615== total heap usage: 5 allocs, 5 frees, 2,096 bytes allocated
==16615==
==16615== All heap blocks were freed -- no leaks are possible
==16615==
==16615== For counts of detected and suppressed errors, rerun with: -v
==16615== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.
For starters indices in C (for example for arrays) start from 0.
So you should also use the value pf the position in the list that starts from 0.
Logically if the given position is greater than or equal to the number of nodes in the list the new value should be appended to the list.
Nowhere in the function insert you are using the size of the list. So this code snippet
int len = 0;
struct Node *temp = head;
while(temp!=NULL)
{
++len;
temp = temp->next;
}
does not make sense.
If the position is greater than the size of the list then this code snippet
for(int i = 2; i<pos; i++)
{
temp1 = temp1->next;
}
can invoke undefined behavior because inside the loop the variable temp1 can be set to NULL.
Also if the position equal to 2 then the node head is not updated.
The function has a non-void return type but returns nothing.
The function insert can be written much simpler as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node *next;
};
struct Node *head = NULL;
int insert( int data, size_t pos )
{
struct Node *temp = malloc( sizeof( struct Node ) );
int success = temp != NULL;
if ( success )
{
temp->data = data;
struct Node **current = &head;
while ( pos-- != 0 && *current != NULL )
{
current = &( *current )->next;
}
temp->next = *current;
*current = temp;
}
return success;
}
void print()
{
for ( const struct Node *current = head; current != NULL; current = current->next )
{
printf( "%d -> ", current->data );
}
puts( "NULL" );
}
int main(void)
{
/*
insert( 3, 2 );
printf( "Linked list is: " );
print();
insert( 4, 3 );
printf( "Linked list is: " );
print();
*/
insert( 3, 3 );
printf( "Linked list is: " );
print();
insert( 1, 0 );
printf( "Linked list is: " );
print();
insert( 2, 1 );
printf( "Linked list is: " );
print();
insert( 4, 3 );
printf( "Linked list is: " );
print();
insert( 5, 10 );
printf( "Linked list is: " );
print();
return 0;
}
The program output is
Linked list is: 3 -> NULL
Linked list is: 1 -> 3 -> NULL
Linked list is: 1 -> 2 -> 3 -> NULL
Linked list is: 1 -> 2 -> 3 -> 4 -> NULL
Linked list is: 1 -> 2 -> 3 -> 4 -> 5 -> NULL

Adding a node to the middle of a singly linked list

So I have code that I will show below
struct GraphicElement {
char* fileName;
struct GraphicElement* pNext;
};
struct RasterGraphic {
struct GraphicElement* GraphicElements;
};
AND ALSO
void InsertGraphicElement(struct RasterGraphic* pA)
{
int counter = 1;
int response = 0;
char tempString[256];
struct GraphicElement *newNode = malloc(sizeof(*newNode));
if (newNode == NULL) return;
newNode->fileName = malloc(256 * sizeof(char));
if (newNode->fileName == NULL) return;
newNode->pNext = NULL;
printf("Insert a GraphicElement in the RasterGraphic\nPlease enter the GraphicElement filename: ");
scanf("%s", newNode->fileName);
if (pA->GraphicElements == NULL)
{
pA->GraphicElements = newNode;
printf("This is the first GraphicElement in the list\n");
}
else
{
struct GraphicElement *tempHead = pA->GraphicElements;
while (tempHead->pNext != NULL)
{
tempHead = tempHead->pNext;
counter++;
}
printf("There are %d GraphicElement(s) in the list. Please specify the position (<= %d) to insert at :", counter, counter);
scanf("%d", &response);
if (response == counter) {
tempHead->pNext = newNode;
return;
}
}
return;
}
So as you can see I have a struct definition and then a function to insert a node into the list. I have it so that if its the first node it inserts and tells the user it is the first element in the list. Where I am having a problem is adding more elements. Right now the code has no problems adding new nodes in sequence. The user is asked where they would like to insert into the list. Right now as long as they choose to just add it in sequence it works perfectly. I've tried a lot of things i just cant figure out the logic to loop through and be able to add a node to the middle of the list so an example output would be like this..
List contains 1, 2, 3
the user adds a fourth element 4 but wants to add it to spot 1 which is where the 2 is sitting so the new updated list would look like 1, 4, 2, 3.
There is no magic to inserting anywhere within the linked list, the only real challenge is keeping your pointers straight when handling three conditions:
inserting the first node (or new first node);
inserting a node between at some position between the existing first and last node; and
inserting at the end of the list.
The first case, inserting the first (or new first) node simply requires allocating a new node and either inserting it is the first node in the list, or if the head node already exists, setting newnode->next = head; and head = newnode;
Inserting at the end is not much different, you just iterate to the last node and set last->next = newnode;
The case of inserting a node in between takes a bit more thought. The easiest way to keep your pointers straight is to pull out a pencil and paper and draw out your pointer diagram of your list and then break the list in two where you need to insert the new node, and figure out the steps required before you pickup the keyboard (it will go a lot easier that way)
Nothing fancy is needed, just a block diagram with your next (or your pNext) pointer connecting the nodes. A simple list will two nodes (A and B) will do, e.g.
A B
+------+ +------+
| node | | node |
| next |--> | next |-->NULL
+------+ +------+
Then just break the list at the point where the new node will be inserted, e.g.
A B
+------+ | +------+
| node | / | node |
| next |--> \ | next |-->NULL
+------+ / +------+
|
new
+------+
| node |
| next |-->
+------+
That allows you to visualize the needed steps. Locate node A, set new->next = B;, set A->next = new; (note: you must stop at the node before the location you wish to insert the new node) The result will then be:
A new B
+------+ +------+ +------+
| node | | node | | node |
| next |--> | next |--> | next |-->NULL
+------+ +------+ +------+
When an understanding of exactly what you need to do to handle the insertion, now pick up the keyboard and implement that logic.
Since you will have a single insert function to handle all three cases, as #WhozCraig commented, when handling list operations (or pointers in general where you may need to assign a new block of memory within a function changing the address of the pointer), it helps to pass the address of the pointer to your function (so that your function receives the pointer itself -- instead of a copy of the pointer).
Whether in your case you need to initially allocate for the list wrapper, or in a simple list where you may assign a new node as the first node in the list, passing the address of the pointer allows the change within the function without having to return and assign the return as the new address back in the calling function.
Adding a couple of typedefs gelement_t for your struct GraphicElement and rgraphic_t for struct RasterGraphic types, both to cut down on typing an remove some of the MixedCase style awkwardness, you can think about your InsertGraphicElement function in the following way.
First, your InsertGraphicElement function will either succeed or fail, so choose a meaningful return type that can indicate success or failure. When dealing with lists, returning a pointer to the newly inserted node is helpful and allows a return of NULL in the even of failure, e.g.
gelement_t *InsertGraphicElement (rgraphic_t **pA)
Since you are passing a pointer to pointer to your RasterGraphic struct, you can add data to the struct to make it a bit more useful as a wrapper to your actual list. Adding a node-counter is a convenient way to keep track of the number of nodes in a singly-linked list without having to iterate over the list each time, e.g.
typedef struct RasterGraphic {
size_t nelements;
gelement_t *GraphicElements;
} rgraphic_t;
Within your function you should validate that you have an allocated pointer, and if not, then allocate for the RasterGraphic struct, e.g.
int position = 0;
if (!*pA) { /* if list NULL - allocate new list */
puts ("allocating new list.");
*pA = malloc (sizeof **pA);
if (!*pA) { /* validate every allocation */
perror ("malloc-*list");
exit (EXIT_FAILURE);
}
(*pA)->nelements = 0; /* initialize values */
(*pA)->GraphicElements = NULL;
}
Next you can allocate and validate the new node to add either as the first node or at position, e.g.
gelement_t *node = malloc (sizeof *node); /* allocate node */
if (!node) { /* validate */
perror ("malloc-node");
exit (EXIT_FAILURE);
}
Next collect your filename and position information and set node->fileName to a newly allocated block holding the filename entered by the user (a couple of helper-functions make this much easier), e.g.
node->fileName = get_filename_stdin(); /* request filename */
if (!node->fileName) { /* validate */
free (node);
return NULL;
}
node->pNext = NULL; /* set next pointer NULL */
position = get_int_stdin (*pA); /* request position */
You are now at the point within the function where you handle the 3-cases identified at the beginning of the answer. If there is no (*pA)->GraphicElements node yet, you will add the first node (so you don't need to ask for position). If it isn't the first node, and the position requested is 0, you insert as a new first node. (both can be handled in a single case)
If the position requested is greater than zero, then you iterate to the node before the insertion point and insert as indicated with the diagram above and insert the node there.
One approach would be:
gelement_t *p = (*pA)->GraphicElements;
if (!p || position == 0) { /* insert as new head */
node->pNext = p;
(*pA)->GraphicElements = node;
}
else { /* insert at position (default end) */
int n = 0;
while (n < position - 1 && p->pNext) { /* locate node before */
p = p->pNext;
n++;
}
node->pNext = p->pNext; /* set node->pNext to current pNext */
p->pNext = node; /* set current pNext to node */
}
(*pA)->nelements++; /* increment number of elements in list */
Which will handle your insertion based on the user input. All that remains is to:
return node; /* meaningful return to indicate success/failure */
}
(note: when you are comfortable with the list operation logic, it helps to break this function up into several functions that handle the operations individually, like create_list(), create_node() and add_node(). (where you create your RasterGraphic list, your GraphicElement node and finally add that node at a given position in the list -- that is left to you)
Putting it altogether and adding the helper functions, a short example would be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h> /* for PATH_MAX */
typedef struct GraphicElement {
char* fileName;
struct GraphicElement* pNext;
} gelement_t;
typedef struct RasterGraphic {
size_t nelements;
gelement_t *GraphicElements;
} rgraphic_t;
char *get_filename_stdin (void)
{
char filename[PATH_MAX] = "";
char *newname = NULL;
fputs ("enter filename : ", stdout);
if (fgets (filename, PATH_MAX, stdin)) {
size_t len = strlen (filename);
if (len && filename[len-1] == '\n') {
filename[--len] = 0;
if (!len) {
fputs ("error: filename empty.\n", stderr);
return NULL;
}
}
else if (len == PATH_MAX) {
fputs ("error: filename exceeds PATH_MAX\n", stderr);
return NULL;
}
newname = malloc (len + 1);
if (!newname) {
perror ("malloc-newname");
exit (EXIT_FAILURE);
}
memcpy (newname, filename, len + 1);
}
return newname;
}
int get_int_stdin (rgraphic_t *list)
{
char buf[PATH_MAX];
int pos = 0;
if (!list->nelements) {
puts ("inserting as head.");
return 0;
}
fputs ("index to insert: ", stdout);
if (fgets (buf, PATH_MAX, stdin))
if (sscanf (buf, "%d", &pos) != 1 || pos < 0 ||
pos > (long)list->nelements)
return list->nelements;
return pos;
}
gelement_t *InsertGraphicElement (rgraphic_t **pA)
{
int position = 0;
if (!*pA) { /* if list NULL - allocate new list */
puts ("allocating new list.");
*pA = malloc (sizeof **pA);
if (!*pA) { /* validate every allocation */
perror ("malloc-*list");
exit (EXIT_FAILURE);
}
(*pA)->nelements = 0; /* initialize values */
(*pA)->GraphicElements = NULL;
}
gelement_t *node = malloc (sizeof *node); /* allocate node */
if (!node) { /* validate */
perror ("malloc-node");
exit (EXIT_FAILURE);
}
node->fileName = get_filename_stdin(); /* request filename */
if (!node->fileName) { /* validate */
free (node);
return NULL;
}
node->pNext = NULL; /* set next pointer NULL */
position = get_int_stdin (*pA); /* request position */
gelement_t *p = (*pA)->GraphicElements;
if (!p || position == 0) { /* insert as new head */
node->pNext = p;
(*pA)->GraphicElements = node;
}
else { /* insert at position (default end) */
int n = 0;
while (n < position - 1 && p->pNext) { /* locate node before */
p = p->pNext;
n++;
}
node->pNext = p->pNext; /* set node->pNext to current pNext */
p->pNext = node; /* set current pNext to node */
}
(*pA)->nelements++; /* increment number of elements in list */
return node; /* meaningful return to indicate success/failure */
}
/* loop over list printing values */
void prn_list (rgraphic_t *list)
{
size_t n = 0;
gelement_t *node = list->GraphicElements;
printf ("\n\n%zu nodes in list\n", list->nelements);
for (; node; node = node->pNext)
printf ("%2zu: %s\n", 1 + n++, node->fileName);
}
/* loop over list freeing memory (pay attention to victim) */
void free_list (rgraphic_t *list)
{
gelement_t *node = list->GraphicElements;
while (node) {
gelement_t *victim = node;
node = node->pNext;
free (victim->fileName);
free (victim);
}
free (list);
}
int main (void) {
rgraphic_t *list = NULL;
puts ("\nNOTE: pressing [Enter] for index - inserts at end!\n"
" [Ctrl+d] at \"filename: \" prompt to end input.\n");
while (InsertGraphicElement(&list)) {} /* create list/insert nodes */
prn_list (list); /* print list */
free_list (list); /* free list */
}
Example Use/Output
$ ./bin/ll_single_insert_ptp
NOTE: pressing [Enter] for index - inserts at end!
[Ctrl+d] at "filename: " prompt to end input.
allocating new list.
enter filename : one
inserting as head.
enter filename : four
index to insert: 1
enter filename : two
index to insert: 1
enter filename : three
index to insert: 2
enter filename : five
index to insert:
enter filename :
5 nodes in list
1: one
2: two
3: three
4: four
5: five
Memory Use/Error Check
In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated.
For Linux valgrind is the normal choice. There are similar memory checkers for every platform. They are all simple to use, just run your program through it.
$ valgrind ./bin/ll_single_insert_ptp
==9747== Memcheck, a memory error detector
==9747== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9747== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==9747== Command: ./bin/ll_single_insert_ptp
==9747==
NOTE: pressing [Enter] for index - inserts at end!
[Ctrl+d] at "filename: " prompt to end input.
allocating new list.
enter filename : one
inserting as head.
enter filename : four
index to insert: 1
enter filename : two
index to insert: 1
enter filename : three
index to insert: 2
enter filename : five
index to insert:
enter filename :
5 nodes in list
1: one
2: two
3: three
4: four
5: five
==9747==
==9747== HEAP SUMMARY:
==9747== in use at exit: 0 bytes in 0 blocks
==9747== total heap usage: 12 allocs, 12 frees, 136 bytes allocated
==9747==
==9747== All heap blocks were freed -- no leaks are possible
==9747==
==9747== For counts of detected and suppressed errors, rerun with: -v
==9747== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Always confirm that you have freed all memory you have allocated and that there are no memory errors.
Look things over and let me know if you have further questions.

Getting input for linked list fgets & scanf C

I created this linked list but I am having trouble getting the char array and the ints at the same time. Any suggestions? I have been up and down in forums and google but I can't seem to get it to agree with anything.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int id;
char name[40];
struct node *next;
struct node *prev;
} info;
int insert (int num, char *Name);
void print ();
struct node *root; // Declare root a pointer to the first node
int main () {
int n, Id, i;
char nAme[40];
char *name_ptr;
root = NULL; // List is empty
printf ("How many list entries do you want to make?\n");
scanf (" %d ", &n);
n = 2;
for (i = 0; i < n; i++) {
printf ("Enter name: ");
fgets (nAme, 40, stdin);
printf ("Enter id number: ");
scanf ("%d", &Id);
name_ptr = &nAme[0];
insert (Id, name_ptr);
print ();
}
}
int insert (int num, char *Name)
{
// Get memory
struct node *temp = (struct node *) malloc (sizeof (struct node));
if (temp == NULL) {
printf ("Some malloc problem.\n");
return 1;
}
temp->id = num;
strcpy (temp->name, Name);
temp->next = root;
root = temp;
}
void print ()
{
struct node *temp = root;
while (temp != NULL) {
printf ("%d\n%s\n", temp->id, temp->name);
temp = temp->next;
}
printf ("\n");
}
Sorry I'm a bit new to this site, so the formatting might say javascript, but its C as you can probably tell.
There are a number of problems conspiring against you. The first, important, but not a show stopper, is fgets will read up to and including the newline. Which means all of your nAme (presuming you meant name) entries have an embedded newline at the end. This will cause all kinds of havok when you attempt to search for or compare specific names in your list.
A huge issue is you have no validation on whether you even receive input to add to your list from the user. Always, always validate user input. That means checking at minimum that you actually have input to store. e.g.
printf ("Number of list entries to make?: ");
if (scanf (" %d%*c", &n) != 1) {
fprintf (stderr, "error: invalid no. of entries.\n");
return 1;
}
for (i = 0; i < n; i++) {
printf ("Enter name: ");
if (!fgets (name, MAXC, stdin)) {
fprintf (stderr, "error: invalid name.\n");
return 1;
}
rmcrlf (name); /* strip trailing newline from name */
printf ("Enter id number: ");
if (scanf ("%d%*c", &id) != 1) {
fprintf (stderr, "error: invalid ID.\n");
return 1;
}
insert (id, name);
}
(note: the rmcrlf (remove carriage-return newline) function trims the trailing new line or erroneous carriage return from the name value)
The more substantive issues being apparent confusion on what type of list you are creating (single/double linked, traditional head/tail, circular, what?) The difference being that a traditional head/tail will use a NULL value to mark the end/beginning of the list, while a circular list points the last node to the first allowing iteration from any point around the list.
You appear to want a doubly-linked list with your prev and next pointers, but you make absolutely no attempt to handle the prev pointer in any way. It is unclear whether you want a circular or head/tail NULL list. Regardless which you choose, you must account for setting the values for your prev and next pointer with each insert you do. It makes a difference whether you are setting the 1st (and 2nd on a circular list) compared to the remaining insertions. The following is an example of the insert function that will correctly handle additions to a circular list. A head/tail NULL list does not need specific handling of the second node.
struct node *insert (int num, char *name)
{
struct node *temp = malloc (sizeof *temp); /* allocate node */
if (!temp) {
fprintf (stderr, "error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
temp->id = num;
strcpy (temp->name, name);
if (!root) { /* empty list - insert first node */
temp->next = temp->prev = temp;
root = temp;
}
else if (root == root->next) { /* insert 2nd node */
temp->next = root;
root->prev = temp;
root->next = temp;
temp->prev = root;
}
else { /* insert all remaining nodes at end */
root->prev->next = temp;
temp->prev = root->prev;
temp->next = root;
root->prev = temp;
}
return temp;
}
(note: the function type being struct node *. It is of little use to return an int value here. You can judge success/failure by returning NULL in the event of a failure and you have the inserted node available for any post-insert processing required. Also, do NOT cast the return of malloc and you need only take the sizeof the object pointed to by the pointer being allocated)
Don't use magic numbers in your code. They make the code harder to maintain. If you need a constant to set the maximum characters in name, then define one with #define MAXC 40 or declare a global enum to define the constant (e.g. enum { MAXC = 40 };).
Putting those pieces together and fixing a few more nits, you could code your doubly-linked circular list something like the following example. You can simplify the code slightly by simply using a traditional head/tail NULL list instead.
Look the code over closely and understand the changes made (you need no name_ptr at all, and you don't set n=2; after taking input for n with scanf). Also note how the '\n' character scanf leaves in the input buffer (e.g. stdin) is handled. If you fail to account for the '\n', you will find scanf skipping over your input due to it taking the '\n' left in the input buffer as your input.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXC 40
struct node {
int id;
char name[MAXC];
struct node *next;
struct node *prev;
} info;
struct node *insert (int num, char *name);
void print (void);
void delete_list (void);
void rmcrlf (char *s);
struct node *root; /* Declare root a pointer to the first node */
int main (void) {
int i, id, n;
char name[MAXC];
root = NULL; /* List is empty */
printf ("Number of list entries to make?: ");
if (scanf (" %d%*c", &n) != 1) {
fprintf (stderr, "error: invalid no. of entries.\n");
return 1;
}
for (i = 0; i < n; i++) {
printf ("Enter name: ");
if (!fgets (name, MAXC, stdin)) {
fprintf (stderr, "error: invalid name.\n");
return 1;
}
rmcrlf (name);
printf ("Enter id number: ");
if (scanf ("%d%*c", &id) != 1) {
fprintf (stderr, "error: invalid ID.\n");
return 1;
}
insert (id, name);
}
print();
delete_list();
return 0;
}
struct node *insert (int num, char *name)
{
struct node *temp = malloc (sizeof *temp); /* allocate node */
if (!temp) {
fprintf (stderr, "error: virtual memory exhausted.\n");
exit (EXIT_FAILURE);
}
temp->id = num;
strcpy (temp->name, name);
if (!root) { /* empty list - insert first node */
temp->next = temp->prev = temp;
root = temp;
}
else if (root == root->next) { /* insert 2nd node */
temp->next = root;
root->prev = temp;
root->next = temp;
temp->prev = root;
}
else { /* insert all remaining nodes at end */
root->prev->next = temp;
temp->prev = root->prev;
temp->next = root;
root->prev = temp;
}
return temp;
}
void print (void)
{
struct node *temp = root;
printf ("\n Id Name\n ---- ---------------------\n");
while (temp->next != root) {
printf (" %4d %s\n", temp->id, temp->name);
temp = temp->next;
}
printf (" %4d %s\n", temp->id, temp->name);
printf ("\n");
}
/* free memory for all nodes in list */
void delete_list (void)
{
struct node *temp = root->next;
while (temp != root) {
struct node *victim = temp;
temp = temp->next;
free (victim);
}
if (temp) free (temp);
}
/** stip trailing newlines by overwriting with null-terminating char.
* str is modified in place.
*/
void rmcrlf (char *s)
{
if (!s || !*s) return;
for (; *s && *s != '\n'; s++) {}
*s = 0;
}
Example Use/Output
$ ./bin/ll_double_cir
Number of list entries to make?: 3
Enter name: cats
Enter id number: 3
Enter name: dogs
Enter id number: 17
Enter name: mice
Enter id number: 123
Id Name
---- ---------------------
3 cats
17 dogs
123 mice
Memory Use/Error Check
In any code your write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed.
It is imperative that you use a memory error checking program to insure you haven't written beyond/outside your allocated block of memory, attempted to read or base a jump on an unintitialized value and finally to confirm that you have freed all the memory you have allocated. For Linux valgrind is the normal choice. Usage is simple, just run your code through it and check the results:
$ valgrind ./bin/ll_double_cir
==14595== Memcheck, a memory error detector
==14595== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==14595== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==14595== Command: ./bin/ll_double_cir
==14595==
Number of list entries to make?: 3
Enter name: cats
Enter id number: 3
Enter name: dogs
Enter id number: 17
Enter name: mice
Enter id number: 123
Id Name
---- ---------------------
3 cats
17 dogs
123 mice
==14595==
==14595== HEAP SUMMARY:
==14595== in use at exit: 0 bytes in 0 blocks
==14595== total heap usage: 3 allocs, 3 frees, 192 bytes allocated
==14595==
==14595== All heap blocks were freed -- no leaks are possible
==14595==
==14595== For counts of detected and suppressed errors, rerun with: -v
==14595== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)
Always confirm All heap blocks were freed -- no leaks are possible and equally important ERROR SUMMARY: 0 errors from 0 contexts.
Look over the changes and if you have any questions, just ask.
What is is not doing?
Lookign at the code:
root should be initialized to NULL.
insert could be called as inert(Id, nName); instread of insert(Id, name_ptr);
in insert, you should initalize ->prev = NULL;

Insert node not values in end of linked lists

Lets say I have some linked lists already available and I want to store first node of each individual list into another list so that I can recall this list to display the original lists. I think we have to use two different structures. I am already successful in retaining original lists and displaying them using Array of first nodes of individual lists but I want to create a linked list of individual list to implement same. It has the expected output but as I said I want to use linked list instead of array of nodes.
Now this is how I am trying to solve the problem to replace the array of linked lists to linked list of first nodes, I am getting crashes whenever I try to debug code. Please help me.
#include <stdio.h>
#include <stdlib.h>
struct node{
int number;
struct node*next;
};
typedef struct node Node;
Node* insertValue(Node * list, int value);
void display(Node*);
struct list_of_nodes {
Node *list;
struct list_of_nodes *next;
};
typedef struct list_of_nodes ListNode;
ListNode* insertNode(ListNode* head,Node* node);
int main()
{
ListNode *head=NULL;
Node *globalList = NULL, *lists[100];
int nbrOfLists, listNo, nbrOfVal, valNo, val,i=0,k;
CHECKER:
printf("\n\n Enter the number of lists (1 to 100):");
scanf("%d", &nbrOfLists);
if(nbrOfLists <= 0 || nbrOfLists > 100) //handling exceptional cases
{
printf("\n \n Number of Lists should be between 1 to 100"); // since array of node pointers contains 100 elements
goto CHECKER;
}
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[listNo] = NULL;
for(valNo = 0; valNo < nbrOfVal; valNo++) // to enter values in each individual list
{
printf("Enter node value %d:", valNo+1);
scanf("%d", &val);
// Here we insert the value in both lists
lists[listNo]= insertValue(lists[listNo], val); // original list has to be retained so storing in array lists
globalList = insertValue(globalList, val); // inserting node in combined list. This prevents an extra loop and merges the list elements into one.
}
head=insertNode(head,lists[listNo]); // CRASHING HERE
printf("\n The list %d is: ",listNo+1);
display(lists[listNo]); // display each list after input
}
printf("\n\n\n THE FINAL LIST IS: ");
display(globalList); //display combined list
printf("\n\n THE LISTS WERE: ");
while(i<nbrOfLists){ //original lists displayed
k=i+1;
printf("\n\n The list %d is: ",k);
display(lists[i]);
i++;
}
printf("\n\n");
return 0;
}
ListNode* insertNode(ListNode* head, Node* node){
ListNode *newNode, *m;
newNode = malloc(sizeof(ListNode));
newNode->list=node;
if(newNode == NULL)
{
newNode->next=NULL; // inserting first node
return newNode;
}
m = head;
while(m->next) // checking for right position in ordered list for new node
{
m = m->next;
}
newNode->next = m->next; // inserting new node
m->next = newNode;
return head;
}
Node* insertValue(Node * list, int value) // function to insert node in ordered manner into list
{
Node *newNode, *m;
newNode = malloc(sizeof(Node));
newNode->number=value;
if(list == NULL)
{
newNode->next=NULL; // inserting first node
return newNode;
}
if(value < list->number)
{
newNode->next = list; // inserting in end
return newNode;
}
m = list;
while(m->next) // checking for right position in ordered list for new node
{
if(value < m->next->number)
break;
m = m->next;
}
newNode->next = m->next; // inserting new node
m->next = newNode;
return list;
}
void display(Node*nodex){ // display node values in list
printf("%d ->",nodex->number);
nodex=nodex->next;
if(nodex)
return display(nodex);
else
return 0;
}
Here is the code which shows expected results but with Array of nodes:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node{
int number;
struct node*next;
};
typedef struct node Node;
Node* insertValue(Node *list, int value);
void display(Node*);
int main()
{
Node *globalList = NULL, *lists[100];
int nbrOfLists, listNo, nbrOfVal, valNo, val, i = 0, k;
CHECKER:
printf("\n\n Enter the number of lists (1 to 100):");
scanf("%d", &nbrOfLists);
if(nbrOfLists <= 0 || nbrOfLists > 100) //handling exceptional cases
{
printf("\n \n Number of Lists should be between 1 to 100"); // since array of node pointers contains 100 elements
goto CHECKER;
}
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[listNo] = NULL;
for(valNo = 0; valNo < nbrOfVal; valNo++) // to enter values in each individual list
{
printf("Enter node value %d:", valNo + 1);
scanf("%d", &val);
// Here we insert the value in both lists
lists[listNo] = insertValue(lists[listNo], val); // original list has to be retained so storing in array lists
globalList = insertValue(globalList, val); // inserting node in combined list. This prevents an extra loop and merges the list elements into one.
}
printf("\n The list %d is: ", listNo + 1);
display(lists[listNo]); // display each list after input
}
printf("\n\n\n THE FINAL LIST IS: ");
display(globalList); //display combined list
printf("\n\n THE LISTS WERE: ");
while(i < nbrOfLists){ //original lists displayed
k = i + 1;
printf("\n\n The list %d is: ", k);
display(lists[i]);
i++;
}
printf("\n\n");
return 0;
}
Node* insertValue(Node *list, int value) // function to insert node in ordered manner into list
{
Node *newNode, *m;
newNode = malloc(sizeof(Node));
newNode->number = value;
if(list == NULL)
{
newNode->next = NULL; // inserting first node
return newNode;
}
if(value < list->number)
{
newNode->next = list; // inserting in end
return newNode;
}
m = list;
while(m->next) // checking for right position in ordered list for new node
{
if(value < m->next->number)
break;
m = m->next;
}
newNode->next = m->next; // inserting new node
m->next = newNode;
return list;
}
void display(Node *nodex){ // display node values in list
printf("%d ->", nodex->number);
nodex = nodex->next;
if(nodex)
return display(nodex);
else
return 0;
}
Please let me know if you do not understood the problem.
After considerable discussion in chat, I ended up using this code which is closely related to the last version in the question:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int number;
struct node *next;
};
typedef struct node Node;
Node *insertValue(Node *list, int value);
void display(Node *);
struct list_of_nodes
{
Node *list;
struct list_of_nodes *next;
};
typedef struct list_of_nodes ListNode;
ListNode *insertNode(ListNode *head, Node *node);
int main(void)
{
ListNode *head = NULL;
Node *globalList = NULL, *lists[100];
int nbrOfLists, listNo, nbrOfVal, valNo, val, i = 0, k;
CHECKER:
printf("\n\n Enter the number of lists (1 to 100):");
scanf("%d", &nbrOfLists);
if (nbrOfLists <= 0 || nbrOfLists > 100)
{
printf("\n \n Number of Lists should be between 1 to 100");
goto CHECKER;
}
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[listNo] = NULL;
for (valNo = 0; valNo < nbrOfVal; valNo++)
{
printf("Enter node value %d:", valNo + 1);
scanf("%d", &val);
lists[listNo] = insertValue(lists[listNo], val);
globalList = insertValue(globalList, val);
}
head = insertNode(head, lists[listNo]);
printf("\n The list %d is: ", listNo + 1);
display(lists[listNo]);
}
printf("\n\n\n THE FINAL LIST IS: ");
display(globalList);
printf("\n\n THE LISTS WERE: ");
while (i < nbrOfLists)
{
k = i + 1;
printf("\n\n The list %d is: ", k);
display(lists[i]);
i++;
}
printf("\n\n");
return 0;
}
ListNode *insertNode(ListNode *head, Node *node)
{
ListNode *newNode, *m;
newNode = malloc(sizeof(ListNode));
newNode->list = node;
newNode->next = NULL;
if (newNode == NULL)
{
fprintf(stderr, "Out of memory in %s\n", __func__);
exit(1);
}
if (head == NULL)
return newNode;
m = head;
while (m->next)
{
m = m->next;
}
newNode->next = m->next;
m->next = newNode;
return head;
}
Node *insertValue(Node *list, int value)
{
Node *newNode, *m;
newNode = malloc(sizeof(Node));
newNode->number = value;
newNode->next = NULL;
if (list == 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;
}
void display(Node *nodex)
{
printf("%d ->", nodex->number);
nodex = nodex->next;
if (nodex)
display(nodex);
}
With a sample data file (ll7.data):
3
6 26 22 83 96 89 69
10 87 33 5 36 85 34 0 25 57 99
5 49 44 27 75 82
I compiled ll7.c above using:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror ll7.c -o ll7
$
And ran it under valgrind which noted that the code leaks like a sieve (because there isn't a free in sight), but otherwise gave it a clean bill of health.
$ valgrind --suppressions=suppressions ./ll7 < ll7.data
==7696== Memcheck, a memory error detector
==7696== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7696== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info
==7696== Command: ./ll7
==7696==
--7696-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option
--7696-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 2 times)
--7696-- UNKNOWN mach_msg unhandled MACH_SEND_TRAILER option (repeated 4 times)
Enter the number of lists (1 to 100):
Enter the number of inputs to the list 1:
Enter node value 1:Enter node value 2:Enter node value 3:Enter node value 4:Enter node value 5:Enter node value 6:
The list 1 is: 22 ->26 ->69 ->83 ->89 ->96 ->
Enter the number of inputs to the list 2:
Enter node value 1:Enter node value 2:Enter node value 3:Enter node value 4:Enter node value 5:Enter node value 6:Enter node value 7:Enter node value 8:Enter node value 9:Enter node value 10:
The list 2 is: 0 ->5 ->25 ->33 ->34 ->36 ->57 ->85 ->87 ->99 ->
Enter the number of inputs to the list 3:
Enter node value 1:Enter node value 2:Enter node value 3:Enter node value 4:Enter node value 5:
The list 3 is: 27 ->44 ->49 ->75 ->82 ->
THE FINAL LIST IS: 0 ->5 ->22 ->25 ->26 ->27 ->33 ->34 ->36 ->44 ->49 ->57 ->69 ->75 ->82 ->83 ->85 ->87 ->89 ->96 ->99 ->
THE LISTS WERE:
The list 1 is: 22 ->26 ->69 ->83 ->89 ->96 ->
The list 2 is: 0 ->5 ->25 ->33 ->34 ->36 ->57 ->85 ->87 ->99 ->
The list 3 is: 27 ->44 ->49 ->75 ->82 ->
==7696==
==7696== HEAP SUMMARY:
==7696== in use at exit: 43,752 bytes in 471 blocks
==7696== total heap usage: 551 allocs, 80 frees, 49,880 bytes allocated
==7696==
==7696== LEAK SUMMARY:
==7696== definitely lost: 32 bytes in 2 blocks
==7696== indirectly lost: 688 bytes in 43 blocks
==7696== possibly lost: 0 bytes in 0 blocks
==7696== still reachable: 29,998 bytes in 310 blocks
==7696== suppressed: 13,034 bytes in 116 blocks
==7696== Rerun with --leak-check=full to see details of leaked memory
==7696==
==7696== For counts of detected and suppressed errors, rerun with: -v
==7696== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$
The prompting output isn't really wanted when the input comes from a file, and that's why the numbers aren't seen, too. When you type at the terminal, the terminal driver echoes what you type to the screen. When the data comes from a file, you don't see the characters as they're read.
The suppressions file lists and suppresses a variety of leaks from the Mac OS X 10.10.3 Yosemite runtime system. That's why there's so much memory in use, too; the runtime system uses a lot of memory.
Were it all my code, there'd be a lot that would be done differently. There is a lot of error checking that should be added and refactorization (especially 'extract function') that could/should be done, but those changes were not made to preserve some semblance to the code posted in the question.
Update: Just about 5 minutes before I finished this,
a new version of the code was posted
that seems to do what I recommended, but the new function was not quite right.
Here is one problem:
ListNode* insertNode(ListNode* head, Node* node){
// ... other code here ...
m = head;
while(m->next)
The first time insertNode is called, head is a null pointer
(which it should be, because the list of lists is still empty at that time).
So this sets m to a null pointer, and then attempts to access m->next ... oops!
I see this comment:
// checking for right position in ordered list for new node
Why? What is the "right position"? It appears that the "right position" is
the end of the list of lists; but what is wrong with the beginning?
If you absolutely must have the list of lists come out in the same order in
which the lists were input, then a simpler and more efficient design is to
insert each new list at the start of the list of lists, and when you are
all done, reverse the list of lists.
But you could also just adapt the code from insertValue a little more
carefully. Compare this code of insertValue:
newNode = malloc(sizeof(Node));
newNode->number=value;
if(list == NULL)
to this code of insertNode:
newNode = malloc(sizeof(ListNode));
newNode->list=node;
if(newNode == NULL)
Do you see the difference? In insertValue the if tests the pointer that was passed into the function; in insertNode the if tests the pointer that you have just assigned by newNode = malloc(sizeof(ListNode)).
Of course if(newNode == NULL) will never execute the body of the if
(unless something has already gone badly wrong).
What you need is to test if(head == NULL) so that you can handle
that case correctly.
The rest of this refers to the older version of the question.
Among other things that probably aren't doing what they're supposed to,
this piece of code has multiple serious flaws:
if(valNo==0){ // FOR EVERY FIRST NODE IN INDIVIDUAL LIST, I AM TRYING TO INSERT IT INTO LIST OF FIRST NODES
head->list=malloc(sizeof(Nodex));
head->list=lists[listNo];
head=head->next;
}
OK, first major flaw, you are trying to add the new list to the list of lists
before the list is complete. Until the list is complete, you don't know
what node will end up at the head of that list. The first node you insert
into the list could end up anywhere in the completed list.
That is not what you want to put in your list of lists.
One thing you should change in the code, therefore, is to move those lines
(the ones I copied) out of the inner for loop where they are now;
put them after the end of that loop instead
(and of course delete the if(valNo==0);
these lines should execute unconditionally).
Next thing, you never allocated a Nodex for head to point to,
so head->list will always be an access error.
Next thing, head->list=lists[listNo] overwrites the pointer you just
set with head->list=malloc(sizeof(Nodex)); the memory you allocated
with malloc(sizeof(Nodex)) is immediately leaked. (It was allocated using
the size of the wrong type anyway, since list was supposed to point to a
Node rather than a Nodex, although the Nodex is probably at least
large enough so you could get away with that mistake.)
Finally: head=head->next;??? Since head is the only Nodex* that you
declared at the start of the main() function, if there were ever a
legitimate Nodex in your list, after head=head->next
there would be nothing pointing to that Nodex any more, at least
nothing that you can find in your program. So if you succeeded in putting
anything in the list of lists, that step would essentially throw it away
(it would become a memory leak).
What you probably should do, for your sanity, is write a function
Nodex* insertList(Nodex* list_list, Node* value_list)
that inserts the head pointer of a list, value_list,
into your list of lists, analogously to the way
Node* insertValue(Node * list, int value) inserts a number into a list,
except that you probably don't need to make insertList keep its list
"sorted", so insertList should be considerably simpler than insertValue.
(In fact it will be so simple that you may be tempted to just write
the code of that function inline in your main function. I suggest you
resist the temptation; writing the code inline did not work for you on
the first attempt, and making even very simple functions to do well-defined
things is a good practice.)

Resources