Transferring data from queue to array - c

I'm trying to put integer data from each node in a queue into an array called arr. The data for each node is inputted by the user, say there's 5 nodes, and has 1 2 3 4 5, where node 1 stores a value of 1 and node 5 stores a value of 5. My code is below:
typedef struct linkedList {
int val;
struct linkedList *next;
} list;
I've tried doing the following but I'm getting a few warnings when I compile the code, I only included the body of the function and not the header or prototype and such.
int i;
int *arr;
list *node = NULL;
for(i = 0; i < 5; i++) {
arr[i] = (int*)malloc(sizeof(int));
arr = node->id;
node = node->next;
}
The errors that I get are: warning: assignment to ‘int *’ from ‘int’ makes pointer from integer without a cast and warning: variable ‘arr’ set but not used
How do I actually get the data from the queue into an array so that the array is arr[0]=1 and arr[4]=5]? Thanks.

Assuming you already have your linked list allocated correctly and you know the number of nodes (since you didn't post the code for your linked list) then your copy to array function should look like this.
int* copylist(struct LinkedList* ls,int numberofnodes){
int* arr = malloc(sizeof(int)*numberofnodes);
for(int index = 0; index < numberofnodes; ++index){
arr[index] = ls->val;
ls = ls->next;
}
return arr;
}

Related

i am having problems understanding this code, can someone help me explicitly explain it, expecially " while (size--) & tmp = (int *)&node->n;"

#include <stdio.h>
#include <stdlib.h>
/**
* struct listint_s - Doubly linked list node
*
* #n: Integer stored in the node
* #prev: Pointer to the previous element of the list
* #next: Pointer to the next element of the list
*/
typedef struct listint_s // generating a structure
{
const int n;
struct listint_s *prev;
struct listint_s *next;
} listint_t;
/**
* create_listint - Creates a doubly linked list from an array of integers
*
* #array: Array to convert to a doubly linked list
* #size: Size of the array
*
* Return: Pointer to the first element of the created list. NULL on failure
*/
listint_t *create_listint(const int *array, size_t size)
{
listint_t *list;
listint_t *node;
int *tmp;
list = NULL;
while (size--)
{
node = malloc(sizeof(*node));
if (!node)
return (NULL);
tmp = (int *)&node->n;
*tmp = array[size];
node->next = list;
node->prev = NULL;
list = node;
if (list->next)
list->next->prev = list;
}
return (list);
}
I am having difficulty understanding these lines of code
while (size--)
and
tmp = (int *)&node->n;
When will the code exit the while loop, also i really want to understand how this piece of code works.
Within the structure
typedef struct listint_s // generating a structure
{
const int n;
struct listint_s *prev;
struct listint_s *next;
} listint_t;
the data member n is declared with the qualifier const. So you may not directly assign to it a value like for example
node->n = array[size];
The compiler will issue an error saying that you are trying to change a constant object.
So there is used a trick. At first there is declared a pointer to the object as a pointer to a non-constant object
int *tmp;
and this pointer is assigned with the address of the data member node->n using casting
tmp = (int *)&node->n;
The casting is required because the expression &node->n has the type const int *
And then using the pointer tmp a value is assigned to the constant object
*tmp = array[size];
As for this while loop
while (size--)
the it iterates while the number of elements in the array is not equal to 0. You may rewrite the while loop like
while ( size-- != 0 )
The function adds new elements in the beginning of the list storing in it values of the passed array starting from the last element of the array and down to the first element of the array. .
Pay attention to that the function is unsafe. It can produce memory leaks if some node will not be dynamically allocated due to this if statement
node = malloc(sizeof(*node));
if (!node)
return (NULL);

How to double the size of a dynamic array while keeping the old contents

For part of my C data structures assignment, I am tasked with taking an array of pointers to nodes of 2 doubly linked lists (one representing the main service queue, and the other representing a "bucket" of buzzers ready to be reused or used for the first time in the queue), doubling the size, while keeping the original contents in tact. The idea is that each node has an ID associated which corresponds to the number index of the pointer array map. So for example, the pointer in index 3 will always point to the node whose ID is 3. The boolean inQ is for something unrelated to this issue.
I've written most of the code, but it seems to be functioning incorrectly (it changes all the original pointers to the last node in the list before the array resizing) So, since the starting size of the array is 10 elements, when I print out the contents after the function, it displays 9 9 9 9 9 9 9 9 9 9.
Here are the structs im using:
typedef struct node {
int id;
int inQ;
struct node *next;
struct node *prev;
}NODE;
typedef struct list
{
NODE *front;
NODE *back;
int size;
} LIST;
//referred to as SQ in the separate header file
struct service_queue
{
LIST *queue;
LIST *bucket;
NODE **arr;
int arrSize;
int maxID;
};
Here is the function in question:
SQ sq_double_array(SQ *q)
{
NODE **arr2 = malloc(q->arrSize * 2 * sizeof(NODE*));
int i;
//fill the first half of the new array with the node pointers of the first array
for (i = 0; i < q->arrSize; i++)
{
arr2[i] = malloc(sizeof(NODE));
if (i > 0)
{
arr2[i - 1]->next = arr2[i];
arr2[i]->prev = arr2[i - 1];
}
arr2[i]->id = q->arr[i]->id;
arr2[i]->inQ = q->arr[i]->inQ;
arr2[i]->next = q->arr[i]->next;
arr2[i]->prev = q->arr[i]->prev;
}
//fill the second half with node pointers to the new nodes and place them into the bucket
for (i = q->arrSize; i < q->arrSize * 2; i++)
{
//Point the array elements equal to empty nodes, corresponding to the inidicies
arr2[i] = malloc(sizeof(NODE));
arr2[i]->id = i;
arr2[i]->inQ = 0;
//If the bucket is empty (first pass)
if (q->bucket->front == NULL)
{
q->bucket->front = arr2[i];
arr2[i]->prev = NULL;
arr2[i]->next = NULL;
q->bucket->back = arr2[i];
}
//If the bucket has at least 1 buzzer in it
else
{
q->bucket->back = malloc(sizeof(NODE));
q->bucket->back->next = arr2[i];
q->bucket->back = arr2[i];
q->bucket->back->next = NULL;
}
}
q->arrSize *= 2;
q->arr = arr2;
return *q;
}
Keep in mind this must only be done in c, which is why im not using 'new'
You could use the realloc function:
void *realloc(void *ptr, size_t size);
Quoted from the man pages:
The realloc() function changes the size of the memory block pointed to
by ptr to size bytes. The
contents will be unchanged in the range from the start of the region up to the minimum of the old
and new sizes. If the new size is larger than the old size, the added memory will not be initial‐
ized. If ptr is NULL, then the call is equivalent to malloc(size), for all values of size; if
size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr
is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc(). If the
area pointed to was moved, a free(ptr) is done.

How to initialize an void* pointer from struct

I have a struct Element. When I try to initialize the elements array to NULL,
I get the error: incompatible types when assigning to type Element from type void *.
How to initialize the void * array?
typedef struct _Element Element;
struct _Element {
void* data;
};
typedef struct _ArrayList ArrayList;
struct _ArrayList {
int size;
Element *elements;
};
int main() {
ArrayList *list;
list->size = 100;
list->elements = (Element*)calloc(sizeof(Element), list->size);
for (i = 0; i < list->size; i++) {
/*
* error: incompatible types when assigning to type
* ‘Element’ from type ‘void *’
*/
list->elements[i] = NULL;
}
}
Firstly, you never allocated memory for your list object! Your list pointer is uninitialized and points nowhere. Trying to apply the -> operator to it causes undefined behavior.
I don't know what your final intent is, but it should be either something like
ArrayList *list = malloc(sizeof *list);
list->size = 100;
...
or
ArrayList list;
list.size = 100;
...
Secondly, your void * pointer is actually a named field called data inside Element struct
for(i = 0; i < list->size; i++)
list->elements[i].data = NULL;
Thirdly, becuse you used calloc the memory is already sort of "initialized" with all-zero bit-pattern (including your data fileds). Formally, such bit-pattern in void * is not guaranteed to represent a null pointer, but on most platforms it actually does.
P.S. Don't cast the result of calloc
list->elements = calloc(sizeof(Element), list->size);
or event better
list->elements = calloc(sizeof *list->elements, list->size);
Apart from all the logical errors, the compiler error is the result of trying to assign a value (NULL) to a struct-typed variable. The fact that the struct contains a void * is coincidental. You'd get the same error with:
typedef struct _Element Element;
struct _Element{
int data;
};
Element e;
e = NULL;
This is most likely a mistake from what you intended to do, which is assign a value to the variable inside the struct:
for(i = 0; i < list->size; i++)
list->elements[i].data = NULL;

Creating array of pointers

I need to create an array to pointers of pNodes but when i declare it i dont know the length of the array
lets see what i mean
this is the Node struct
typedef struct _Node {
struct _Node* next;
pElement element;
} Node, *pNode;
this is the Hash struct
typedef struct _Hash {
int hashSize;
pNode *hashTable;
}Hash,*pHash;
now i want each of the
hashTable boxes to point to a pNode
the problem is that i dont know the size of the array, if i did it would be like (i guess)
pNode hashTable[hashSize]
the way i wrote it and tried to resett all boxes to NULL:
this is the CODE:
allocation memory:
pHash hash = (pHash)(malloc(sizeof(Hash)));
hash->hashTable = (pNode)(malloc(sizeof(pNode) * size));
hash->hashSize = size;
resetHashTable(hash->hashTable, size); // reseting the array to NULLS
the func:
static void resetHashTable(pNode *hashTable, int size) {
int i;
for (i = 0; i < size; i++) {
hashTable[i] = (pNode)NULL;
}
}
one of the many many errors i get from the program is (the first error)
hash.c:37:18: warning: assignment from incompatible pointer type [enabled by default]
hash->hashTable = (pNode)(malloc(sizeof(pNode) * size));
can i have some pointers how i need to write it?
If this is not C++ just don't cast malloc, you have an error in this line
hash->hashTable = (pNode)(malloc(sizeof(pNode) * size));
It could be
hash->hashTable = (pNode *)(malloc(sizeof(pNode) * size));
// ^ hashTable is declared pNode *
A better solution would be
hash->hashTable = malloc(sizeof(pNode) * size);
You are declared the pNode as a pointer. Then in Hash structure You are declared the pNode * hastable So you have to use the double pointer **. Or else make that as single pointer in hash structure.
hash->hashTable = (pNode*)(malloc(sizeof(pNode) * size));

function argument a pointer array (C)

in my code I have a array of pointers, where the pointers point to my struct
struct Container *bucket[sizeOfHashMap];
I have a function that will return 1 of these array pointers (e.g it may return the pointer at array index 6). As an argument it wants a pointer to this pointer. The function can be seen here:
struct Container* getWhichBucket(char word[], struct Container **bucket[10]){
int value = 0;
int i = 0;
int size = strlen(word);
int hashIndex = 0;
for(i =0; i < size; i++){
value += (int)word[i];
}
//size of array is worked out by getting memory that array takes up / a slot
hashIndex = value % sizeOfHashMap;
return *bucket[hashIndex];
}
I call the function like this (where test is an array of characters)
addToBucket(test, getWhichBucket(test, &bucket));
the add to bucket looks like this:
void addToBucket(char word[], container **bucket){
container *temp = (struct Container*)malloc (sizeof(struct Container));
strcpy(temp->key, word);
temp->value = 9001;
temp->next = *bucket;
*bucket = temp;
return;
}
However the compiler issues warnings when I compile the code and when I run it I get a segmentation error. Does anyone know why? The warnings can be seen here:
cw.c: In function ‘main’:
cw.c:86:2: warning: passing argument 2 of ‘getWhichBucket’ from incompatible pointer type [enabled by default]
cw.c:37:19: note: expected ‘struct Container ***’ but argument is of type ‘struct Container * (*)[(long unsigned int)(sizeOfHashMap)]’
cw.c:86:2: warning: passing argument 2 of ‘addToBucket’ from incompatible pointer type [enabled by default]
cw.c:56:6: note: expected ‘struct container **’ but argument is of type ‘struct Container *’
addToBucket(test, getWhichBucket(test, &bucket));
is passing a
struct Container *(*)[10]
to getWhichBucket. That's the wrong type, as the compiler says.
You can fix the prototype and implementation
struct Container* getWhichBucket(char word[], struct Container *(*bucket)[10]){
int value = 0;
int i = 0;
int size = strlen(word);
int hashIndex = 0;
for(i =0; i < size; i++){
value += (int)word[i];
}
//size of array is worked out by getting memory that array takes up / a slot
hashIndex = value % sizeOfHashMap;
return (*bucket)[hashIndex];
}
or change the call, but there's no easy way to get a struct Container **bucket[10] from a struct Container *bucket[10], so then you'd probably still want to change the type and implementation of getWhichBucket.
Since you're not modifying the bucket argument there, there's no need to pass the address, you can simply pass the struct Container *bucket[10] directly,
struct Container* getWhichBucket(char word[], struct Container *bucket[]){
int value = 0;
int i = 0;
int size = strlen(word);
int hashIndex = 0;
for(i =0; i < size; i++){
value += (int)word[i];
}
//size of array is worked out by getting memory that array takes up / a slot
hashIndex = value % sizeOfHashMap;
return bucket[hashIndex];
}
and call
addToBucket(test, getWhichBucket(test, bucket));
You need to change your declaration of addToBucket from
void addToBucket(char word[], container *bucket)
{
container *temp = (struct Container)malloc (sizeof(struct Container));
strcpy(temp->key, word);
temp->value = 9001;
temp->next = *bucket;
*bucket = temp;
return;
}
to
void addToBucket(char word[], Container *bucket)
{
Container *temp = malloc (sizeof(struct Container));
strcpy(temp->key, word);
temp->value = 9001;
temp->next = *bucket;
*bucket = temp;
return;
}
Note the change in case for Container -- case matters in C... container is not the same thing as Container.
Also... note... you should not cast malloc in C.

Resources