Below I have made a simple Linked List in C. The code is currently producing a segmentation fault which I find odd because I was copying an example from our current book. The only thing I did to the code was put the code into the method "addToList". I'm aware the segmentation fault is coming from the method addToList but I do not know where I made a mistake.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int val;
struct node *next;
} Node;
void addToList(Node *, int);
void printList(Node *);
void main() {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
printf("Enter an integer: ");
x = scanf("%d");
addToList(head, x);
}
printList(head);
}
void addToList(Node *head, int val) {
Node *current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof(Node));
current->next->val = val;
current->next->next = NULL;
}
void printList(Node *head) {
Node *current = head;
while (current != NULL) {
printf("%d->", current->val);
current = current->next;
}
printf("\n");
}
Any help with telling me what is wrong or where I'm making the mistake would be greatly appreciated.
Look carefully at your code:
int main(void) {
int x;
Node *head = malloc(sizeof(Node));
for (x = 1; x < 4); x++) {
...
addToList(head, x);
}
...
}
You are not initializing the memory, so head->val and head->next are not
initialized. Because of that
while (current->next != NULL) {
current = current->next;
}
will loop an undefined amount of times. The first current->next is most
probably not NULL, so current = current->next get executed. At that point current is pointing to nowhere, hence the undefined behaviour which in your case leads to a segfault.
You have to initialized the memory like this:
Node *head = malloc(sizeof *head);
if(head == NULL)
// error handling
head->next = NULL;
But you could also use calloc, which also sets the memory to 0, thus you don't have to initialize the values (in this case):
Node *head = calloc(1, sizeof *head);
if(head == NULL)
// error handling
You should always check for the return value of malloc/calloc/realloc.
Also note that the signature of the main function can be one of these:
int main(void);
int main(int argc, char **argv);
int main(int argc, char *argv[]);
edit
Another error I've noticed right now:
x = scanf("%d");
That's not how scanf works. You have to pass a pointer, scanf saves the
scanned value through the passed pointer. scanf returns the number of matched
values on success, in this case, success would be 1:
int num;
int ret = scanf("%d", &num);
if(ret != 1)
{
fprintf(stderr, "Could not read value from the user\n");
continue; // to contiune looping
// you could also do a break; and stop the looping, or
// exit(1), etc.
}
// error with scanf
Also don't use the same variable x for the loop iteration and user input,
otherwise you are messing with the loop.
edit
User user3629249 wrote in the comment
good information, however the result will be the first entry in the linked list will contain garbage.
Better to declare head via: Node *head = NULL; and the function addToList() check for NULL and proceed accordingly.
That's right, the head element doesn't save any number in this way.
Option 1: double pointer
Here addToList receives a double pointer. The initialization of head occurs
when *head points to NULL. The function allocates memory for it, initializes
the memory, saves the value and returns. In the concurrent calls of addToList
*head won't be NULL, so addToList looks for the end of the list.
I've made small changes in the way you do malloc and realloc. Also I added
an implementation of freeList which should be used to free the memory:
void addToList(Node **head, int val) {
if(head == NULL)
{
fprintf(stderr, "head cannot be NULL\n");
return;
}
if(*head == NULL)
{
*head = calloc(1, sizeof **head);
head[0]->val = val;
head[0]->next = NULL;
return;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return;
current->next->val = val;
current->next->next = NULL;
}
int main(void)
{
int x;
Node *head = NULL;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
addToList(&head, val);
}
printList(head);
freeList(head);
return 0;
}
void freeList(Node *head)
{
if(head == NULL)
return;
Node *current = head;
Node *next;
while(next = current->next)
{
free(current);
current = next;
}
free(current); // the last one
free(head);
}
Option 2: addToList returns a pointer to the head
Here addToList takes a pointer to the head. If it's NULL, it allocates
memory and initializes like in the shown above. If head is not NULL, the
functions looks for the last element and the returns the head. On error the
function returns NULL.
Node *addToList(Node *head, int val) {
if(head == NULL)
{
head = calloc(1, sizeof **head);
head->val = val;
head->next = NULL;
return head;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = malloc(sizeof *current->next);
if(current->next == NULL)
return NULL;
current->next->val = val;
current->next->next = NULL;
return head;
}
int main(void)
{
int x;
Node *head = NULL, *tmp;
for (x = 1; x < 4; x++)
{
int val;
printf("Enter an integer: ");
if(scanf("%d", &val) != 1)
{
fprintf(stderr, "Could not read from user. Skipping entry\n");
continue;
}
tmp = addToList(head, val);
if(tmp == NULL)
{
fprintf(stderr, "Not enough memory\n");
freeList(head);
return 1;
}
head = tmp;
}
printList(head);
freeList(head);
return 0;
}
Related
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.
I am new to C and try to learn how to implement C on linked list. I am really confused why I can't access myList in the main function? because when I try to myList->data, it's segmentation fault. I think there's some error in my addtohead function?
Below is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct NODE{
int data;
struct NODE *next;
}node;
node * myList;
node * addToHead(node*, int);
void printList();
int main(){
myList = NULL;
int input;
while (scanf("%i",&input) == 1){
addToHead(myList, input);
printf("%d \n", myList->data);
}
printf("My List:\n");
printList(myList);
return 0;
}
node* addToHead(node* head, int newData){
node *temp = (node *)malloc(sizeof(node));
temp -> data = newData;
temp -> next = NULL;
if(head != NULL){
temp -> next = head;
}
head = temp;
return head;
}
void printList(node* head){
node *temp = head;
while(temp != NULL){
printf("%d ", temp->data);
temp = temp -> next;
}
printf("\n");
}
Your addToHead function is supposed to return the mallocated memory back to caller.
So you should assign the return value to mylist at first:
int main(){
node *myList = NULL;
int input;
while (scanf("%i",&input) == 1){
myList = addToHead(myList, input);
printf("%d \n", myList->data);
}
printf("My List:\n");
printList(myList);
return 0;
}
Into your addToHead function you wrote
head = temp;
But head has local scope and the assigned value is not reflected to the pointer myList.
To do so you have to use pointer to pointer.
int main(){
node *myList = NULL;
int input;
while (scanf("%i",&input) == 1)
{
if (addToHead(&myList, input) == true)
{
printf("%d \n", myList->data);
}
else
{
fprintf(stderr, "Error addToHead\n");
}
}
return 0;
}
bool addToHead(node** head, int newData){
node *temp = malloc(sizeof(node));
if (temp != NULL)
{
temp -> data = newData;
temp -> next = NULL;
if(head != NULL)
{
temp -> next = *head;
}
*head = temp;
return true;
}
return false;
}
Finally always remember to check the malloc return value: it can fail.
You return the new head node from addToHead, but you don't do anything with it. You need to assign this value to myList to update it:
myList = addToHead(myList, input);
Also, you misspelled a variable on the following line:
printf("%d \n", myListd->data);
It should be:
printf("%d \n", myList->data);
In this function definition
node* addToHead(node* head, int newData){
node *temp = (node *)malloc(sizeof(node));
temp -> data = newData;
temp -> next = NULL;
if(head != NULL){
temp -> next = head;
}
head = temp;
return head;
}
The parameter node* head is a local variable of the function. Any changes of the parameter will not influence on the original argument. The function parameters will be destroyed after exiting the function.
You can consider the function definition and its call the following way
addToHead(myList, input);
//...
node* addToHead(/*node* head, int newData*/){
node *head = myList;
int newData = input;
node *temp = (node *)malloc(sizeof(node));
temp -> data = newData;
temp -> next = NULL;
if(head != NULL){
temp -> next = head;
}
head = temp;
return head;
}
So the original variable myList will not be changed after the function call. You have to assign explicitly the returned value to the variable
myList = addToHead(myList, input);
Also the function has a drawback. It does not report an error in case when the new node was not allocated.
A better approach to write the function looks the following way
int /* _Bool */ addToHead( node **head, int newData )
{
node *temp = ( node * )malloc( sizeof( node ) );
int /* _Bool */ success = temp != NULL;
if ( success )
{
temp -> data = newData;
temp -> next = *head;
*head = temp;
}
return success;
}
In this case the function can be called in a loop the following way
while ( scanf( "%i", &input ) == 1 && addToHead( &myList, input ) )
{
//...
}
I keep getting this Segmentation Fault: 11 error and I don't know why.
My Code:
typedef struct Node* NodePtr;
struct Node
{
NodePtr next;
void *val;
};
struct List
{
NodePtr head;
};
typedef struct List* ListPtr;
int compare(void *one, void *two)
{
if(*(int*)one < *(int*)two)
return -1;
else if(*(int*)one > *(int*)two)
return 1;
return 0;
}
ListPtr create()
{
ListPtr blah = malloc(sizeof(struct List));
memset(blah, 0, sizeof(struct List));
return blah;
}
NodePtr scan(NodePtr head, void *obj)
{
NodePtr previous, current;
previous = head;
current = head->next; // Segmentation fault here!!
while(current != NULL && (compare(curry->val, obj) == -1))
{
previous = current;
current = current->next;
}
return previous;
}
int insert(ListPtr llist, void *obj)
{
NodePtr newobj = malloc(sizeof(struct Node));
NodePtr prevNode, nextNode;
prevNode = search(llist->head, obj);
nextNode = prevNode->next;
if((nextNode == NULL) || (compare(nextNode->val, obj) != 0))
{
prevNode->next = newobj;
newobj->next = nextNode;
return 1;
}
else
{
free(newobj);
}
return 0;
}
I thought head was not allocated, so I added malloc in create for blah->head, but still no luck.
I think the error is here after some debugging: current = head->next.
Any help would be appreciated! Thank you for your time!
EDIT: How I call insert:
int main(int argc, char *argv[])
{
ListPtr list = create();
int x = 2;
int *p = &x;
while(*p != 0)
{
printf("\nEnter a number: ");
scanf("%d", p);
if(*p != 0)
insert(list, p);
}
return 0;
}
You don’t appear to check whether the list is empty when you scan it. However, without a Minimum Complete Verifiable Example that tells us how you called the function, it is impossible to tell for sure what you did.
Update
Now that you have, that seems to be it. You create an empty list and search it inside your insert function. The search function dereferences the zeroed-out pointer in head, causing a segfault.
Try the following: first, check that your pointer is valid in each of your functions before you do anything with it. An empty list should fail every search. Second, for maximum portability, you want to set your head pointer to NULL (since a NULL pointer is not necessarily all-bits-zero on all implementations).
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef struct _listnode
{
int item;
struct _listnode *next;
} ListNode;
int search(ListNode *head, int value);
void printList(ListNode *head);
int main()
{
ListNode *head = NULL, *temp = NULL;
int i = 0;
int value = 0;
while (1)
{
printf("Enter a integer: ");
scanf("%d", &i);
if (i == -1)
break;
if (head == NULL)
{
head = malloc(sizeof(ListNode));
temp = head;
}
else
{
temp->next = malloc(sizeof(ListNode));
temp = temp->next;
}
temp->item = i;
}
printList(head);
printf("Enter the value to search for: ");
scanf("%d", &value);
printf("Value of %d found in index %d",value,search(&head, value));
return 0;
}
void printList(ListNode *head)
{
while (head != NULL)
{
printf("%d ", head->item);
head = head->next;
}
printf("\n");
}
int search(ListNode *head, int value)
{
if (head == NULL)
return NULL;
if (head->item != value)
{
head = head->next;
}
return value;
}
I am trying to search a value inside a LinkedList and print out the index of the node when the value is found. But after my printlist, my program just shut down, I did not even reach to the part that require me to enter the value I want to search. Is there something wrong with my printList?
First of all, you should check the return value of scanf() - it returns the number of items successfully matched and assigned. Only after checking the return value can you be sure that the values you use are valid.
The problem, however, is that you never terminate the list properly, that is, you never set the last node's next to NULL. Try to add this after the while:
temp->next = NULL;
Personally, though, I'd advice against doing so. In general, it is more elegant if the list itself is in a consistent state after each iteration of the loop. So, this is what I suggest instead:
while (1)
{
printf("Enter a integer: ");
if (scanf("%d", &i) != 1) {
/* Deal with invalid input... */
}
if (i == -1)
break;
ListNode *new_node;
if ((new_node = malloc(sizeof(*new_node))) == NULL) {
/* Deal with memory exhaustion */
}
new_node->item = i;
new_node->next = NULL;
if (head == NULL)
head = new_node;
else
temp->next = new_node;
temp = new_node;
}
That makes temp work as a pointer to the previous node, so you might want to rename it to prev. Note the check for the return value of scanf() and malloc(), as well as the operand to sizeof: it is a good idea not to hardcode the type when using sizeof for maintenance reasons. Finally, notice, if you will, that there is now a single call to malloc(). This is conceptually easier to understand, since a new node is allocated in the same place in the code, regardless of head being valid or not.
Also, your search() function is broken. It assumes that if value is not the first node's value, then it is the second - not what you want. Also, you are not returning the index of the node, instead, you are returning the value itself. In fact, there's a situation where you return NULL (?!). I doubt that this compiles without warnings.
You need something like this instead:
int search(ListNode *head, int value)
{
int res = 0;
for (; head != NULL && head->item != value; head = head->next, res++)
; /* Intentionally left blank */
if (head == NULL)
return -1;
else
return res;
}
You don't put temp->next to NULL after this line temp = temp->next; in the list creation so it can be NULL or at any other value. When you iterate the list in printList() you reach this random value pointer and you have a segfault.
When i am printing linked list , i get runtime error
#include stdio.h
#include stddef.h
typedef struct
{
int info;
struct DEMO1 *next;
} DEMO1;
void insertatlast(DEMO1 * p, int o);
void printl(DEMO1 * p);
int main()
{
int temp;
DEMO1 *head = NULL;
if (head == NULL)
while (1)
{
printf("ENTER 0 to exit");
scanf("%d", &temp);
if (temp == 0)
break;
insertatlast(head, temp);
}
printl(head);
return 0;
}
void insertatlast(DEMO1 * head, int data)
{
if (head == NULL)
{
DEMO1 *node = (DEMO1 *) (malloc(sizeof(DEMO1)));
node->info = data;
node->next = 0;
head = node;
}
else
{
DEMO1 *temp;
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
DEMO1 *node = (DEMO1 *) (malloc(sizeof(DEMO1)));
node->info = data;
node->next = 0;
temp->next = node;
}
}
void printl(DEMO1 * head)
{
DEMO1 *temp;
temp = head;
printf("%d", temp->info);
while (temp != NULL)
{
printf(":) %d\n", temp->info);
temp = temp->next;
}
}
When head is NULL, head is changed within the insertatlast() function only and not in main(). return head to update head in main() also.
DEMO1* insertatlast(DEMO1 * head, int data)
{
if (head == NULL)
{
DEMO1 *node = (DEMO1 *) (malloc(sizeof(DEMO1)));
node->info = data;
node->next = 0;
head = node;
}
else
{
DEMO1 *temp;
temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
DEMO1 *node = (DEMO1 *) (malloc(sizeof(DEMO1)));
node->info = data;
node->next = 0;
temp->next = node;
}
return head;
}
int main()
{
int temp;
DEMO1 *head = NULL;
if (head == NULL)
while (1)
{
printf("ENTER 0 to exit");
scanf("%d", &temp);
if (temp == 0)
break;
head=insertatlast(head, temp);
}
printl(head);
return 0;
}
When you compile it (after fixing the missing <> in #includes, you can read some warning from your compiler — hopefully you have warnings enabled. Even if they doesn't solve your problem, it is a good habit to take a look at them.
Lines like
DEMO1 *head = NULL;
if (head == NULL)
should suggest you you are doing something wrong. The fact the if-body is executed, tell you alone that head is NULL when you call insertatlast. That's fine, you expect it. What you likely do not expect is that your head is not modified by the call to insertatlast: so when you call printl, head is NULL still, and calling
`printl(NULL);`
is problematic, because of
temp = head;
... temp->info ...
I guess someone told you that if you want to modify a value of a variable in the caller, you have to pass a pointer to that variable, and that since you have already a pointer, you get confused.
The fact is, a pointer is a variable too, and if you need to modify it, you must get the pointer to... a pointer.
DEMO1* head = NULL;
//...
insertatlast(&head, temp);
and your prototype for the insert would be
void insertatlast(DEMO1 **head, int data);
Then, you modify the caller variable (the DEMO1*), access it and so on, by using *head (don't forget that in insertatlast head has type DEMO1**, and so *head has type DEMO1*).
Note
Do not cast malloc return value; in C
DEMO1* node = malloc(sizeof (DEMO1));
suffices.