I have a function as following
void printLinkedList(struct node *head) {
printf("%d-->", head->data);
while(head->ptr != NULL) {
head = head->ptr;
printf("%d-->", head->data);
}
printf("NULL\n");
}
I would like to print the content of a linked list constructed in the following way:
for (int i = 0; i < 10; i++) {
head->data = i+1;
head->ptr = malloc(sizeof(struct node));
head = head->ptr;
}
So ideally this should give me something like:
1-->2-->3-->4-->...-->10-->NULL
If everything is correct, however, valgrind is giving me memory errors. Please tell me what I am doing wrong.
check this.
struct node *temp, *head= NULL, *last = NULL;
for (int i = 0; i < 10; i++) {
temp = malloc(sizeof(struct node));
temp->data = i+1;
temp->ptr = NULL;
if (head == NULL)
head = temp;
if (last != NULL)
last->ptr = temp;
last = temp;
}
printLinkedList(head);
I revised Toms's answer a little:
struct node *head = NULL, **temp = &head;
for (int i = 0; i < 10; i++) {
*temp = malloc(sizeof(struct node));
(*temp)->data = i+1;
(*temp)->ptr = NULL;
temp = &(*temp)->ptr;
}
printLinkedList(head);
The orignal code produces a seg fault because temp is not malloced properly.
If you call print function without constructing the Linked list, it will show error, so change the print function as follows:
void printLinkedList(struct node *head)
{
while(head != NULL)
{
printf("%d-->", head->data);
head = head->ptr;
}
printf("NULL\n");
}
here is the revised code - your construction was faulty.
typedef struct _node {
int data;
struct _node *ptr;
} NODE, *PNODE;
PNODE head;
int main (int argc, char * argv[])
{
head = (PNODE) malloc(sizeof(NODE));
PNODE node = head;
int i = 0;
node->data = ++i;
node->ptr = NULL;
for ( ;i < 10; ) {
PNODE tmp = (PNODE) malloc(sizeof(NODE));
tmp->data = ++i;
tmp->ptr = NULL;
node->ptr = tmp;
node =tmp;
}
printLinkedList(head);
freeLinkedList(head);
return 0;
}
Related
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node* next;
}
node;
int main(void){
node* list = NULL;
node *n = malloc(sizeof(node));
if(n==NULL){
return 1;
}
n->number = 2;
n-> next = NULL;
list = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list);
return 1;
}
n->number = 3;
n->next = NULL;
list->next = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list->next);
free(list);
}
n->number = 4;
n->next = NULL;
list->next->next =n;
n = malloc(sizeof(node));
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
for( node* tmp = list; tmp != NULL; tmp->next){
printf("%i\n" , tmp->number);
}
while(list!=NULL){
node*tmp = list->next;
free(list);
list=tmp;
}
}
was trying linked list.
expected when running the code:
0
1
2
3
4
$
//asdoihasidashiofdhiohdfgdiwheifiopioioiophfaifjasklfhafiashfauiosfhwuiohwefuiowhfaslfidasdaskdasjdlaksdjqwfiqpweiojfkldfjsdfklwhefiowefweopfiosfkosid;fjwdfp;fdasiopfjew[0fowejfwepfojmofejmiwrfgj;wdfjewio;fijwefjsdp;jfkl;wjw
Actually you are not changing the pointer
for( node* tmp = list; tmp != NULL; tmp->next){
You need to write
for( node* tmp = list; tmp != NULL; tmp = tmp->next){
It will be even better to write
for ( const node* tmp = list; tmp != NULL; tmp = tmp->next ){
because within the loop the list is not being changed.
Also in this code snippet
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
the statement
n->next = NULL;
is redundant.
In this loop, tmp->next has no effect because you don't assign it to anything.
for (node* tmp = list; tmp != NULL; tmp->next) {
printf("%i\n", tmp->number);
}
You must do tmp = tmp->next:
for (node* tmp = list; tmp != NULL; tmp = tmp->next) {
// ^^^^^
printf("%i\n", tmp->number);
}
Also, you can't expect 1 to be in the output because you never create a node with that number. With the above change the program will therefore output:
0
2
3
4
Sidenote: Your program is full of repetition which makes it hard to find errors and it's also what makes it harder to see that you forgot to add the node with the number 1. If you instead make functions of the things that you do repeatedly it'll be much clearer. You can also make functions with descriptive names to make the whole program easier to read and maintain.
If your program was rewritten to make use of functions, it could look like below - and then it'll be very obvious that the node with the number 1 is missing.
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
struct node {
int number;
node* next;
};
node *create_node(int number, node *next) {
node *nn = malloc(sizeof *nn);
if(!nn) exit(1);
// assign values to the new node:
*nn = (node){.number = number,
.next = next};
return nn;
}
void insert_first(node **list, int number) {
*list = create_node(number, *list);
}
void insert_last(node **list, int number) {
// find the last "next" pointer (the one pointing at NULL):
while(*list) list = &(*list)->next;
// make the pointer pointing at NULL now point at the new node:
*list = create_node(number, NULL);
}
void free_all(node **list) {
for(node *tmp; *list; *list = tmp) {
tmp = (*list)->next;
free(*list);
}
}
void print_all(const node *list) {
for (; list; list = list->next) {
printf("%d\n", list->number);
}
}
int main(void) {
node* list = NULL;
insert_last(&list, 2);
insert_last(&list, 3);
insert_last(&list, 4);
insert_first(&list, 0);
print_all(list);
free_all(&list); // list == NULL after this
}
was trying to scan numbers from a file and store them as linked list, however the temporary pointer (ptr) used to link nodes runs through a while loop each time a value is scanned and stored. Is there a way to simplify this without using a while loop? My approach doesn't seem to work.
original code:
struct node
{
int data;
struct node *link;
} *head = NULL, *ptr = NULL, *temp = NULL;
int main()
{
-----
-----
for (i = 0; i < n ; ++i)
{
temp = malloc(sizeof(struct node));
fscanf(fptr, "%d", &(temp->data));
temp->link = NULL;
if (head == NULL)
head = temp;
else
{
ptr = head;
while (ptr->link != NULL)
ptr = ptr->link;
ptr->link = temp;
}
}
-----
}
my approach:
struct node
{
int data;
struct node *link;
} *head = NULL, *ptr = NULL, *temp = NULL;
int main()
{
-----
-----
for (i = 0; i < n ; ++i)
{
temp = malloc(sizeof(struct node));
fscanf(fptr, "%d", &(temp->data));
temp->link = NULL;
if (head == NULL)
{
head = temp;
ptr = head;
}
else
{
ptr->link = temp;
ptr->link = ptr->link->link;
}
}
-----
}
In this code snippet
else
{
ptr->link = temp;
ptr->link = ptr->link->link;
}
ptr->link is set to NULL because in fact it is set to temp->link that is equal to NULL due to this assignment
temp->link = NULL;
What you need is to write
else
{
ptr->link = temp;
ptr = temp;
}
Actually you are trying to implement a two-sided sinngly-linked list where the pointer ptr plays the role of the tail pointer..
I'm trying to make a circular linked list. When I try to display the list after creating it, the program keeps on crashing. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node * next;
} node;
node * createList(int);
void display(node * head);
int main() {
struct node * head;
head = createList(5);
display(head);
}
node * createList(int n) {
int i = 0,data = 0;
struct node * head = NULL;
struct node * temp = NULL;
struct node * p = NULL;
for (i = 0; i < n; i++) {
temp = (node*)malloc(sizeof(node));
temp->data = data++;
temp->next = head;
if (head == NULL) {
head = temp;
} else {
p = head;
while (p->next != NULL) {
p = p->next;
}
p->next = temp;
}
}
return head;
}
void display(node * head) {
struct node * temp = head->next;
while (temp != head) {
printf("%d-> \t",temp->data);
temp = temp->next;
}
printf("\n");
}
What am I doing wrong?
You have set every temp's next to head in temp->next = head; but did it too early (the first is just NULL). Then you tested p->next against NULL in while (p->next != NULL) { but you should have tested against head. Alternatively, you can continue to test against NULL but then you need to initialize temp->next to NULL and assign head to temp->next only after the for loop.
Your display code started from the second link.
Here is a fixed code using the first option in 1. above:
for (i = 0; i < n; i++) {
temp = (node*)malloc(sizeof(node));
temp->data = data++;
if (head == NULL) {
head = temp;
} else {
p = head;
while (p->next != head) {
p = p->next;
}
p->next = temp;
}
temp->next = head;
}
Here is a fixed code using the alternative option in 1. above. You still need to initialize temp->next to NULL since malloc() does not initialize.
for (i = 0; i < n; i++) {
temp = (node*)malloc(sizeof(node));
temp->data = data++;
temp->next = NULL;
if (head == NULL) {
head = temp;
} else {
p = head;
while (p->next != NULL) {
p = p->next;
}
p->next = temp;
}
}
if (temp != NULL) {
temp->next = head;
}
But in reality, there is no need to "walk" from the head on every creation. You can simply keep the previous and link it to the next:
for (i = 0; i < n; i++) {
temp = (node*)malloc(sizeof(node));
temp->data = data++;
if (head == NULL) {
head = p = temp;
} else {
p = p->next = temp;
}
}
if (temp != NULL) {
temp->next = head;
}
Here is a fix for the display():
void display(node * head) {
struct node * temp = head;
if (temp != NULL) {
do {
printf("%d-> \t",temp->data);
temp = temp->next;
} while (temp != head);
}
printf("\n");
}
The problem is on the first node you initialize:
struct node *head = NULL;
...
for (i = 0; i < n; i++) {
...
temp->next = head;
So tmp->next == NULL on the first iteration leaving head->next == NULL. That will not work for a circular list. When you attempt to insert the 2nd node:
p = head;
while (p->next != NULL) {
What was head->next again?? (oh, NULL) Dereferencing a NULL pointer (BOOM Segfault!)
Do your circular list correctly. On insertion of the first node set:
if (head == NULL) {
head = temp;
head->next = temp; /* you must set head->next to temp */
} ...
So on the insertion of the remaining nodes you simply need:
} else {
p = head;
while (p->next != head) { /* iterate to last node */
p = p->next;
}
p->next = temp; /* now set p->next = temp */
}
Now, you handle your display() function the same way, e.g.
void display (node *head)
{
if (!head) { /* validate list not empty */
puts ("(list-empty)");
return;
}
struct node *temp = head;
do { /* same loop problem fixed in display() */
printf ("%d-> \t", temp->data);
temp = temp->next;
} while (temp != head);
putchar ('\n');
}
If you make the changes, then you can test your list with:
int main (void) {
struct node *head, *tmp;
head = createList(5);
display (head);
puts ("\niterate from mid-list");
tmp = head;
tmp = tmp->next;
tmp = tmp->next;
display (tmp);
}
Example Use/Output
$ ./bin/lls_circular_fix
0-> 1-> 2-> 3-> 4->
iterate from mid-list
2-> 3-> 4-> 0-> 1->
Lastly, you are not multiplying the type node by head in struct node * head = NULL; Write it as struct node *head = NULL; (the same for all your function declarations as well) Much more readable.
When you go to delete a note from the list, you must create a special case for both head and tail (the last node). In this sense, the singly-linked list takes a bit more effort than a doubly-linked list due to not having a prev node pointer to track the prior node.
Look things over and let me know if you have questions.
A full example would be:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
node *createList (int);
void display (node *head);
int main (void) {
struct node *head, *tmp;
head = createList(5);
display (head);
puts ("\niterate from mid-list");
tmp = head;
tmp = tmp->next;
tmp = tmp->next;
display (tmp);
}
node *createList (int n)
{
int i = 0,data = 0;
struct node *head = NULL;
struct node *temp = NULL;
struct node *p = NULL;
for (i = 0; i < n; i++) {
if (!(temp = malloc (sizeof *temp))) {
perror ("malloc-temp");
return NULL;
}
temp->data = data++;
temp->next = head; /* head is NULL on 1st node insertion */
if (head == NULL) {
head = temp;
head->next = temp; /* you must set head->next to temp */
} else {
p = head;
while (p->next != head) { /* iterate to last node */
p = p->next;
}
p->next = temp; /* now set p->next = temp */
}
}
return head;
}
void display (node *head)
{
if (!head) { /* validate list not empty */
puts ("(list-empty)");
return;
}
struct node *temp = head;
do { /* same loop problem fixed in display() */
printf ("%d-> \t", temp->data);
temp = temp->next;
} while (temp != head);
putchar ('\n');
}
For some reason, if I have a linked list that looks like 3->2->1->0, and I called deleteSecond(head), I get 3->1->0->0. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int data;
struct ListNode *next;
} *LinkedList;
int deleteSecond(LinkedList list) {
if (list == NULL || list->next == NULL)
return 0;
int val = list->next->data;
LinkedList second = list->next;
list->next = list->next->next;
free(second);
return val;
}
int main() {
LinkedList head = NULL;
head = malloc(sizeof(LinkedList));
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(LinkedList));
newNode->data = i;
newNode->next = head;
head = newNode;
}
LinkedList ptr = head;
for (int i = 0; i < 4; i++) {
printf("%d\n", ptr->data);
ptr = ptr->next;
}
printf("\n");
deleteSecond(head);
while (head != NULL) {
printf("%d\n", head->data);
head = head->next;
}
return 0;
}
I believe my deleteSecond function should be correct. I create a pointer to my second node, and then I make the head->next = head->next->next, and the I free the pointer to the second node. I don't know why I have two 0's at the end of the list.
You are creating an empty node head which is creating problem. Your last node should point to NULL. So initializing head = NULL is the correct one.
LinkedList head = NULL;
// head = malloc(sizeof(LinkedList));
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(LinkedList));
newNode->data = i;
newNode->next = head;
head = newNode;
}
head = malloc(sizeof(LinkedList));
This is wrong. Correct would be
head = malloc(sizeof(*head));
Then again same way it would be
LinkedList newNode = malloc(sizeof(*newNode));
Now let's see what you did here.
head's data or link attribute is never initialized. So you get undefined behavior accessing it.
This is the code you wanted to write if you want to allocate memory to head.
...
int main(void) {
LinkedList head = NULL;
head = malloc(sizeof(*head));
if( head == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
head->next = NULL;
head->data = 2017; // dummy data.
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(*newNode));
if( newNode == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
newNode->data = i;
newNode->next = head;
head = newNode;
}
...
...
deleteSecond(head);
while (head != NULL) {
printf("%d\n", head->data); // prints 2017 also. But deletes the node that was in second position.
head = head->next;
}
return 0;
}
Here we have used one extra node for holding the dummy data. Yes! it's not needed. This dummy node is doing nothing significant other than providing an next link for the newNodes which is not needed if you just use head as LinkedList or struct LinkedNode* and allocates no memory to it. It suggests we can eliminate than and simply use the pointer to struct ListNode namely head.
Then the code will be simply like
LinkedList head = NULL;
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(*newNode));
if( newNode == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
newNode->data = i;
newNode->next = head;
head = newNode;
}
There are couple of things you can consider
Don't hide pointers under typedef.
Do check the return value of malloc.
Do free the memory that you allocate after you are done working with it.
The code can be written this way also. It doesn't use the pointer under typedef and modularize the reusable codes.
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int data;
struct ListNode *next;
} ListNode;
void freeMemList(ListNode *head){
ListNode *temp;
while(head!=NULL){
temp = head;
head = head->next;
free(temp);
}
}
int deleteSecond(ListNode * list) {
if (list == NULL || list->next == NULL)
return 0;
int val = list->next->data;
ListNode * second = list->next;
list->next = list->next->next;
free(second);
return val;
}
void printList(ListNode *head){
while (head != NULL) {
printf("%d\n", head->data);
head = head->next;
}
}
struct ListNode * addNodes(struct ListNode* head, int n){
for (size_t i = 0; i < n; i++) {
ListNode * newNode = malloc(sizeof(*newNode));
if( newNode == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
newNode->data = i;
newNode->next = head;
head = newNode;
}
return head;
}
int main(void) {
ListNode * head = NULL;
head = addNodes(head,4);
printList(head);
printf("********\n");
int valDeleted = deleteSecond(head);
printf("%s %d\n","Value deleted ", valDeleted );
printList(head);
freeMemList(head);
return 0;
}
I'm very new to programming and I started to learn C. Now I just cant understand why my node structure is not visible to my functions.
I try to get some help on http://www.cprogramming.com/tutorial/c/lesson7.html
but with no luck in using code blocks 13.12
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct ptr * next;
};
struct node* head;
void Insert(int x)
{
struct node *temp;
temp = (node*)malloc(sizeof(struct node));
if(head == NULL)
head = temp;
temp->data = x;
temp->data = x;
temp->next = NULL;
struct node* temp1 = head;
while(temp1-> != NULL;) {
temp1 = temp1->next;
}
temp1->next = temp;
}
void print() {
struct node* temp = head;
while(temp != NULL) {
printf("the data is %d", temp->data);
temp = temp->next;
}
}
int main ()
{
head = NULL;
int a,c;
printf("How many numbers ? : \n");
scanf("%d",&a);
for(i = 0; i<a; i++); {
printf("Enter a number:\n");
scanf("%d",&c);
Insert(c);
print();
}
}
There are quite a few lets go one by one
number 1
struct node {
int data;
struct node *next; // chagnge ptr -> node
};
number 2
struct node *temp;
temp = malloc(sizeof(struct node)); // struct node casting
number 3
while(temp1->next != NULL) { // remove semi colum and put a next
temp1 = temp1->next;
}
number 4
int i; // for while loop
for(i = 0; i<a; i++) {
Now hopefully it compiles well, check runtime errors ( if any )
and yes
return 0; // just before main
you are building an infinite loop with your first element:
temp = (struct node*)malloc(sizeof(struct node));
if(head == NULL)
head = temp;
temp->data = x;
temp->next = NULL;
struct node* temp1 = head;
while(temp1->next != NULL) { // nothing to do
temp1 = temp1->next;
}
temp1->next = temp; //temp is head and temp1 is head, so head->next points to head
you should do something like
if (head == NULL) {
//fill head and leave
} else {
//traverse to the last element and concatenate the new element
}