C Linked List from Array - c

In the function, I created an array of size two which will hold two PolyTerms. Then, within the function, i created a List. After that, i want to pass the array elements into the List as linked list.
I'm getting an error after the if statement
head->next = nodePtr; (Bad Access).
Thanks.
Part of my code:
struct Fraction {
int num;
int denom;
};
struct PolyTerm {
int ex;
struct Fraction coe;
};
typedef struct PolyTerm PTerm;
typedef struct PolyTerm* PTermPtr;
struct PolyListNode {
PTermPtr termAddr;
struct PolyListNode* next;
};
typedef struct PolyListNode PList;
typedef struct PolyListNode* PNodeAddr;
typedef struct PolyListNode* PolyList;
PolyList sortPoly(void);
PolyList sortPoly() {
int arraySize = 2;
int i = 0;
//Array of PTermPtr. Each element holds ex, num and denom.
//Populating 2 elements for arrayTerm
PTermPtr arrayTerm;
arrayTerm = (PTermPtr) malloc(arraySize);
((arrayTerm) + 0)->ex = 2;
((arrayTerm) + 0)->coe.num = 2;
((arrayTerm) + 0)->coe.denom = 2;
((arrayTerm) + 1)->ex = 3;
((arrayTerm) + 1)->coe.num = 2;
((arrayTerm) + 1)->coe.denom = 2;
PNodeAddr nodePtr; //To create nodes
PolyList head = 0; //New List
PNodeAddr current; //To store Address of List Head
current= head; //Store address of head of list
while (i < arraySize) {
nodePtr = (PNodeAddr) malloc(sizeof(PList));
nodePtr->termAddr = (arrayTerm + i);
nodePtr->next = 0;
if (current == 0) {
head->next = nodePtr; //ERROR. Bad Access
} else {
while (current != 0) {
current = current->next;
}
current->next = nodePtr;
}
i++;
}
free (arrayTerm);
return head;
}

Just think about what is going on the first time the code goes thru the loop:
PolyList head = 0; //New List
Head is now 0 (or null).
current= head; //Store address of head of list
Current and head are now 0
if (current == 0) {
It is.
head->next = nodePtr; //ERROR. Bad Access
Try to access head which is 0 and null. you are accessing null
It should also be noted the sizes you pass in to malloc are wrong. You are passing in the size of the arrays you want to create not the size of memory needed.
For example you are need a 2 element array of type mytype you want this code:
newarray = malloc(2 * sizeof(mytype));
then
newarray[0]
and
newarray[1]
have space for a mytype.

Related

I am implementing a doubly linked list in C, and having segmentation fault in a destroy function

I divided the code in two files, .h and .c
The definition of function names is in .h, the implementation of the function is in .c
in my main file:
struct no
{
tipo info;
struct no *ant;
struct no *nxt;
};
struct list
{
no_t *head;
no_t *tail;
int size;
};
this is in my .h file:
typedef struct no no_t;
typedef struct list list_t;
typedef int tipo;
...again in main
void list_destroy(list_t **l)
{
if ((*l) == NULL || l == NULL)
return;
if (!(*l)->head)
return;
no_t *next = (*l)->head; //create two variables for iterating through the list
no_t *aux; //set aux to free
while (next->nxt) //the pointer for next node, in the last node, is NULL
{ //by that I believe I'm able to iterate through all nodes
aux = next;
free(aux);
next = next->nxt;
}
free(*l);
(*l) = NULL;
}
is quite a simple code, but I can't see where I'm missing here
next = next->nxt;
For the compiler it makes no difference, for sure. But for someone, even you, it is hard to read this next = next->nxt stuff. Or is it is not?
A possible alternative (using your code) and a short test program
so_list.h
#include <stdio.h>
#include <stdlib.h>
typedef int Tipo;
typedef struct st_no
{
Tipo info;
struct st_no* prev;
struct st_no* next;
} Node;
typedef struct
{
Node* head;
Node* tail;
unsigned size;
} List;
List* list_create();
List* list_destroy(List*);
int list_insert(const Tipo, List*);
In the header, only typedefs and the function prototypes.
names with only the first letter in uppercase are reserved here for defined names. An useful convention.
instead of using List** is often clearer to just return the pointer to the list. In this way it is easier for example to invalidate the pointer and to create the linked lists as in
List* my_list = list_create();
my_list = list_destroy(my_list);
and there is no need to test the two levels of indirection as you need when ** is used
main.c: a minimalist test set
#include "so-list.h"
int main(void)
{
List* my_list = list_create();
my_list = list_destroy(my_list);
my_list = list_create();
for (int i = 1; i <= 5; i += 1)
printf("insert(%d,list) returned %d\n",
i, list_insert(i,my_list)
);
my_list = list_destroy(my_list);
my_list = list_create();
for (int i = 11; i <= 15; i += 1)
printf("insert(%d,list) returned %d\n",
i, list_insert(i, my_list)
);
my_list = list_destroy(my_list);
return 0;
}
A list is created, then destroyed
using the same pointer, a list is created, values 1 to 5 are inserted ant then the list is deleted.
using the same pointer, a list is created, values 11 to 15 are inserted ant then the list is again deleted.
the output
List created!
List deleted!
List created!
insert(1,list) returned 1
insert(2,list) returned 2
insert(3,list) returned 3
insert(4,list) returned 4
insert(5,list) returned 5
1 deleted
2 deleted
3 deleted
4 deleted
5 deleted
List deleted!
List created!
insert(11,list) returned 1
insert(12,list) returned 2
insert(13,list) returned 3
insert(14,list) returned 4
insert(15,list) returned 5
11 deleted
12 deleted
13 deleted
14 deleted
15 deleted
List deleted!
code for destroy_list()
List* list_destroy(List* l)
{
if (l == NULL) return NULL;
// delete the ´size´ nodes, 1 by 1
Node* p = NULL;
for (unsigned i = 0; i < l->size; i += 1)
{
p = l->head->next; // save pointer
printf("%d deleted\n", l->head->info); // just for the demo
free(l->head); // free head
l->head = p; // advance head
}
free(l); // free list
printf("List deleted!\n\n"); // just for the demo
return NULL;
}
This function always return NULL as just a way to invalidade the pointer in the caller in the same expression as in pList = destroy_list(pList);
This is somewhat different than the code you wrote. We just delete the elements one by one as we know the list has size elements. A local pointer is used in the loop to save the address of the next element. It seems to be easier to read.
The complete code for so-list.c
#include "so-list.h"
List* list_create()
{
List* one = (List*)malloc(sizeof(List));
one->head = NULL;
one->tail = NULL;
one->size = 0;
printf("List created!\n");
return one;
}
List* list_destroy(List* l)
{
if (l == NULL) return NULL;
// delete the ´size´ nodes, 1 by 1
Node* p = NULL;
for (unsigned i = 0; i < l->size; i += 1)
{
p = l->head->next; // save pointer
printf("%d deleted\n", l->head->info);
free(l->head); // free head
l->head = p; // advance head
}
free(l); // free list
printf("List deleted!\n\n");
return NULL;
}
// just for test, insert ´info´ at the end, returns size
int list_insert(const Tipo info, List* l)
{
// insert node at the end, just for test
Node* one = (Node*)malloc(sizeof(Node));
one->info = info;
one->next = NULL;
one->prev = l->tail;
if (l->size == 0)
l->head = one; // 1st node
else
l->tail->next = one;
l->tail = one;
l->size += 1;
return l->size;
};
about your version of list_destroy()
The logic there is a bit wrong but the error is well described in another answer. I recommend not to use ** in this situations. But it can be done for sure.
so-list.c
This is just a minimum to have a running test
#include "so-list.h"
List* list_create()
{
List* one = (List*)malloc(sizeof(List));
one->head = NULL;
one->tail = NULL;
one->size = 0;
printf("List created!\n");
return one;
}
List* list_destroy(List* l)
{
if (l == NULL) return NULL;
// delete the ´size´ nodes, 1 by 1
Node* p = NULL;
for (unsigned i = 0; i < l->size; i += 1)
{
p = l->head->next; // save pointer
printf("%d deleted\n", l->head->info);
free(l->head); // free head
l->head = p; // advance head
}
free(l); // free list
printf("List deleted!\n\n");
return NULL;
}
// just for test, insert ´info´ at the end, returns size
int list_insert(const Tipo info, List* l)
{
// insert node at the end, just for test
Node* one = (Node*)malloc(sizeof(Node));
one->info = info;
one->next = NULL;
one->prev = l->tail;
if (l->size == 0)
l->head = one; // 1st node
else
l->tail->next = one;
l->tail = one;
l->size += 1;
return l->size;
};
This has an issue
no_t *next = (*l)->head;
no_t *aux;
while (next->nxt)
{
aux = next; // aux point to the same object as next
free(aux); // free aux, which is the same as next
next = next->nxt; // deference next, which just got free'd. OOPS!
}
You invoke free on aux, which is also aliasing next. Then you try to deference next->nxt. Well, next just got released in the previous statement. Also, as I called out in the comment, you are leaking the last element in the list.
Fixed:
no_t* aux = (*l)->head;
while (aux)
{
no_t* next = aux->nxt;
free(aux);
aux = next;
}
You should look to your "free" and your "next->nxt" statements. May it can help you solve it.

Problem with implementing a function to reverse a linked list in C

So I wanted to write a function to reverse a linked list using an array of pointers but I'm getting warnings: assignment from incompatible pointer type [-Wincompatible-pointer-types]. I wanted to store the pointers to nodes of the list in an array of pointers int **s = (int **)calloc(10, sizeof(int)); and thought that s[*top] = *l will assign the pointer to which **l is pointing to *topth element of array *s[]. So am I wrong thinking that elements of array *s[] are pointers? If someone could explain it to me I'd be very glad. Here's the whole code (except the part where I create the list which is fine):
typedef struct list {
int v;
struct list *next;
} list;
void reverseListS(list **l, int **s, int *top) {
while ((*l)->next != NULL) {
s[*top] = *l;
*top++;
*l = (*l)->next;
}
list *temp = *l;
while (!(*top == 0)) {
temp->next = s[*top];
*top--;
temp = temp->next;
}
temp->next = NULL;
}
int main() {
int **s = (int **)calloc(10, sizeof(int));
int *top = 0;
reverseListS(&l, s, top);
}
Many issues. Just in main: Should be sizeof(int *) (or sizeof *s). Although, I think you want s to be an array of ints, so it should be an int *. And top does not point anywhere - why is it even a pointer?. l is not initialized.
In reverseListS at s[*top] = *l; you are trying to assign a struct list * to an int *.
I have re-written your code to work. I'm not saying this is the best way to reverse a list, but it makes the fewest modifications to your code - as I understand it.
typedef struct list {
int v;
struct list *next;
} list;
void reverseListS(list **l)
{
// Count number of items
// *this step could be skipped by dynamically resizing the array with realloc
int count = 0;
list *temp = *l;
while (temp) {
count += 1;
temp = temp->next;
}
// Allocate memory - an array of list *
list **s = malloc(count * (sizeof *s));
if (!s) return;
// Copy list item addresses to array
temp = *l;
int index = 0;
while (temp) {
s[index++] = temp;
temp = temp->next;
}
// Rebuild the list in reverse order
// *if you already have an "append_to_list" function, that should be used here
temp = NULL;
for (int i = index - 1; i >= 0; i--) {
if (!temp) {
// This is the new first item in list.
// Make the original list point to it
*l = temp = s[i];
}
else {
// Append to end of new list
temp->next = s[i];
temp = s[i];
}
s[i]->next = NULL;
}
free(s);
}
int main() {
list *l;
// TODO: Fill the list with values.
reverseListS(&l);
}

Why do these code snippets behave differently?

I am relatively new to C, and have been learning about linked lists with pointers.
I learned that
(*foo).bar is the same ad foo->bar.
foo->bar is used because it is more readable.
Therefore I do not understand why these code snippets behave differently:
1)
void appendCourse(CourseNode** pLL, Course c){
CourseNode * root = *pLL;
CourseNode* last = makeCourseNode(c);
if(root != NULL){
CourseNode node = *root;
while(node.pNext != NULL){
node = *node.pNext;
}
node.pNext = last;
} else {
*pLL = last;
}
}
and
2)
void appendCourse(CourseNode** pLL, Course c){
CourseNode * root = *pLL;
CourseNode* last = makeCourseNode(c);
if(root != NULL){
CourseNode *node = root;
while(node->pNext != NULL){
node = node->pNext;
}
node->pNext = last;
} else {
*pLL = last;
}
}
to me it looks like 1) should behave as if dereferencing first, then member access. Sort of like (*foo).bar
but 1) doesn't seem to work right at all, it can only successfully add the first element.
2) does however add all elements into the linked list.
In case this helps: my structs and other method:
typedef struct CourseNode {
struct CourseNode* pNext;
Course course;
} CourseNode;
typedef struct
{
StudentNode *pWaitlistHead; // Waitlist for this course
char szCourseId[12]; // Course Identifier
char szRoom[15]; // Room number of the course
char szDays[15]; // What days the course will meet, ex: MWF, TR, etc
char szTimes[15]; // Meeting Time, ex: 10:00-11:15am
int iAvailSeats; // Number of available seats in the course
double dFee; // Additional fees for the course
} Course;
CourseNode* makeCourseNode(Course c){
CourseNode * node = malloc(sizeof(CourseNode));
node->pNext = NULL;
node->course = c;
return node;
}
CourseNode node = *root;
while(node.pNext != NULL){
node = *node.pNext;
}
This creates a new CourseNode called node. The value of that new CourseNode is modified, but that has no affect on the linked list.
CourseNode *node = root;
while(node->pNext != NULL){
node = node->pNext;
}
Here, node points to a CourseNode that is on the linked list.
The simplest way to understand the difference is that the first code excerpt creates new CourseNodes. It's like the difference between these two:
int foo (int *i)
{
int *j = i; // j is a pointer to the same int i points to
*j = 2; // this changes the value of the int i points to
int j = *i; // this creates a new int
j = 2; // this changes the value of that new int
}

How to dynamically populate Linked List with Fibonacci series

I have a linked list, which I wanted to populate up to a certain loop number. I have my code below is shows a Fibonacci series using a C Linked list.
Here is my code without any loop:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int count;
int fibo;
struct Node* next;
}node;
int
fibo(int val){
if(val == 1 || val == 2) {
return 1;
}
return fibo(val - 1) + fibo(val - 2);
}
int
main (void)
{
node f1, f2, f3;
f1.count = 1;
f1.fibo = fibo(1);
f2.count = 2;
f2.fibo = fibo(2);
f3.count = 3;
f3.fibo = fibo(3);
f1.next = &f2;
f2.next = &f3;
f3.next = NULL;
printf("f1 fibo : %i\n", f1.fibo);
printf("f2 fibo : %i\n", f2.fibo);
printf("f3 fibo : %i\n", f3.fibo);
return (0);
}
Now I want to do this via a loop. How would I do that?
For this answer, I'm going to ignore the computational efficiency concerns that arise from recomputing all of the Fibonacci numbers up to the given number you are retrieving with each call to fibo(n).
Linked lists are not usually "random access" data structures that let you access an arbitrary element with an index. When using a linked list with pointers, you only need to have the pointer to the head (first element) of the linked list. You then traverse the list starting at the head using a loop going through each next link. If a list is empty, your head is usually NULL.
You can apply this here. One way (there are several) is to define a function to allocate and set a single entry:
node *set_fibo(int n)
{
node *fibo_entry = malloc(sizeof(node));
if ( fibo_entry == NULL ) {
// error
}
fibo_entry->count = n;
fibo_entry->fibo = fibo(n);
fibo_entry->next = NULL;
return fibo_entry;
}
And then in your main:
node *fibo_list = NULL;
node *last_fibo = NULL;
// Assume n_fibo is the number of Fibonacci numbers you want to store in order
for ( int n = 1; n <= n_fibo; n++ ) {
if ( n == 1 )
fibo_list = last_fibo = set_fibo(1);
else {
last_fibo->next = set_fibo(n);
last_fibo = last_fibo->next;
}
}
Although the question has already been answered, I would like to add something regarding the efficiency aspect of your code. As pointed out before, you do not have to calculate the fibo value by starting from the beginning, since you saved the latest results in the singly linked list.
So given you have the following list 1-1-2-3-5-, you can easily calculate the fibo value of the new node by simply adding the fibo value of the two lates elements (i.e. 3 and 5). Hence the value of the fibo value of the new node should be 8.
Given the pointer to the second last element, this function will add add a new node to the list and set the correct fibo value:
void addNode(struct Node* node){
struct Node* n = malloc(sizeof(struct Node));
n->next = NULL;
n->count = node->next->count + 1;
n->fibo = node->fibo + node->next->fibo;
node->next->next = n;
}
In order to use this function, you have to create the first two nodes in the list:
struct Node* n2 = malloc(sizeof(struct Node));
n2->count = 2;
n2->fibo = 1;
n2->next = NULL;
struct Node* n1 = malloc(sizeof(struct Node));
n1->count = 1;
n1->fibo = 1;
n1->next = n2;
If you now want to add - lets say 10 - new nodes, you simply do:
struct Node* ptr = n1;
int i;
for(i=0; i<10;i++) {
addNode(ptr);
ptr = ptr->next;
}
If you now want to print the entries of all nodes in the list, simply iterate over the list until you reach NULL.
ptr = n1;
while(ptr != NULL) {
printf("fib(%d) = %d\n ", ptr->count, ptr->fibo);
ptr = ptr->next;
}
Please keep in mind, that you have to manually free dynamically allocated items!
In your example, the nodes are automatic variables in main. They are not dynamically allocated and they live as long as you don't return from main. You can extend this concept with a automatic array of nodes:
#include <stdio.h>
#include <stdlib.h
typedef struct Node Node;
struct Node {
int count;
int fibo;
Node* next;
};
#define N 30
int main (void)
{
Node fibo[N];
Node *head = NULL;
Node **p = &head;
int f1 = 0;
int f2 = 0;
for (size_t i = 0; i < N; i++) {
Node *nd = &fibo[i];
nd->count = i + 1;
nd->fibo = f2 + f1 ? f2 + f1 : 1;
f1 = f2;
f2 = nd->fibo;
*p = nd;
p = &(*p)->next;
}
*p = NULL;
Node *nd = head;
while (nd) {
printf("fib(%d) == %d\n", nd->count, nd->fibo);
nd = nd->next;
}
return (0);
}
It's not clear, though, why you need the Fibonacci series as linked list. Also, a word of warning: Don't mix nodes on the stack (like here) and nodes on the heap (as in lurker's answer) in a list. This answer just extends your answer to many nodes, whereas lurker's answer shows a more general concept of linked lists.
Here is how I think you can do it. You can use an array for the nodes.
node f[3];
int i;
for ( i = 0 ; i < 3 ; i++ )
{
f[i].count = i+1;
f[i].fibo = fibo (i+1);
if ( i == 2 )
{
f[i].next = NULL;
}
else
{
f[i].next = &f[i+1];
}
}

Split linked list into half

I am trying to create a function splitlist(), which will split a singly linked list into two sublists – one for the front half, and one for the back half. I have come up with a code below which will work for the first time that I call the function, but when I call the function repeatedly, the program crashes. Any advice on how I can change my code to prevent such an error? The function splitlist() is void as it prints two lists which contains frontList and backList.
typedef struct _listnode {
int item;
struct _listnode *next;
} ListNode;
typedef struct _linkedlist {
int size;
ListNode *head;
} LinkedList;
void splitlist(LinkedList* list1, LinkedList * firsthalf, LinkedList *secondhalf)
{
ListNode *cur = list1->head;
ListNode *front = firsthalf->head;
ListNode *back = secondhalf->head;
int totalnodes = list1->size;
int i;
if (totalnodes % 2 != 0) //if odd number of elements, add 1 to make it easier for traversal of list
{
totalnodes = totalnodes + 1;
}
int halfnodes = totalnodes / 2;
{
for (i = 0; i < halfnodes; i++)
{
if (firsthalf->head == NULL) //initialise the head
{
firsthalf->head = malloc(sizeof(ListNode)); //create first node
front = firsthalf->head;
}
else
{
front->next = malloc(sizeof(ListNode));
front = front->next;
}
front->item = cur->item; // insert value from list1 into firsthalf
cur = cur->next; //point to next node in list1
}
front->next = NULL; //last node
for (i = halfnodes; i < totalnodes; i++)
{
if (secondhalf->head == NULL)
{
secondhalf->head = malloc(sizeof(ListNode));
back = secondhalf->head;
}
else
{
back->next = malloc(sizeof(ListNode));
back = back->next;
}
back->item = cur->item;
cur = cur->next;
}
back->next = NULL;
}
}
There are many things wrong with this code. First of all malloc return values are not checked, malloc can fail. And i strongly suspect that because of malloc fail your programm stops. You repeatedly allocate the memory inside the function, but do you free it when you do not need it anymore? Why do yo use malloc at all?
As posted earlier you do not need to.
Please post how the function is called, because it is really unclear how LinkedList* list1, LinkedList * firsthalf, LinkedList *secondhalf are used. Also it is unclear what is the structure of LinkedList is.
why use malloc?It will create a new list.But we want to split the list.
I guess firsthalf and second half are NULL
void splitlist(LinkedList* list1, LinkedList * firsthalf, LinkedList *secondhalf)
{
ListNode *cur = list1->head;
ListNode *front;
int totalnodes = list1->size;
int i;
if (totalnodes % 2 != 0) //if odd number of elements, add 1 to make it easier for traversal of list
{
totalnodes = totalnodes + 1;
}
int halfnodes = totalnodes / 2;
firsthalf->head=list1->head;
front=firsthalf->head;
for(i=0;i<halfnode;i++)
front=front->next;
secondhalf->head=front->next;
front->next=NULL;
}
At first glance I can't see much wrong with your code (assuming the assignment is to create copies of the list nodes in the new half lists), so the error could be in how you call the function, as an exmple, that could be:
LinkedList mainlist= {0};
LinkedList firsthalf= {0}, secondhalf= {0};
//mainlist got filled somehow; we now want to split
firsthalf->List= malloc(sizeof(ListNode));
secondthalf->List= malloc(sizeof(ListNode));
memset(firsthalf->List, 0, sizeof(ListNode));
memset(secondhalf->List, 0, sizeof(ListNode));
splitlist(&mainlist, &firsthalf, &secondhalf);

Resources