why does my LinkListCreate function stop running? - c

I want to creat a link list by CreateLinkList(LinkList *L, int n), but the output of printf is 0 1 only.
It seems to stop at line 3 in CreateLinkList.
How can I fix it?
void CreateLinkList(LinkList *L, int n)
{
srand(time(0));
printf("1\n");
*L = (Node*)malloc(sizeof(Node)); \\ it seems to stop here
printf("2\n");
Node *flag = *L;
printf("3\n");
for (int i=0; i<n; i++)
{
Node *newNode = (Node*)malloc(sizeof(Node));
newNode->data = rand() %100+1;
flag->next = newNode;
flag = newNode;
}
printf("4\n");
flag->next = NULL;
printf("5\n");
}
int main()
{
LinkList *p;
printf("0");
CreateLinkList(p, 10);
return 0;
}
The LinkList and Node were defined as:
typedef struct
{
int data;
struct Node *next;
} Node;
typedef Node *LinkList;

For starters this structure definition
typedef struct
{
int data;
struct Node *next;
} Node;
is invalid. Within the structure the type struct Node * is not the same as the typedef name Node.
Write instead
typedef struct Node
{
int data;
struct Node *next;
} Node;
Neither the node L nor the node flag are initialized.
*L = (Node*)malloc(sizeof(Node)); \\ it seems to stop here
printf("2\n");
Node *flag = *L;
So this statement
flag->next = newNode;
invokes undefined behavior.
Moreover the pointer p is not also initialized in main
LinkList *p;
So even this call
*L = (Node*)malloc(sizeof(Node));
also invokes undefined behavior.
In any case it is a bad idea to use such a typedef like
typedef Node *LinkList;
because it only confuses readers of the code.
The function can be defined as it is shown in the demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct Node
{
int data;
struct Node *next;
} Node;
typedef Node *LinkList;
void CreateLinkList( LinkList *head, unsigned int n )
{
const int MAX_VALUE = 100;
srand( ( unsigned int )time( NULL ) );
for ( unsigned int i = 0; i < n; i++ )
{
*head = malloc( sizeof( Node ) );
( *head )->data = rand() % MAX_VALUE + 1;
( *head )->next = NULL;
head = &( *head )->next;
}
}
void print( LinkList head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "NULL" );
}
int main(void)
{
LinkList head = NULL;
CreateLinkList( &head, 10 );
print( head );
return 0;
}
The program output might look like
14 -> 40 -> 17 -> 54 -> 8 -> 48 -> 40 -> 25 -> 99 -> 41 -> NULL

Related

Why isn't my reverse(); function working?

I'm writing a program in C for reversing a circular singly linked list. I keep getting segmentation fault for some reason. I'm sure the problem is with the reverse function as I tried commenting the function call, the program works fine.
For my reverse() function, I have used 3 pointers: prev, next and curr. The logic is that I'll run a loop till curr takes the address of head, which will be stored in the link part of the last node since it is a circular linked list. I'll keep updating curr->link using prev pointer which will change its link from the next to its previous node.
When the loop breaks, head->link = prev; and head = prev; will update the respective addresses such that they point to the first node of the reversed list.
//reversing CLL
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
} *head;
void reverse() {
struct node *prev = NULL, *curr = head, *next;
while (curr != head) {
next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
}
head->link = prev;
head = prev;
}
void createList(int n) {
int i, data;
head = (struct node *)malloc(sizeof(struct node));
struct node *ptr = head, *temp;
printf("Enter data of node 1\t");
scanf("%d", &data);
head->data = data;
head->link = NULL;
for (i = 2; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
printf("Enter data of node %d\t", i);
scanf("%d", &data);
temp->data = data;
temp->link = NULL;
ptr->link = temp;
ptr = ptr->link;
}
ptr->link = head;
}
void disp() {
struct node *ptr = head;
do {
printf("%d\t", ptr->data); //gdb debugger shows problem is in this line
ptr = ptr->link;
} while (ptr != head);
}
int main() {
int n;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
createList(n);
printf("\n\nList is displayed below!\n");
disp();
printf("\n\nReversing list ...\n");
reverse(); // on commenting this call, disp() function
// works accurately showing node data non-reversed
disp();
printf("\n\nList successfully reversed!\n");
}
The loop in the reverse() function exits immediately because curr is initialized to the value of head so the test while (curr != head) is false at the first iteration.
reverse() then sets head->link to NULL and finally head is also set to NULL (the initial value of prev), which explains the segmentation fault in the subsequent disp() function where you use a do { } while (pre != head) that cannot handle an empty list.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *link;
};
struct node *reverse(struct node *head) {
struct node *prev = NULL, *curr = head;
if (head) {
do {
struct node *next = curr->link;
curr->link = prev;
prev = curr;
curr = next;
} while (curr != head);
curr->link = prev;
head = prev;
}
return head;
}
struct node *createList(int n) {
struct node *head = NULL, *tail = NULL, *temp;
int i;
for (i = 1; i <= n; i++) {
temp = (struct node *)malloc(sizeof(struct node));
temp->data = 0;
temp->link = NULL;
printf("Enter data of node %d\t", i);
scanf("%d", &temp->data);
if (head == NULL) {
head = temp;
} else {
tail->link = temp;
}
tail = temp;
temp->link = head;
}
return head;
}
void disp(struct node *head) {
if (head) {
struct node *ptr = head;
do {
printf("%d\t", ptr->data);
ptr = ptr->link;
} while (ptr != head);
}
}
int main() {
struct node *head;
int n = 0;
printf("Enter no of nodes to be created\t");
scanf("%d", &n);
head = createList(n);
printf("\n\nList is displayed below!\n");
disp(head);
printf("\n\nReversing list ...\n");
head = reverse(head);
disp(head);
printf("\n\nList successfully reversed!\n");
// should free the list
return 0;
}
For starters it is a bad idea to use the global variable head
struct node {
int data;
struct node *link;
} *head;
In this case the functions depend on the global variable and you can not use more than one list in a program.
Due to this initialization
struct node *prev = NULL, *curr = head, *next;
^^^^^^^^^^^^
the condition of the while loop
while (curr != head) {
is never evaluates to true because initially the pointer curr is equal to the pointer head.
Moreover if the list is empty then this statement
head->link = prev;
invokes undefined behavior.
Here is a demonstrative program that shows how the list can be declared in main and then reversed.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *link;
};
size_t assign( struct node **head, const int a[], size_t n )
{
while ( *head )
{
struct node *tmp = *head;
*head = ( *head )->link;
free( tmp );
}
size_t total = 0;
struct node *first = NULL;
while ( total < n && ( *head = malloc( sizeof( struct node ) ) ) != NULL )
{
( *head )->data = a[total];
( *head )->link = NULL;
++total;
if ( first == NULL ) first = *head;
head = &( *head )->link;
}
if ( first != NULL ) *head = first;
return total;
}
void display( const struct node *head )
{
if ( head != NULL )
{
const struct node *current = head;
do
{
printf( "%d -> ", current->data );
} while ( ( current = current->link ) != head );
}
puts( "null" );
}
struct node * reverse( struct node **head )
{
if ( *head )
{
struct node *last = *head;
struct node *prev = NULL;
while ( ( *head )->link != last )
{
struct node *current = *head;
*head = ( *head )->link;
current->link = prev;
prev = current;
}
( *head )->link = prev;
last->link = *head;
}
return *head;
}
int main(void)
{
struct node *head = NULL;
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
assign( &head, a, sizeof( a ) / sizeof( *a ) );
display( head );
display( reverse( &head ) );
display( reverse( &head ) );
return 0;
}
The program output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9 -> 8 -> 7 -> 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> 0 -> null
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null

C - How to split a linked list with struct type data

I have a problem that require Splitting a singly linked list into 2 part with a function: Split(n1, n2) where n1 = position of the element, n2 is number of elements to be split. I've managed to come up with an algorithm and a Testing program:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Node
{
int value;
struct Node *next;
};
int push_front( struct Node **head, int value )
{
struct Node *new_node = malloc( sizeof( struct Node ) );
int success = new_node != NULL;
if ( success )
{
new_node->value = value;
new_node->next = *head;
*head = new_node;
}
return success;
}
void display( const struct Node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->value );
}
//puts( "null" );
}
struct ListPair
{
struct Node *head1;
struct Node *head2;
};
struct ListPair split( struct Node **head, size_t pos, size_t n )
{
struct ListPair p = { .head1 = NULL, .head2 = NULL };
struct Node **current1 = &p.head1;
struct Node **current2 = &p.head2;
for ( size_t i = 0; *head != NULL && i != pos; i++ )
{
*current2 = *head;
*head = ( *head )->next;
( *current2 )->next = NULL;
current2 = &( *current2 )->next;
}
while ( *head != NULL && n-- )
{
*current1 = *head;
*head = ( *head )->next;
( *current1 )->next = NULL;
current1 = &( *current1 )->next;
}
while ( *head != NULL )
{
*current2 = *head;
*head = ( *head )->next;
( *current2 )->next = NULL;
current2 = &( *current2 )->next;
}
return p;
}
int main(void)
{
const size_t N = 15;
struct Node *head = NULL;
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < N; i++ )
{
push_front( &head, rand() % N );
}
display( head );
putchar( '\n' );
struct ListPair p = split( &head, 6, 3 );
display( head );
display( p.head1 );
display( p.head2 );
return 0;
}
The result is:
12 -> 14 -> 3 -> 0 -> 12 -> 5 -> 4 -> 0 -> 2 -> 14 -> 1 -> 0 -> 6 -> 0 -> 5 -> null
null
5 -> 4 -> 0 -> 2 -> 14 -> null
12 -> 14 -> 3 -> 0 -> 12 -> 1 -> 0 -> 6 -> 0 -> 5 -> null
But don't know how to implement the above into my linked list, which is:
typedef struct address_t
{
char name[30];
char storage[5];
char screen[5];
int price;
} address;
typedef address elementtype;
typedef struct node node;
typedef struct node{
elementtype element;
node *next;
};
node *root, *cur, *prev;
Please help :(
Overview
As far as I understand the question you simply want to remove a sublist from a single linked list e.g. the list = el1 -> el2 -> el5 -> el6 -> el3 -> null. When you call split(list, 2, 2) the result will be two lists list and list1 with list = el1 -> el2 -> el3 -> null and list1 = el5 -> el6 -> null.
But what is not really clear is what the actual problem is you are facing, and what have you tried so far to make it work?
Answer
From how I read the question it is not really important, how the content of each list element looks like. So why don't you just take your struct Node from the example and replace the field int value by address value like the following:
typedef struct {
char name[30];
char storage[5];
char screen[5];
int price;
} address;
struct Node
{
address value;
struct Node *next;
};
There are a few issues in your code you might want to change.
1. Your split function sets the passed in pointer head to NULL. This might not be wanted behavior
2. You are returning a struct from split(...). Since everything in C is passed around by value you might consider passing a (double-)pointer to split(...) as well and put the resulted ListPair in there, because then the ListPair has not to be copied when returning from the function
3. Normally you would not use a _t for the struct name but not for the typedef itself.
4. You typedef the struct address_t and typedef the type with elementtype, but never used address
5. You have a typedef, that does not have a name
typedef struct node{
elementtype element;
node *next;
};
Just remove the typedef in that line, because you already did a typedef one line before.

How to keep track of and return the head of a linked list in C while adding a node to the end

Currently I have a node struct that looks like the following:
struct Node {
int data;
Node* next;
};
and I want to implement a function that will make a linked list given a list of elements and will return the head of the list. I currently have the following structure:
struct Node *make_list(int values[10]) {
struct Node *curr;
head = (struct Node*) malloc(sizeof(struct Node));
struct Node *head;
head->value = values[0];
head->next = NULL;
curr = head;
for (int i = 1; i < 10 i++) {
struct Node *tmp;
tmp->value=values[i];
curr->next=tmp;
}
return head;
}
For some reason this code is always returning NULL as the head of the linked list, but after that null element, the 10 elements are in order. Does anybody know why this is happening?
For starters this declaration of node
struct Node {
int data;
Node* next;
};
is invalid in C. You have to declare the structure like
struct Node {
int data;
struct Node* next;
};
Your function definition will not compile and does not make great sense.
It can be defined for example the following way
struct Node * make_list( const int values[], size_t n )
{
struct Node *head = NULL;
struct Node **current = &head;
for ( size_t i = 0; i < n; i++ )
{
*current = malloc( sizeof( struct Node ) );
( *current )->data = values[i];
( *current )->next = NULL;
current = &( *current )->next;
}
return head;
}
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;
};
struct Node * make_list( const int values[], size_t n )
{
struct Node *head = NULL;
struct Node **current = &head;
for ( size_t i = 0; i < n; i++ )
{
*current = malloc( sizeof( struct Node ) );
( *current )->data = values[i];
( *current )->next = NULL;
current = &( *current )->next;
}
return head;
}
void out( struct Node *head )
{
for ( ; head != NULL; head = head->next )
{
printf( "%d -> ", head->data );
}
puts( "null" );
}
int main(void)
{
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
const size_t N = sizeof( a ) / sizeof( *a );
struct Node *head = make_list( a, N );
out( head );
return 0;
}
Its output is
0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
An alternative to Vlad's answer (which I think will be simpler to understand):
struct Node *make_list(int values[10]) {
struct Node* head = (struct Node*) malloc(sizeof(struct Node));
head->value = values[0];
head->next = NULL;
struct Node *curr;
curr = head;
for (int i = 1; i < 10; i++) {
struct Node* tmp = (struct Node*) malloc(sizeof(struct Node));
tmp->value=values[i];
tmp->next = NULL;
curr->next=tmp;
curr = tmp;
}
return head;
}
You must always allocate new memory to a new node
struct Node* tmp = (struct Node*) malloc(sizeof(struct Node));
otherwise it will be lost after the function finishes.
Then, you must ensure that you new node receives the correct values:
tmp->value=values[i];
tmp->next = NULL;
Finally, you need to update your curr node, so it points to the last item in the list (usually we call this as tail).
next=tmp;
curr = tmp;
You can try it out here.

how can i swap two nodes without exchanging data

#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *head;
void createnodeatbeg(int key) {
struct node *new = (struct node*)malloc(sizeof(struct node));
new->data = key;
new->next = head;
head = new;
}
void printlist() {
struct node *temp = head;
printf("list is:");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
void swapnodes(int x, int y) {
struct node *prevX = NULL;
struct node *prevY = NULL;
struct node *currX = head;
struct node *currY = head;
while (currX->data != x && currX != NULL) {
prevX = currX;
currX = currX->next;
}
printf("not found\n");
while (currY->data != y && currY != NULL) {
prevY = currY;
currY = currY->next;
}
if (currX == NULL || currY == NULL) {
printf("elements not found\n");
return;
}
struct node *swap = currY->next;
prevX->next = currY;
currY->next = prevY;
prevY->next = currX;
currX->next = swap;
}
int main() {
head = NULL;
int nodes, key;
printf("enter number of nodes\n");
scanf("%d", &nodes);
for (int i = 0; i < nodes; i++) {
int data;
printf("enter number\n");
scanf("%d", &data);
createnodeatbeg(data);
}
printlist();
int x, y;
printf("enter the values from the list to be swapped\n");
scanf("%d %d", &x, &y);
swapnodes(x, y);
printf("swapped list is:\n");
printlist();
}
My code works when elements (x and y) are present in the list but if it is not present in the list then error is ./a.out terminated by signal SIGSEGV (Address boundary error).
The problem is that the control doesn't comes out of the first while loop in swapNodes() function.
The code takes a user input and creates a node at the beginning.
The order of operands in the conditions of the while statements is wrong.
while(currX->data!=x && currX!=NULL)
{
prevX=currX;
currX=currX->next;
}
//...
while(currY->data!=y && currY!=NULL)
{
prevY=currY;
currY=currY->next;
}
Here must be
while(currX != NULL && currX->data!=x)
{
prevX=currX;
currX=currX->next;
}
//...
while(currY != NULL && currY->data!=y)
{
prevY=currY;
currY=currY->next;
}
So if for example currX is equal to NULL then the expression currX->data!=x will not be eva;luated.
This code snippet
struct node *swap = currY->next;
prevX->next = currY;
currY->next = prevY;
prevY->next = currX;
currX->next = swap;
is also wrong because for example prevX or prevY can be equal to NULL.
And you have to deal with the head in the function by reference. Otherwise the head node will not be changed.
You should split the function into two functions. The first one founds the node with the given value and the second one will swap found nodes if they are not equal to NULL.
Also it is a bad idea when functions depend on global variables. In fact your program can not deal with two lists simultaneously.
Here is a demonstrative program that shows how the function swap can be implemented.
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node ** find( struct node **head, int data )
{
while ( *head && ( *head )->data != data ) head = &( *head )->next;
return head;
}
void swap( struct node **head, int data1, int data2 )
{
struct node **left, **right;
if ( *( left = find( head, data1 ) ) && *( right = find( head, data2 ) ) )
{
struct node *tmp = *left;
*left = *right;
*right = tmp;
tmp = ( *left )->next;
( *left )->next = ( *right )->next;
( *right )->next = tmp;
}
}
int push_front( struct node **head, int data )
{
struct node *tmp = malloc( sizeof( struct node ) );
int success = tmp != NULL;
if ( success )
{
tmp->data = data;
tmp->next = *head;
*head = tmp;
}
return success;
}
void display( struct node **head )
{
for ( struct node *current = *head; current; current = current->next )
{
printf( "%d ", current->data );
}
}
int main(void)
{
const int N = 10;
struct node *head = NULL;
for ( int i = 0; i < N; i++ ) push_front( &head, i );
display( &head );
putchar( '\n' );
for ( int i = 0; i < N; i+=2 )
{
swap( &head, i, i + 1 );
}
display( &head );
putchar( '\n' );
return 0;
}
Its output is
9 8 7 6 5 4 3 2 1 0
8 9 6 7 4 5 2 3 0 1
The problem is in following identical lines:
while(currX->data!=x && currX!=NULL)
while(currY->data!=y && currY!=NULL)
This is because instead of fist checking for NULL and then use it, you are checking for NULL latter. So when x or y is not present then you are trying to access NULL->data, which is giving Segmentation Fault Error (SIGSEGV)
Change it to following respectively:
while(currX!=NULL && currX->data!=x)
while(currY!=NULL && currY->data!=y)

Linked list and pointers

I'm trying to pass to a pointer my address of the linked list in main,pass it in a function to allocate memory to it and traverse to the next node while keeping the position of the next node without breaking head node.
typedef struct {
int data;
struct node_list *next;
}node_list;
typedef struct {
struct node_list *head;
}list;
void insert_list(node_list **c, int num);
void main()
{
int num;
list *list_odd = (list*)calloc(1, sizeof(list));
node_list *c = &list_odd->head;
while (num != -1)
{
if (num % 2)
insert_list(c, num);
}
}
void insert_list(node_list **c, int num)
{
if (*c == NULL)
{
*c = (node_list*)malloc(sizeof(node_list)); // it allocates the memory in the right place.
(*c)->data = num;
(*c) = (*c)->next; // but this step breaks the starting list pointer
}
else
{
(*c)->next = (node_list*)malloc(sizeof(node_list));
(*c)->data = num;
(*c) = (*c)->next;
}
}
Edit: I may not explained myself, To clarify: If my list points to the start of the linked-list, while I allocate memory to it and then do (*c) = (*c)->next, my head no longer points to the begging. What I'm trying to achieve is having the start of the list and saving the position of the next node.
I'd like to suggest a two-sided singly linked list.
Here is a demonstrative program.
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
int data;
struct node *next;
} node;
typedef struct list
{
node *head;
node *tail;
} list;
int push_back( list *lst, int data )
{
node *new_node = malloc( sizeof( node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( lst->tail == NULL )
{
lst->tail = lst->head = new_node;
}
else
{
lst->tail = lst->tail->next = new_node;
}
}
return success;
}
void display( list *lst )
{
for ( node *current = lst->head; current != NULL; current = current->next )
{
printf( "%d ", current->data );
}
printf( "\n" );
}
int main( void )
{
list lst = { NULL, NULL };
int data;
while ( scanf( "%d", &data ) == 1 && data != -1 )
{
if ( data % 2 != 0 ) push_back( &lst, data );
}
display( &lst );
return 0;
}
If to enter this sequence of numbers
0 1 2 3 4 5 6 7 8 9 -1
then the output will be
1 3 5 7 9
The complexity of adding a new node to the end of the list is O(1).
What I'm trying to achieve is having the start of the list and saving the position of the next node.
I'm not entirely sure what you're trying to do, so I've made an equivalent program. If you find this way of adding to the list to be too slow, then the program needs to be changed to either keep a {head, tail} pair or add items to the front of the list. From your text it sounds like you're trying to keep the head the same -- so a {head,tail} pair is probably best.
#include <stdlib.h> //added
#include <stdio.h> //added
#include <assert.h>
typedef struct node_list_t { //changed
int data;
struct node_list_t *next; //changed
} node_list;
typedef struct list_t { //gave the struct a tag
node_list *head; //use the typedef name, not the struct name
}list;
void insert_list(list *my_list, int num);
void main()
{
int num = 0; // initialised
list my_list = {0}; // changed to be on stack. Could be calloc'd if you like
node_list* printer;
while (num != 50) //changed limit
{
if (num % 2)
{
// we're just passing in the list
insert_list(&my_list, num);
}
num += 1; //actually incrementing number. :)
}
for (printer = my_list.head;
printer;
printer = printer->next)
{
printf("%d\n", printer->data);
}
}
void insert_list(list *my_list, int num)
{
node_list *c = (node_list*) calloc(1, sizeof(node_list));
c->data = num;
assert(!c->next);
if (!my_list->head)
{
// if the head is not initialised, then make C the head
my_list->head = c;
}
else
{
// otherwise stick it on the end of the list.
node_list *p;
for (p = my_list->head;
p->next;
p = p->next)
{
//do nothing
}
p->next = c;
}
}

Resources