I am a beginner to C and am learning linked lists. I tried making functions to have everything organised but no matter what i do the function print_list doesn't print the values. The output is only START and END. I noticed that if I put the same block of code directly into the function that builds the lists, then it prints correctly. What am I doing wrong? (Also first time asking on stack overflow)
Thank you to whoever answers.
#include <stdlib.h>
#include <stdio.h>
typedef struct nd
{
int val;
struct nd *next;
} node;
typedef node * Lista;
void print_list(node*currnode)
{
printf("START -> ");
while (currnode != NULL)
{
printf("%d -> ", currnode->val);
currnode = currnode->next;
}
printf("END");
}
//reimpilista means "buildlist"
node*riempilista(Lista lis){
node *currentNode, *temp;
int i,n;
printf("how many nodes?\n");
scanf("%d",&n);
for (i = 0; i < n; i++)
{
currentNode = (node *)malloc(sizeof(node));
printf("Enter element %d : ", (i + 1));
scanf("%d", ¤tNode->val);
if (i == 0)
{
temp = currentNode;
}
else
{
temp->next = currentNode;
temp = currentNode;
}
}
temp->next = NULL;
return lis;
}
int main(){
Lista listautente=NULL;
listautente=riempilista(listautente);
print_list(listautente);
return 0;
}
When you build the list you need to return the head of the list as a result. So you need to store the pointer to the first node. Then when adding a new node you need to know the previous node, so you need to store it as well. The last added node should have next field poiting to NULL otherwise you won't be able to determine the end of the list and will get an exception.
Here is your code slightly edited.
#include <stdlib.h>
#include <stdio.h>
typedef struct nd {
int val;
struct nd *next;
} node;
typedef node *Lista;
void print_list(node *currnode) {
printf("START -> ");
while (currnode != NULL) {
printf("%d -> ", currnode->val);
currnode = currnode->next;
}
printf("END");
}
//reimpilista means "buildlist"
node *riempilista() {
node *firstNode = NULL, *currentNode = NULL, *previousNode = NULL;
int i, n;
printf("how many nodes?\n");
scanf("%d", &n);
for (i = 0; i < n; ++i) {
currentNode = (node *)malloc(sizeof(node));
printf("Enter element %d : ", (i + 1));
scanf("%d", ¤tNode->val);
currentNode->next = NULL;
if (i == 0) {
firstNode = currentNode;
}
if (previousNode != NULL) {
previousNode->next = currentNode;
}
previousNode = currentNode;
}
return firstNode;
}
int main() {
Lista listautente = riempilista();
print_list(listautente);
return 0;
}
I tried to fix your program with minimal changes. Here it is:
Change
node *currentNode, *temp;
to
node *currentNode, *temp, *head;
Change
temp = currentNode;
to
temp = currentNode; head = temp;
Change
return lis;
to
return head;
Here is the link to the modified code:
https://onlinegdb.com/8cjqifgl2
Related
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;
}
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insert(struct node *link, int data) {
if (link == NULL) {
link = (struct node *)malloc(sizeof(struct node));
link->data = data;
link->next = NULL;
} else {
struct node *newlink = (struct node *)malloc(sizeof(struct node));
newlink->data = data;
newlink->next = link;
link = newlink;
}
return link;
}
void reverse(struct node *link) {
int i, j = 0;
int arr1[100], arr2[100];
struct node *current;
int count = 0;
current = link;
while (current != NULL) {
arr1[i] = current->data;
i = i + 1;
count = count + 1;
current = current->next;
}
printf("\n");
i = 0;
j = 0;
for (i = count - 1; i >= 0; i--) {
arr2[j] = arr1[i];
j = j + 1;
}
printf("The elements in the linked list are: ");
for (i = 0; i < count; i++) {
printf("%d ", arr1[i]);
}
printf("The elements in the reversed linked list are: ");
for (j = 0; j < count; i++) {
printf("%d ", arr2[j]);
}
}
void print(struct node *link) {
struct node *temp = link;
printf("The elements in the linked list are: ");
while (temp != NULL) {
printf("%d ", temp->data);
temp = temp->next;
}
}
void main() {
int value;
printf("Enter the value:\n");
scanf("%d", &value);
struct node *link = NULL;
link = insert(link, value);
char ans[3] = "yes";
while (ans[0] == 'y') {
printf("Do you want to add another node? Type Yes/No\n");
scanf("%s", ans);
if (ans[0] == 'y') {
printf("Enter the value:\n");
scanf("%d", &value);
link = insert(link, value);
} else {
reverse(link);
}
}
}
Here is the code I wrote to reverse a single linked list in C. I seem to try different combinations of the program but while doing it by array method, I am unable to get rid of the segmentation fault, and hence it doesn't give output.
There are some problems in your code:
i is uninitialized when used in the while loop in function reverse, causing undefined behavior which could explain the segmentation fault.
j is not modified in the loop at the end of the reverse function, causing an infinite loop:
for (j = 0; j < count; i++) {
printf("%d ", arr2[j]);
}
you are not reversing the list, you just print the list contents in reverse order, and assume its length is at most 100. This is probably not what you are expected to do.
in function main, the array ans should be made larger to accommodate at least the word yes, and you should prevent scanf() from storing more characters into it than would fit. Also reorganize the code to avoid duplication:
int main(void) {
struct node *link = NULL;
for (;;) {
char ans[80];
int value;
printf("Enter the value:\n");
if (scanf("%d", &value) != 1)
break;
link = insert(link, value);
printf("Do you want to add another node? Type Yes/No\n");
if (scanf("%79s", ans) != 1 || ans[0] != 'y') {
break;
}
}
reverse(link);
return 0;
}
Most of the above problems would have been spotted immediately by increasing the compiler warning level (for example gcc -Wall -Werror or clang -Weverything -Werror).
Here is a simpler version that reads numbers and allocates the list in the same order as you do, inserting each new element before the previous one, then reverses the list and finally prints it. As expected, the list is printed in the order of entry.
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *insert(struct node *head, int data) {
struct node *newlink = malloc(sizeof(*newlink));
newlink->data = data;
newlink->next = head;
return newlink;
}
struct node *reverse(struct node *link) {
struct node *prev = NULL;
while (link) {
struct node *temp = link->next;
link->next = prev;
prev = link;
link = temp;
}
return prev;
}
void print(struct node *link) {
printf("The elements in the linked list are: ");
for (struct node *n = link; n; n = n->next) {
printf("%d ", n->data);
}
printf("\n");
}
int main(void) {
struct node *link = NULL;
int value;
printf("Enter the values, end the list with 0:\n");
while (scanf("%d", &value) == 1 && value != 0) {
link = insert(link, value);
}
link = reverse(link);
print(link);
return 0;
}
What is wrong in this code. During the insertion operation, when inserting the second element, the programs halts and Windows shows that the program has stopped working. In the build log it shows Process terminated with status -1073741510and sometimes Process terminated with status 255. Even though there's a return statement in the main function.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
void insert(int);
void print();
struct node
{
int data;
struct node *link;
};
struct node *temp, *temp1, *temp2, *head, *end;
int main()
{
int i, ch, a;
head = NULL;
temp = (node*)malloc(sizeof(node));
printf("Enter the number of items");
scanf("%d", &ch);
for(i = 0; i < ch; i++)
{
printf("\nEnter the number");
scanf("%d", &a);
insert(a);
**call to insert**
print();
}
return 0;
}
void insert(int x)
{
temp = (node*)malloc(sizeof(struct node));
temp->data = x;
temp->link = NULL;
temp2 = head;
if(head == NULL)
{
head = temp;
}
else
{
while(temp2 != NULL)
{
temp2 = temp2->link;
}
temp2->link = temp;
}
}
void print()
{
temp1 = head;
printf("\nthe list is:");
while(temp1 != NULL)
{
printf("%d", temp1->data);
temp1 = temp1->link;
}
}
This part of the function
else
{
while(temp2 != NULL)
{
temp2 = temp2->link;
}
temp2->link = temp;
}
is wrong. After exit from the loop the node temp2 is equal to NULL. Thus this statement
temp2->link = temp;
results in undefined behavior.
Change the code snippet the following way
else
{
while(temp2->link != NULL)
{
temp2 = temp2->link;
}
temp2->link = temp;
}
Also this statement in main
temp = (node*)malloc(sizeof(node));
does not make sense and leads to a memory leak.
These declarations of global variables except of the variable head
struct node *temp, *temp1, *temp2, *head, *end;
also do not make sense.
I'm getting assignment makes pointer from integer without a cast errors on lines 46 and 53, the two lines with double asterisks on either side, and for the life of me, I cannot figure out why. Linked lists are very new to me, I don't know how they work completely yet.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct node_def
{
int data;
struct node_def *next;
};
typedef struct node_def node;
node *makeNode (int a);
node *insertFront(node *head,node *new);
void printList(node *head);
int numNodes = 0;
int main()
{
srand(time(0));
int r = rand() % 10000;
int i = 0;
node *head = NULL;
node *tmp = NULL;
printf("How many nodes? ", numNodes);
scanf("%d", numNodes);
printf("\n");
head = insertFront(head, tmp);
for(i = 0; i < numNodes; i++)
{
makeNode(r);
printList(head);
}
printf("\n");
return 0;
}
node *makeNode (int a)
{
node *new = malloc(sizeof(node));
**new = a;**
return new;
}
node *insertFront(node *head, node *new)
{
**new->data = head;**
new->next = new;
return 0;
}
void printList(node *head)
{
int j = 0;
for(j = 0; j < numNodes; ++j)
{
while (head != NULL)
{
printf(" %4d", head->data);
head = head->next;
}
if(j % 10 == 0)
printf("\n");
}
return;
}
new = a is meant to make new nodes and assign them a random number from 0 - 9999.
You try to assign r to new, but new is a struct.
You make a pointer to struct : node *new
What you want to do is assigning r to new->data, which is an int.
node *insertFront(node *head, node *new)
{
**new->data = head;** // ** is meaningless
new->next = new; // new is a reserved key word, don't use it this way
return 0;
}
What you try to do is to put a NULL pointer as the head of your list.
Just push element into it within your makeNode function.
insert like this :
void createNode(node *head)
{
Node *new_node = malloc(sizeof(Node*));
new_node->data = rand() % 100000;
new_node->next = NULL;
if(head == NULL)
head = new_node;
else if(head != NULL)
//Here you have to adapt your list, search (linked list crud functions)
}
You have a bad understanding about what pointers are.
Hope it helps bro
I am trying to write a program that creates and displays linked lists, and allows people to insert an element at the beginning, middle or end.
Insertion at the beginning or the middle works perfectly. However, my program fails when it comes to inserting at the end. Please have a look and tell me where I am going wrong or what needs modification. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node {
int number;
struct node *next;
};
typedef struct node NODE;
NODE *node1, *start, *rear, *m, *nodex, *temp1;
int main() {
int i, n1, n2;
start = NULL;
printf("Enter the number of inputs to the list:");
scanf("%d", &n1);
for (i = 0; i < n1; i++) {
// node creation begins here
node1 = (NODE*) malloc(sizeof(NODE));
int inf;
printf("Enter node value:");
scanf("%d", &inf);
node1->number = inf;
node1->next = NULL;
if (start == NULL) {
// first node creation
start = rear = node1;
} else {
m = start;
if (m->number > inf) {
// for insertion in beginning
node1->next = m;
start = node1;
} else {
while (m->next->number < inf) {
// searching to insert in middle of sorted list
m = m->next;
}
temp1 = m->next;
m->next = node1;
node1->next = temp1;
}
}
display(); // to display the linked list
}
return 0;
}
void display() {
nodex = start;
while (nodex != NULL) {
printf("%d ->", nodex->number);
nodex = nodex->next;
}
}
What happens at the end of the list?
while(m->next->number < inf){
//searching to insert in middle of sorted list
m=m->next;
}
This check fails when m->next is NULL. NULL->something fails. So do a check if it's a valid pointer, like:
while(m->next)
if(m->next->number < inf)
m=m->next;
else
break;