Creating a linked list with a for loop - c

Here is my struct
struct ListItem{
int data;
struct ListItem *next;
};
Assuming the first node of the linked list will have data = 0, I want to write a for loop that creates a linked list of size 5 but I'm not sure how to work
I tried the following
int main(int argc, char* argv[]){
struct ListItem a;
a.data = 0;
for (int i = 1; i < 5; i++){
struct ListItem *pointer = &a;
struct ListItem nextnode;
nextnode.data = i;
a.next = &nextnode;
pointer = pointer->next;
}
}
But the result is
a.data = 0
and a.next->data = 4

Don't modify a. Take a temp node starting as a. Make it's next point to the new node and then set temp node to the new node. Also allocate dynamically in heap. Otherwise the memory will get deallocated after every loop run

struct ListItem a[5] = { {0, NULL}};
struct ListItem *pointer = &a[0];
for (int i = 0; i < 5; i++){
a[i].data = i;
if(i != 5 -1)
a[i].next = &a[i+1];
}

Related

How to allocate struct pointer inside a struct dynamically?

I currently have a struct Struct1 which has a pointer to Struct2 that gets allocated multiple times based on some conditions in the code. I tried to allocate it test->Struct2Pair[i] = malloc(sizeof(struct Struct2));this way but it seems to fail. Any idea what I am doing wrong?
Here is a simplified version of what I'm trying to do.
struct Struct2 {
int x;
int y;
};
struct Struct1 {
struct Struct2 *Struct2Pair;
int val;
};
int main()
{
struct Struct1 *test = malloc(sizeof(struct Struct1));
for ( int i = 0; i < 5; i++ )
{
test->Struct2Pair[i] = malloc(sizeof(struct Struct2));
}
return 0;
}
Thanks!
In order to make Struct2Pair to point 5 consecutive memory object of type Struct2 you must allocate a 5*sizeof(Struct2). so in latter part of code you can access it as an array of size 5.
You must do null check for the return value of malloc.
struct Struct1 *test = malloc(sizeof(struct Struct1));
// |-----change is here and here--------------|
// v v
test->Struct2Pair = malloc(sizeof(struct Struct2) * 5);
//access can be as follows for all the index from 0 to 4
test->Struct2Pair[2].x = 10;
test->Struct2Pair[2].y = 20;
For better visualization refer this and this.
The issue you are having is located within the for loop and the number of available Struct2s in the test->Struct2Pair array.
You hadn't allocated any space for test->Struct2Pair before placing Struct2s into it
test->Struct2Pair[i] = malloc(sizeof(struct Struct2));
Then loop through more indexes then are available for the test->Struct2Pair array
for ( int i = 0; i < 5; i++ )
You may consider adding another variable to store the size of the test->Struct2Pair array:
int size = 5;
struct Struct1 *test = malloc(sizeof(struct Struct1));
test->Struct2Pair = malloc(size * sizeof(struct Struct2));
for ( int i = 0; i < size; i++ )
{
test->Struct2Pair[i].x = 0;
test->Struct2Pair[i].y = 0;
}
Reference on malloc:
https://en.cppreference.com/w/c/memory/malloc

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);
}

Dynamic Struct Array at Specific Address

I am attempting to dynamically allocate an array of the following struct at a particular address in memory. I use the pointer struct page_frame* memBlocks as the start to the array, but each access to the next element with memBlocks[i] in the for loop only moves 8 bytes. I checked the size of my struct in gdb which shows the expected 16 bytes, so why are accesses to the pointer behaving in this way?
struct page_frame{
struct page_frame* next; //Next node of linked list
int used;
};
struct page_frame* memBlocks;
memBlocks = (struct page_frame*)0xffffffff80000000 + physFree;
int indices = ((int)physEnd/4096)
for(int i = 0; i < indices; i++)
{
struct page_frame temp;
temp.used = 3;
temp.next = (struct page_frame*)&memBlocks[i+1];
memBlocks[i] = temp;
}
I was overwriting my structs by setting each element equal to temp. I was able to fix it with the following.
struct page_frame* memBlocks = (struct page_frame*)0xffffffff80000000 + physFree;
int indices = ((int)physEnd/4096);
//struct page_frame arr[physEnd];
for(int i = 0; i < indices; i++)
{
memBlocks[i].used = 1;
memBlocks[i].next = &memBlocks[i+1];
}

Creating List using pointers

I want to create a linked list and keep two pointers. One for the head and one for the last element. I tried several approaches and just found a solution, but I don't know why my first solution don't work. The pointer in head->next always points on the last element, instead of the correct one.
int main(void){ // first solution
struct pointList *lastElement;
struct pointList *head;
struct pointList headHelp = {.next = NULL, .p.x = 5, .p.y = 5};
head = &headHelp;
int i = 0;
lastElement = &headHelp;
for( i = 8; i < 10; i++){
printf("LastElement: %d/%d\n", lastElement->p.x, lastElement->p.y);
struct pointList *helpPoint;
helpPoint = ((struct pointList*) malloc(sizeof(struct pointList)));
struct pointList newElement = *helpPoint;
newElement.next = NULL;
newElement.p.x = i;
newElement.p.y = i;
lastElement->next = &newElement;
lastElement = &newElement;
}
//printList(head);
printf("LastElement: %d/%d\n", lastElement->p.x, lastElement->p.y);
printf("head -> next: %d/%d\n", head->next->p.x, head->next->p.y);
printf("finish\n");
return 0;
}
output:
LastElement: 5/5
LastElement: 8/8
LastElement: 9/9
head -> next: 9/9
finish
but it should be : head -> next: 8/8
So the "next" pointer of head is changed in every loop execution
The solution which works looks like this:
int main(void){
struct pointList *lastElement;
struct pointList *head;
struct pointList headHelp = {.next = NULL, .p.x = 5, .p.y = 5};
head = &headHelp;
int i = 0;
lastElement = &headHelp;
for( i = 8; i < 10; i++){
printf("LastElement: %d/%d\n", lastElement->p.x, lastElement->p.y);
lastElement->next = ((struct pointList*) malloc(sizeof(struct pointList)));
lastElement->next->next = NULL;
lastElement->next->p.x = i;
lastElement->next->p.y = i;
lastElement = lastElement->next;
}
//printList(head);
printf("LastElement: %d/%d\n", lastElement->p.x, lastElement->p.y);
printf("head -> next: %d/%d\n", head->next->p.x, head->next->p.y);
printf("finish\n");
return 0;
}
used struct:
struct pointList {
struct point p;
struct pointList *prev;
};
The problem with the first code snippet is that you take and use the pointer to a local variable. The variable newElement have its scope inside the loop only, so when the loop iterates the current newElement variable goes out of scope and you are left with a stray pointer. This leads to undefined behavior.
You also allocate memory for helpPoint but you don't actually use it (when you initialize newElement using helpPoint you initialize one uninitialized structure with another uninitialized structure), and you do not free it anywhere leading to memory leaks.

C Linked List from Array

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.

Resources