I am trying to print the length of a linked list I created in another .c file called linklist.c from the main.c file. It is not working and I believe is has something to do with pointers and/or memory management over all. I call into question the heap mainly here. some guidance would be appreciated.
#include <stdio.h>
#include <stdlib.h>
#include "node.h"
int main()
{
printf("Hello world!\n");
struct node* mylist = BuildOneTwoThree();
int length = Length(mylist);
printf(mylist->data);
printf(length);
return 0;
}
#include "node.h"
#include <stdio.h>
#include <stdlib.h>
// Return the number of nodes in a list (while-loop version)
int Length(struct node** head) {
int count = 0;
struct node* current = head;
while (current != NULL) {
count++;
current = current->next;
}
return(count);
}
/*
Build the list {1, 2, 3} in the heap and store
its head pointer in a local stack variable.
Returns the head pointer to the caller.
*/
struct node* BuildOneTwoThree() {
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = malloc(sizeof(struct node)); // allocate 3 nodes in the heap
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 1; // setup first node
head->next = second; // note: pointer assignment rule
second->data = 2; // setup second node
second->next = third;
third->data = 3; // setup third link
third->next = NULL;
// At this point, the linked list referenced by "head"
// matches the list in the drawing.
return head;
}
/*
Takes a list and a data value.
Creates a new link with the given data and pushes
it onto the front of the list.
The list is not passed in by its head pointer.
Instead the list is passed in as a "reference" pointer
to the head pointer -- this allows us
to modify the caller's memory.
*/
void Push(struct node** headRef, int data) {
struct node* newNode = malloc(sizeof(struct node));
newNode->data = data;
newNode->next = *headRef; // The '*' to dereferences back to the real head
*headRef = newNode; // ditto head points to new node
}
// Given a list and an index, return the data
// in the nth node of the list. The nodes are numbered from 0.
// Assert fails if the index is invalid (outside 0..lengh-1).
int GetNth(struct node* head, int index) {
struct node* current = head;
int answer = 0;
int x = index;
if(x <= 0 || x >= sizeof(head)-1 )
{
return -1;
}
for(int i = 0; i <= sizeof(head)-1; i++){
if (i == x){
return current->data;
}
current = current->next;
}
}
As you can see I use the BuildOneTwoThree function to build the linkedlist and am writing appropriate functions...It crashes when I try to access mylist into output.
For the most part the code seems to function from the point of view of the question only, printf had to be properly formatted.
printf("%i", length);
type cast malloc required
Change **head to *head in function argument Length
Use proper printf statement.
This question is limited to printing lenght of link list. please find code below:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
struct node* BuildOneTwoThree();
int Length(struct node* head);
int main()
{
printf("Hello world!\n");
struct node* mylist = BuildOneTwoThree();
int length = Length(mylist);
printf("data =%d\n",mylist->data);
printf("length = %d",length);
return 0;
}
// Return the number of nodes in a list (while-loop version)
int Length(struct node* head) {
int count = 0;
struct node* current = head;
while (current != NULL) {
count++;
current = current->next;
}
return(count);
}
/*
Build the list {1, 2, 3} in the heap and store
its head pointer in a local stack variable.
Returns the head pointer to the caller.
*/
struct node* BuildOneTwoThree() {
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = (struct node *)malloc(sizeof(struct node)); // allocate 3 nodes in the heap
second = (struct node *)malloc(sizeof(struct node));
third = (struct node *)malloc(sizeof(struct node));
head->data = 1; // setup first node
head->next = second; // note: pointer assignment rule
second->data = 2; // setup second node
second->next = third;
third->data = 3; // setup third link
third->next = NULL;
// At this point, the linked list referenced by "head"
// matches the list in the drawing.
return head;
}
Related
Im trying to learn doubly linked lists. I used the following to print:
typedef struct Node{
int data;
struct Node* prev;
struct Node* next;
}node;
typedef struct List{
node *head;
}list;
node * createNode(int data) {
node * newNode = (node*)malloc(sizeof(node));
newNode->data = data;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
_Bool isEmpty(const list *L)
{
if (L->head == NULL)
return 1;
return 0;
}
_Bool insert(list *L, node *N) {
if(isEmpty(L)) {
L->head = N;
}
else{
L->head->prev = N;
N->next = L->head;
L->head = N;
}
if (L->head==N)
return 1;
return 0;
}
void _print(list *L){
node *temp=L->head;
while(temp!=NULL){
printf("%d ", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(int argc, char *argv[]){
list *L1=(list *)malloc(sizeof(list));
node *N1=createNode(3);
node *N2=createNode(1);
node *N3=createNode(5);
insert(L1, N3);
insert(L1, N2);
insert(L1, N1);
_print(L1);
}
for reference my list struct only contains a pointer "head" and my node struct contains next, prev and data.
It prints the correct data but goes into infinite loop.
What is the reason ?
The problem is that this line in main:
list *L1=(list *)malloc(sizeof(list));
Allocates memory for the list, but does not initialize it.
Without initialization the value of L1->head can be anything.
And if it happens to be different than 0 (i.e. NULL), insert will interpret it as pointing to a valid node (which it isn't).
The result is undefined behavior (UB), which means anything can happen. It might seem to work, it can crash, or get into an infinite loop etc.
In order to fix it, you need to initialize the list pointed by L1.
You can do it at least in 2 ways:
Replace the call to malloc with calloc, which also zeroes the allocated memory:
list* L1 = (list*)calloc(sizeof(list), 1);
Add an explicit initialization after the malloc:
list* L1 = (list*)malloc(sizeof(list));
L1->head = NULL; /* <--- initialization */
You can also add a function for encapsulating the initialization.
I have started to learn about linked lists, and I have written this code.
It should be a recursive call to create a new link in a linked list in c.
But, if you’ll check the output, you’ll see it’s passing over the middle links.
I don’t know why I’m losing the middle links.
Btw, I do have a destroy function in my code, I just didn’t write it here.
I do have a different version of a working code, I don’t ask for solutions, I’m only asking why this recursive idea doesn’t work.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct node {
int data;
struct node *next;
}node;
node *create(node **head, int data)
{
if(!*head) {
*head = malloc(sizeof(node));
assert(*head);
(*head)->data = data;
(*head)->next = NULL;
return *head;
}
node *new = NULL;
new = create(&new,data);
(*head)->next = new;
return *head;
}
void display(node *head)
{
assert(head);
node *current = head;
do
{
printf("%d\t",current->data);
current = current->next;
}while(current);
}
int main()
{
int count = 0, data = 0;
node *head = NULL;
printf("Enter list count:\n");
while(count <= 0){
scanf("%d",&count);
if(count <= 0) printf("\nEnter a valid number:\n");
}
while(count){
scanf("%d",&data);
head = create(&head,data);
count--;
}
printf("\nHere are the elements:\n");
display(head);
return 0;
}
As implemented create() either adds a new node to the tail or iterates to the next linked node. Logic changed to affect that. It's confusing that the first argument is called head to changed it to n. Changed main() to retain the head and made the program non-interactive for ease of testing. Recatored display to use a for() loop:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
node *create(node **n, int data) {
if(!*n) {
*n = malloc(sizeof(**n));
assert(*n);
(*n)->data = data;
(*n)->next = NULL;
return *n;
}
node *n2 = (*n)->next;
(*n)->next = create(&n2, data);
return n2;
}
void display(node *head) {
assert(head);
for(node *c = head; c; c = c->next) {
printf("%d\t", c->data);
}
}
int main() {
node *head = NULL;
node *tail = NULL;
for(int i = 0; i < 10; i++) {
tail = create(&tail, i);
if(!head) head = tail;
}
display(head);
return 0;
}
and it displays:
0 1 2 3 4 5 6 7 8 9
If you compile your code with NDEBUG (some folks do that for production) then your code no longer has any error handling.
Thank you all for your answers. I see the problem now, after “explaining to the duck” a thousand times. In function create(), under the if() block, I assigned (*head)->next = new; without first making it point to the last link, so it’s just over write the next link in every call to the function.
The solution is:
Add a “current” pointer points to the head(to not lose it’s value)
Iterate through the list until we find the last link,
assign current->next the value of new.
Here is the fixed section:
node *new = NULL;
new = create(&new,data);
node *current = *head;
while(current->next) current = current->next;
current->next = new;
return *head;
I am practicing creating a link list, but encountered a problem when trying to insert an item to the front of the list. The code in my insert function works properly if I put it within main, but not when run separately as a function.
I am using a pointer as a argument in the function so I don't understand why the value in my print statement isn't changing to 100 which should be at the front of the linked list using the insert function (When I run the function 61 is printed, I am aiming for 100 to be printed).
Thanks for the help!
#include <stdio.h>
#include <stdlib.h>
typedef struct node *nodePtr;
typedef struct node node;
struct node {
int value;
nodePtr next;
};
node insert(node *first, int value)
{
nodePtr temp;
temp = malloc(sizeof(node));
temp->value = value;
temp->next = first;
first = temp;
}
int main()
{
nodePtr first;
first = malloc(sizeof(node));
first->value = 61;
first->next = NULL;
insert(first, 100);
printf("%d", first->value);
}
your passing a pointer to the node as a argument to the function and changing the value of formal parameter does not change the value of the actual parameter do this it should work.
enter code here
#include <stdio.h>
#include <stdlib.h>
typedef struct node *nodePtr;
typedef struct node node;
struct node {
int value;
nodePtr next;
};
void insert(node **first, int value)
{
nodePtr temp;
temp = malloc(sizeof(node));
temp->value = value;
temp->next = *first;
*first = temp;
}
int main()
{
nodePtr first;
first = malloc(sizeof(node));
first->value = 61;
first->next = NULL;
insert(&first, 100);
printf("%d",first->value);
}
You have passed a pointer to function insert() and stored it in a variable first whose scope is local to function insert(). Now you have
updated pointer first in function insert().
When you will return to main() function updated value of pointer next is lost that is why you are getting unexpected result while printing value in main().
To summarise:
first = malloc(sizeof(node)); // let's say first is p1
...
insert(first, 100); // first is P1
....
node insert(node *first, int value) // first is p1
....
tmp = malloc(sizeof(node)); // let's say tmp is p2
first = temp; // Now first has become p2 but its scope is local to insert()
....
printf("%d", first->value); // first is still p1 here
Solution
node* insert(node *first, int value)
{
nodePtr temp;
temp = malloc(sizeof(node));
temp->value = value;
temp->next = first;
first = temp;
return first;
}
int main()
{
nodePtr first;
first = malloc(sizeof(node));
first->value = 61;
first->next = NULL;
first = insert(first, 100);
printf("%d", first->value);
return 0;
}
I started learning C programming a few days ago through the book, Programming in C, and I have prior knowledge of java. Inserting a node into a linked list is very easy in java, but I thought if I could do the same in C.
So, I came up with this program,
#include "node.h"
void insertEntry(struct node* root, struct node* after)
{
struct node* first = root;
while(first != (struct node*) 0)
{
if(first->value == after->value)
{
struct node ins;
ins.value = 3456;
ins.next = first->next;
first->next = &ins;
}
first = first->next;
}
}
int main(void)
{
struct node n1, n2, n3;
struct node* list_pointer = &n1;
n1.value = 100;
n1.next = &n2;
n2.value = 200;
n2.next = &n3;
n3.value = 300;
n3.next = (struct node*) 0;
void insertEntry(struct node* root, struct node* after);
while (list_pointer != (struct node*) 0)
{
printf("%i\n", list_pointer->value);
list_pointer = list_pointer->next;
}
printf("\n");
list_pointer = &n1;
insertEntry(list_pointer, &n2);
while (list_pointer != (struct node*) 0)
{
printf("%i\n", list_pointer->value);
list_pointer = list_pointer->next;
}
return 0;
}
node.h
#include <stdio.h>
struct node
{
int value;
struct node* next;
};
Basically, this program takes pointer to the first element of the linked list and the pointer to the element after which it is to be inserted, and inserts a new node after this node.
But when I run this, my program crashes and I cannot find where or why this error occurs.
I looked over to the code in java and tried to implement the same in C.
Thank you.
Here's your problem:
{
struct node ins; // You create an object in the stack
ins.value = 3456;
ins.next = first->next;
first->next = &ins; // You reference your object
} // Your object is popped out of the stack and ceases to exist
// Any access to first->next past this block may cause segfault
In order to avoid this, you could create ins with malloc(), but beware: this isn't java and you have to keep track of all objects you allocated in the heap yourself.
The main problem is you insert a node that is allocated on the stack -- it's invalid as soon as the function is left. To allocate new memory, you need malloc() (don't forget to free() when done, there is no garbage collection).
A few side notes:
It's utterly pointless to cast 0 when used as a pointer to any specific pointer type ... 0 is 0.
You don't need the root node for inserting, so why pass it in the first place?
declaring a prototype inside of a function (in that case: main) doesn't make too much sense ... it will work without because the function you want to call is already defined in the same file.
#include headers where they are needed! node.h doesn't need stdio, the main program does.
A version of roughly your program that would work:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node
{
int value;
struct node *next;
};
struct node *insertEntry(struct node* after, int val)
{
assert(after); /* not NULL */
struct node *new = malloc(sizeof(struct node));
new->value = val;
new->next = after->next;
after->next = new;
return new;
}
void freeNodeList(struct node* root)
{
struct node *current, *last;
current = root;
while (current)
{
last = current;
current = current->next;
free(last);
}
}
int main(void)
{
struct node *n1, *n2, *n3;
struct node *ptr;
n1 = malloc(sizeof(struct node));
n2 = malloc(sizeof(struct node));
n3 = malloc(sizeof(struct node));
n1->value = 100;
n1->next = n2;
n2->value = 200;
n2->next = n3;
n3->value = 300;
n3->next = 0;
insertEntry(n2, 250);
ptr = n1;
while (ptr)
{
printf("%d\n", ptr->value);
ptr = ptr->next;
}
freeNodeList(n1);
return 0;
}
You should read up on gdb and how to use it.
gcc -Wall -O0 -g x.c -o x
x being your program to compile with debuging information and no optimisation.
then run your program through gdb to find the location/occurrence of the fault.
ie.
gdb x
Here is a linked list I am working on, and trying to figure out exactly what each line does. The way I seem to be learning how to program is painstakingly difficult, and I am getting extremely discouraged. Regardless, I understand how the link list works, but I am not understanding what the code is saying and what it exactly is doing to create the structs. For example: I can't understand why would you be assigning a pointer to node (13 and 14), especially when my understand of pointers is that they are used to store memory locations.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct numnode
{
int val;
struct numnode * next;
};
typedef struct numnode node;
main()
{
int i;
node * head;
node * newnode;
head = NULL;
for (i = 1; i <= 10; i++)
{
newnode = (node *) malloc(sizeof(node));
newnode->val = i;
newnode->next = NULL;
if (head == NULL)
{
head = newnode;
}
else
{
newnode->next = head;
head = newnode;
}
}
}
Here are some annotations (and minor edits to reduce the amount of code).
/* Linked list node definition */
struct node {
int val;
struct node * next;
};
int main() {
int i;
struct node *head, *new_node;
head = NULL;
for (i = 1; i <= 10; i++) {
// Allocate a new node and initialize its components (val and next)
new_node = (struct node *) malloc(sizeof(node));
new_node->val = i;
new_node->next = NULL;
// The if block is actually not necessary...
if (head == NULL) {
// If the linked list is empty, set the head pointer to the initial node
head = new_node;
} else {
// Now that you have your new node, connect it. Start:
// head->[current linked list]
// [new_node.next]->NULL
new_node->next = head;
// head->[current linked list]->...
// [new_node.next]->[current linked list]->...
head = newnode;
// head->[new_node.next]->[current linked list]->...
}
}
}
The key thing is that malloc returns a pointer to memory. Each new node is allocated dynamically and thus is a location in memory (not a basic type).
If you fix the statement pointed out by PakkuDon you will find that the code inserts at the head. It will end up with a list whose values descend from 9 down to 1.
pointer is just the thing to tell you where is the value,like a phone number,you can call anyone no matter who there is,as you konw the number.pointer can point to anything(under your access) as you want,no matter it is a int or a struct.
Here is the summary of this code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct numnode
{
int val;
struct numnode * next;
};
typedef struct numnode node;
main()
{
int i;
node * head;
node * newnode;
head = NULL;
for (i = 1; i <= 10; i++)
{
newnode = (node *) malloc(sizeof(node));
newnode->val = i;
newnode->next = NULL;
if (head == NULL) // It'll be NULL first time, as head = NULL.
{
// True # i = 1
head = newnode;
}
else // Afterwards, as head=newnode
{
// New node will be created every time. Till i <= 10.
newnode->next = head;
head = newnode;
}
}
}
It is a simple code though.
PS: It is head == NULL