Unable to swap nodes in single linked list - c

Im currently trying to make an algorithm that creates a single linked list, and sorts it in ascending order (user input n and numbers).
I can create the list fine, but when i try to swap 2 nodes value, it gives exits, segmentation fault.
I have a strong feeling it has to do with my dynamically allocated memory for the nodes, but im very new to programming, so i could use any help locating the fault
#include <stdio.h>
#include <stdlib.h>
struct node {
int val;
struct node *next;
}*node_st;
void createlist (int n) {
struct node *fnNode, *temp;
int i, num;
node_st = (struct node *)malloc(sizeof(struct node));
if (node_st == NULL) {
printf("Memory allocation fault!");
exit(0);
}
else {
printf("Input data for node 1:");
scanf("%d",&num);
node_st->val =num;
node_st->next = NULL;
temp = node_st;
for (i=2;i<=n;i++) {
fnNode = (struct node *)malloc(sizeof(struct node));
if (fnNode == NULL) {
printf("Memory allocation fault!");
break;
}
else {
printf("input data for node %d : ", i);
scanf("%d",&num);
fnNode->val = num;
fnNode->next = NULL;
temp->next = fnNode;
temp = temp->next;
}
}
}
}
void showlist() {
struct node *temp;
if (node_st == NULL) {
printf("List is empty..");
}
else {
temp = node_st;
while (temp != NULL) {
printf("Value = %d \n",temp->val);
temp = temp->next;
}
}
}
void sort(int n) {
struct node *temp;
struct node *temp2;
if (node_st == NULL) {
printf("List is empty..");
}
else {
temp = node_st;
temp2 = temp->next;
while (temp != NULL) {
if (temp->val > temp2->val) {
printf("test!!!");
temp = temp2;
temp2 = temp->next;
}
}
}
}
int main(void) {
int n,a,x,y,z;
printf("Input amount of nodes you want");
scanf("%d",&n);
createlist(n);
printf("Data entered: \n");
showlist();
sort(n);
return 0;
}
aplogize in advance for the messy code, again im new and havent cleaned it up 100%.

Related

Linked list unable to print all elements

I'm trying to print the linked list to which I prompt for user input.
This code below is not printing the whole list, only the last element at a time.
I don't seem to find the bug. Can you please take a look at it?
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
struct Node *head;
void Insert(int x) {
struct Node *temp = (struct Node *)malloc(sizeof(struct Node));
temp->data = x;
temp->next = NULL;
head = temp;
};
void Print() {
struct Node *temp = head;
printf("Linked list is: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
};
int main() {
head = NULL;
int i, x;
for (i = 1; i <= 10; i++) {
if (i == 1) {
printf("Enter 1st number: \n");
} else if (i == 2) {
printf("Enter 2nd number: \n");
} else {
printf("Enter %dth number: \n", i);
}
scanf("%d", &x);
Insert(x);
Print();
}
}
temp->next = NULL; is the culprit. It should be temp->next = head;.
Another (more cornercase) issue is that your code fails to check for errors in malloc and scanf.
Edit in response to comment:
If you want to append (as opposed to prepend), you'll need to keep a tail pointer for forward traversal and then either use a dummy first node (avoids a branch) or special-case an insert to an empty list.
Example of both (with simplistic error handling via exit(1)) in one piece of code:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
#define DUMMYFIRST 1 //change to 0 to compile the other variant
#if DUMMYFIRST
struct Node dummyfirst;
struct Node *head=&dummyfirst;
#else
struct Node *tail,*head=0;
#endif
void Insert(int x) {
struct Node *newnode = malloc(sizeof(struct Node));
//don't cast the result of malloc in C
//https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc
if(!newnode) { perror("malloc"); exit(1); }
newnode->data = x;
newnode->next = 0;
#if !DUMMYFIRST
if(!tail) tail = head = newnode;
else head->next = newnode;
#else
head->next = newnode;
#endif
head = newnode;
};
void Print() {
#if DUMMYFIRST
struct Node *newnode = dummyfirst.next;
#else
struct Node *newnode = tail;
#endif
printf("Linked list is: ");
while (newnode != NULL) {
printf("%d ", newnode->data);
newnode = newnode->next;
}
printf("\n");
};
int main() {
int i, x;
for (i = 1; i <= 10; i++) {
if (i == 1) {
printf("Enter 1st number: \n");
} else if (i == 2) {
printf("Enter 2nd number: \n");
} else {
printf("Enter %dth number: \n", i);
}
if(1!=scanf("%d", &x)) exit(1);
Insert(x);
Print();
}
}
A more library friendly approach to handling errors would be to propagate the error to the caller, i.e., instead of exiting with an error message right away, you'd change the return value from void to something indicating the error, e.g. so that the caller could check and decide what to do (print it, print it in a localized version, try a different algorithm...)
E.g.:
struct Node *Insert(int x) {
struct Node *newnode = malloc(sizeof(struct Node));
//don't cast the result of malloc in c
//https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc
if(!newnode) return NULL;
//...
};
//...
//calling code:
if(!Insert(x)) perror("Insert"),exit(1);
When you insert the new node, you do not link the rest of the list, instead of temp->next = NULL; you should write
temp->next = head;
To ensure defined behavior, you should check for memory allocation failure and invalid input.
Also remove the dummy ; after the function bodies.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
};
struct Node *head;
int Insert(int x) {
struct Node *temp = malloc(sizeof(*temp));
if (temp) {
temp->data = x;
temp->next = head;
head = temp;
return 1;
} else {
return 0;
}
}
void Print(void) {
struct Node *temp = head;
printf("Linked list is: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main() {
static char suffix[4][3] = { "th", "st", "nd", "rd" };
int i, x;
for (i = 1; i <= 10; i++) {
int suff = (i >= 1 && i <= 3) ? i : 0;
printf("Enter %d%s number:\n", i, suffix[suff]);
if (scanf("%d", &x) != 1) {
fprintf(stderr, "invalid or missing input\n");
break;
}
if (!Insert(x)) {
fprintf(stderr, "cannot allocate memory for Node\n");
return 1;
}
Print();
}
return 0;
}

Keep printing the last element in the linked list

I created a standard linked list in C. It asks the user to input a number, and program end if user input #. If the user inputs anything else the program will stop.
The problem is that my program runs forever and prints the normal list at first then keeping print the last element of the linked list.
Hope someone could tell me where did I made mistake.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} NodeT;
void freeLL(NodeT *list) {
NodeT *p, *temp;
p = list;
while (p != NULL) {
temp = p->next;
free(p);
p = temp;
}
}
void showLL(NodeT *list) {
NodeT *temp = list;
temp = temp->next;
printf("Done. The list is ");
printf("%d", temp->data);
temp = temp->next;
//iterate the entire linked list and print the data
while (temp != NULL) {
printf("-->");
printf("%d", temp->data);
temp = temp->next;
}
}
NodeT *joinLL(NodeT *list, int v) {
NodeT *current = list;
NodeT *head;
head->data = v;
head->next = NULL;
while (current->next != NULL) {
current = current->next;
}
current->next = head;
return head;
}
int main() {
int data;
NodeT *list = NULL;
list = (NodeT *)malloc(sizeof(NodeT));
printf("Enter a number: ");
if (scanf("%d", &data) != 1) {
printf("Done. ");
} else {
printf("Enter a number: ");
joinLL(list, data);
while (1 == scanf("%d", &data)) {
printf("Enter a number: ");
joinLL(list, data);
}
showLL(list);
freeLL(list);
}
return 0;
}
I believe the problem is in the joinLL function which add a new node at the end of the linked list.
The problem is you do not allocate elements in joinLL: only a single element in allocated in main().
You should instead always allocate the element in joinLL and update the head pointer from the return value.
Similary, freeLL should take a pointer to head and set it to NULL for consistency.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} NodeT;
void freeLL(NodeT *p) {
while (p != NULL) {
NodeT *temp = p->next;
free(p);
p = temp;
}
}
void showLL(const NodeT *list) {
NodeT *p = list;
printf("The list is ");
if (p == NULL) {
printf("empty");
} else {
printf(" %d", temp->data);
while ((p = p->next) != NULL) {
printf("--> %d", temp->data);
}
}
printf("\n");
}
NodeT *joinLL(NodeT *head, int v) {
NodeT *newp = malloc(sizeof(*p));
NodeT *current;
if (newp == NULL) {
fprintf(stderr, "allocation failure\n");
exit(1);
}
newp->data = v;
newp->next = NULL;
if (head == NULL) {
return newp;
}
for (current = head; current->next != NULL; current = current->next)
continue;
current->next = newp;
return head;
}
int main() {
NodeT *list = NULL;
for (;;) {
int data;
printf("Enter a number: ");
if (scanf("%d", &data) != 1) {
printf("Done. ");
break;
}
list = joinLL(list, data);
}
showLL(list);
freeLL(list);
return 0;
}
Your program keeps running because of a memory access error, you did not allocate memory for your head(you set a pointer, but use it directly without initializing it)
Change to this may solve the problem:
head=(NodeT*)malloc(sizeof(NodeT));
if(NULL==head)
{
// failed : do something...
return NULL;
}
head->data=v;
head->next=NULL;
When I just tested it, I found that there was another problem:
list = (NodeT*)malloc(sizeof(NodeT));
malloc will not be initialize your list, so the value that your list->next initially points to is uncertain.
in c, malloc does not need to be cast.

Traversing single linked list not working why?

im starting to learn data structures and i tried to making a simple program about a single linked list.
The problem is that when i call my display function (transversing the list) it doesn't give me an output? What is wrong with my code and how do i fix this?
This my program:
int main(){
int n;
printf(" Input the number of nodes : ");
scanf("%d", &n);
create(n);
printf("\n Data entered in the list : \n");
display();
}
void create(int n)
{
struct node *head=NULL;
int data, i;
head = (struct node *)malloc(sizeof(struct node));
if(head == NULL)
{
printf(" Memory can not be allocated.");
}
else
{
printf(" Input data for node 1 : ");
scanf("%d", &data);
head->data = data;
head->next = NULL;
for(i=1; i<n; i++) // Creating n nodes
{
struct node *current = (struct node *)malloc(sizeof(struct node)); // addnode
if(current == NULL)
{
printf(" Memory can not be allocated.");
break;
}
else
{
printf(" Input data for node %d : ", i);
scanf(" %d", &data);
current->data = data;
current->next = NULL;
head->next = current;
head = head->next;
}
}
}
}
My Traversing function:
void display(struct node *head)
{
struct node* ptr = head;
if(head == NULL)
{
printf(" List is empty.");
}
else
{
while(ptr != NULL)
{
printf(" Data = %d\n", ptr->data);
ptr = ptr->next;
}
}
}
The problem are lines in create()
head->next = current;
head = head->next;
this operation set head to current. Note that current->next is NULL. As result the entire content of the list is lost except the last element.
Just replace those lines with:
current->next = head;
head = current;
This will put the current node at the top of the list.
Remember to return head from create().
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node * next;
};
struct node * create(int n) {
struct node *head=NULL;
int data, i;
struct node * ptmp = NULL;
head = (struct node *)malloc(sizeof(struct node));
if(head == NULL) {
printf(" Memory can not be allocated.");
} else {
printf(" Input data for node 1 : ");
scanf("%d", &data);
head->data = data;
head->next = NULL;
ptmp = head;
for(i=1; i<n; i++) {
struct node *current = (struct node *)malloc(sizeof(struct node)); // addnode
if(current == NULL) {
printf(" Memory can not be allocated.");
break;
} else {
printf(" Input data for node %d : ", i);
scanf(" %d", &data);
#if 0
// insert first
current->data = data;
current->next = head;
head = current;
#else
// insrt last
current->data = data;
current->next = NULL;
ptmp->next=current;
ptmp = current;
#endif
}
}
}
return head;
}
void display(struct node *head)
{
struct node* ptr = head;
if(head == NULL) {
printf(" List is empty.");
} else {
while(ptr != NULL) {
printf(" Data = %d\n", ptr->data);
ptr = ptr->next;
}
}
}
int main() {
int n = 0;
printf(" Input the number of nodes : ");
scanf("%d", &n);
if (n<=0 || n > 6400) {
printf("Invalid input : %d (Enter value in range 0-6400)\n", n);
return 0;
}
struct node * head = create(n);
printf("\n Data entered in the list : \n");
display(head);
}

Correct way to delete a node in doubly circular linked list

The purpose of this code is to manage insertion and deletion and visualisation. I just want to know if I'm doing everything correctly, let me know if there are more possible ways to do this. This is my first attempt, i didn't follow any tutorial.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
int n;
struct Node *next;
struct Node *prev;
}TNode;
typedef TNode* Node;
void NewNode(Node *pp, int n)
{
Node temp, last;
temp = (Node)malloc(sizeof(struct Node));
temp->n = n;
temp->next = temp;
temp->prev = temp;
if(*pp != NULL)
{
last = (*pp)->prev;
temp->next = (*pp);
temp->prev = last;
last->next = (*pp)->prev = temp;
}
*pp = temp;
}
void ViewList(Node head)
{
if(head == NULL)
{
return;
}
Node node = head->prev;
do
{
printf("Curr: %d\n", node->n);
node = node->prev;
}while(node != head->prev);
}
void ReadData(Node * head, int * n)
{
printf("\nInsert a number:");
scanf("%d", n);
NewNode(head, *n);
}
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
while(head != NULL)
{
if(head->n == d)
{
return head;
}
head = head->next;
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
void Delete(Node * head)
{
Node del = SearchNode(*head);
if(*head == NULL || del == NULL)
{
return;
}
if(*head == del && del->next == *head)
{
*head = NULL;
free(del);
return;
}
if(*head == del)
{
*head = del->next;
del->prev->next = *head;
(*head)->prev = del->prev;
free(del);
return;
}
if((*head)->prev == del)
{
(*head)->prev = del->prev;
del->prev->next = *head;
free(del);
return;
}
del->next->prev = del->prev;
del->prev->next = del->next;
free(del);
}
int Menu()
{
int c;
printf("\n*** M E N U ***\n"
"1 - New Node\n"
"2 - View List\n"
"3 - Delete\n"
"0 - Exit\n"
"\n>> ");
scanf(" %d", &c);
return c;
}
int main()
{
int c,n;
Node head = NULL;
do {
c = Menu();
switch (c)
{
case 1: ReadData(&head, &n); break;
case 2: ViewList(head); break;
case 3: Delete(&head); break;
default: c = 0;
}
} while (c != 0);
return 0;
}
How can i test if this is a real circular doubly linked list and not a simple doubly linked list?
Your program works fine, the only real bug I detected is in SearchNode: if the element is not present in the list, you enter an infinite loop. Your list is obviously a circular list and therefore you need to check if you have got back to the head in the function, which means that the element you're searching for is not in the list:
Corrected version:
Node SearchNode(Node head)
{
int d;
printf("\nElement to Delete:");
scanf("%d", &d);
Node start = head; // remember where we started
while (head != NULL)
{
if (head->n == d)
{
return head;
}
head = head->next;
if (head == start) // if we are back to where we started
break; // the element hasn't been found and we stop the loop
}
printf("\nNo Element [%d] Found", d);
return NULL;
}
There are also some design flaws, that don't prevent the program from working correctly:
One of them is this: The n variable is not used outside ReadData, so it's pointless to declare it in main and pass it's pointer to ReadData.
Corrected version:
void ReadData(Node * head)
{
int n; // declare n locally
printf("\nInsert a number:");
scanf("%d", &n);
NewNode(head, n);
}
Call it like this: ReadData(&head) and remove int n; from main.

Printing strings in linked lists

So I'm having trouble getting my program to print both the strings I input, or however many you want to put in the list, it always prints out the last string inputted multiple times. I am sorry about all the commented out code, most of it you don't need to read.
#include<stdio.h>
#include<stdlib.h>
struct node{
char *data;
struct node *next;
}*head;
typedef struct node NODE;
// Function prototypes
void append(char myStr[]);
void add( char myStr[] );
//void addafter(char myStr[], int loc);
void insert(char myStr[]);
int delete(char myStr[]);
void display(struct node *r);
int count();
// main function
int main()
{
int i;
struct node *n;
head = NULL;
char myStr[50];
while(1)
{
printf("\nList Operations\n");
printf("===============\n");
printf("1.Insert\n");
printf("2.Display\n");
printf("3.Size\n");
printf("4.Delete\n");
printf("5.Exit\n");
printf("Enter your choice : ");
if(scanf("%d", &i) <= 0)
{
printf("Enter only an Integer\n");
exit(0);
}
else
{
switch(i)
{
case 1:
printf("Enter the name to insert : ");
scanf("%50s", myStr);
insert(myStr);
break;
case 2:
if(head == NULL)
{
printf("List is Empty\n");
}
else
{
printf("Name(s) in the list are : ");
}
display(n);
break;
case 3:
printf("Size of the list is %d\n",count());
break;
case 4:
if(head == NULL)
printf("List is Empty\n");
else
{
printf("Enter the myStrber to delete : ");
scanf("%50s",myStr);
if(delete(myStr))
printf("%s deleted successfully\n",myStr);
else
printf("%s not found in the list\n",myStr);
}
break;
case 5:
return 0;
default:
printf("Invalid option\n");
}
}
}
return 0;
}
// Function definitions
void append(char myStr[])
{
struct node *temp,*right;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = myStr;
right=(struct node *)head;
while(right->next != NULL)
{
right = right->next;
}
right->next = temp;
right = temp;
right->next = NULL;
}
// adding a node to the beginning of the linked list
void add( char myStr[] )
{
struct node *temp;
temp =(struct node *)malloc(sizeof(struct node));
temp->data = myStr;
// only one node on the linked list
if (head == NULL)
{
head = temp;
head->next = NULL;
}
else
{
temp->next = head;
head = temp;
}
}
void insert(char myStr[])
{
int c = 0;
struct node *temp;
temp = head;
if(temp == NULL)
{
add(myStr);
}
else
{
append(myStr);
}
}
int delete(char myStr[])
{
struct node *temp, *prev;
temp = head;
while(temp != NULL)
{
if(temp->data == myStr)
{
if(temp == head)
{
head = temp->next;
head = (*temp).next;
free(temp);
return 1;
}
else
{
prev->next = temp->next;
free(temp);
return 1;
}
}
else
{
prev = temp;
temp = temp->next;
}
}
return 0;
}
void display(struct node *r)
{
r = head;
if(r == NULL)
{
return;
}
while(r != NULL)
{
printf("%s ", r->data);
r = r->next;
if(r == NULL)
{
printf("\nOur linked list is finished!");
}
}
printf("\n");
}
int count()
{
struct node *n;
int c = 0;
n = head;
while(n != NULL)
{
n = n->next;
c++;
}
return c;
}
The problem seems to be that myStr at main function is a char[], so it's content is overritten every time you insert data. Notice that struct node data field is a char*, it's just pointing to myStr address.
Hope this help!
Your program has only one place to write your input, myStr.
With each input, myStr is erased and a something else is written to myStr.
The data member of all of the nodes, points to myStr. myStr will only contain the last input.
The display() function asks each node what is data. data points to myStr so each node prints the contents of myStr. myStr will only contain the last input so all the nodes print the last input.
To fix this, in the add() and append() functions, you need to give the data member some memory by using malloc(). Then copy the contents of myStr to the data member by using strcpy().
temp->data = malloc ( strlen ( myStr) + 1);
strcpy ( temp->data, myStr);
Do this instead of temp->data = myStr;
You will need #include<string.h>
The memory will need to be free()'d in the delete() function.
free(temp->data);
Do this before freeing temp
char *data
that variable from struct is always assigned with the address of myStr as its a pointer it would only show you the value of myStr

Resources