c pointers to struct issue - c

Would someone please help me with thhis c pointers issue. It seems to me like it should work but there must be something im not understanding as the code doesnt compile. On the line where is says this: ERROR<<<<>>>>>>>>. I think the problem is with function getDynArr which is at the tag: GETDYNARR<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>. I think getDynArr(da, i) may be returning int for some reason?
/* dynArr.c: Dynamic Array implementation. */
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#ifndef KEYTYPE
#define KEYTYPE char *
#endif
#ifndef VALUETYPE
#define VALUETYPE double
#endif
#ifndef TYPE
#define TYPE struct association
//# define TYPE int
#endif
struct association
{
KEYTYPE key;
VALUETYPE value;
};
struct DynArr
{
TYPE *data; /* pointer to the data array */
// struct association *data;
int size; /* Number of elements in the array */
int capacity; /* capacity ofthe array */
};
///////////////////dictionary Section
void dyArrayDictionaryPut(struct DynArr *vec, KEYTYPE key, VALUETYPE val)
{
struct association *ap;
if (dyArrayDictionaryContainsKey(vec,key))
dyArrayDictionaryRemove(vec, key);
ap = malloc(sizeof(struct association));
assert(ap != 0);
ap->key = key;
ap->value = val;
//dyArrayAdd(vec, ap);
addDynArr(vec, ap);
}
VALUETYPE dyArrayDictionaryGet(struct DynArr *da, KEYTYPE key, VALUETYPE *valptr)
{
struct association *ap;
int i = 0;
if(dyArrayDictionaryContainsKey(da, key))
{
for ( i = 0; i < da->size; i++)
{
//if(da->data[i]->key == key)
if(da->data[i].key == key)
{
//return da->data->value;
struct association temp3;
temp3 = getDynArr(da, i); //ERROR<<<<<ERROR>>>>>>>>>incompatible types when assigning to type 'struct association' from type 'int'
//ap = getDynArr(da, i);
//*valptr = ap->value;
}
}
}
}
int dyArrayDictionaryContainsKey(struct DynArr *da, KEYTYPE key)
{
int i = 0;
for (i = 0; i < da->size; i++)
{
if(da->data[i].key == key)
{
return 1;
}
}
return 0;
}
void dyArrayDictionaryRemove(struct DynArr *da, KEYTYPE key)
{
for (int i = 0; i < da->size; i++)
{
if(da->data[i].key == key)
{
removeAtDynArr(da, i);
return;
}
}
}
////
void _initDynArr(struct DynArr *v, int capacity)
{
assert(capacity > 0);
assert(v!= 0);
v->data = malloc(sizeof(TYPE) * capacity);
assert(v->data != 0);
v->size = 0;
v->capacity = capacity;
}
struct DynArr* createDynArr(int cap)
{
struct DynArr *r;
assert(cap > 0);
r = malloc(sizeof( struct DynArr));
assert(r != 0);
_initDynArr(r,cap);
return r;
}
void freeDynArr(struct DynArr *v)
{
assert(v!=0);
if(v->data != 0)
{
free(v->data); /* free the space on the heap */
v->data = 0; /* make it point to null */
}
v->size = 0;
v->capacity = 0;
}
void deleteDynArr(struct DynArr *v)
{
assert (v!= 0);
freeDynArr(v);
free(v);
}
void _dynArrSetCapacity(struct DynArr *v, int newCap)
{
int i;
TYPE *oldData;
int oldSize = v->size;
oldData = v->data;
printf("========Resizing========\n");
/* Create a new dyn array with larger underlying array */
_initDynArr(v, newCap);
for(i = 0; i < oldSize; i++){
v->data[i] = oldData[i];
}
v->size = oldSize;
/* Remember, init did not free the original data */
free(oldData);
#ifdef ALTERNATIVE
int i;
/* Create a new underlying array*/
TYPE *newData = (TYPE*)malloc(sizeof(TYPE)*newCap);
assert(newData != 0);
/* copy elements to it */
for(i = 0; i < v->size; i++)
{
newData[i] = v->data[i];
}
/* Delete the oldunderlying array*/
free(v->data);
/* update capacity and size and data*/
v->data = newData;
v->capacity = newCap;
#endif
}
int sizeDynArr(struct DynArr *v)
{
assert(v!=0);
return v->size;
}
void addDynArr(struct DynArr *v, TYPE val)
{
assert(v!=0);
/* Check to see if a resize is necessary */
if(v->size >= v->capacity)
_dynArrSetCapacity(v, 2 * v->capacity);
v->data[v->size] = val;
v->size++;
}
//GETDYNARR<<<<<<<<<<<<<<<<<<<<<GETDYNARR>>>>>>>>>>>>>>>>>
//type is struct association
//TYPE getDynArr(struct DynArr *v, int pos )
struct association getDynArr(struct DynArr *v, int pos)
{
assert(v!=0);
assert(pos < v->size);
assert(pos >= 0);
struct association returned = v->data[pos];
return returned;
}
void putDynArr(struct DynArr *v, int pos, TYPE val)
{
assert(v!=0);
assert(pos < v->size);
assert(pos >= 0);
v->data[pos] = val;
}
void swapDynArr(struct DynArr *v, int i, int j)
{
TYPE temp;
assert(v!=0);
assert(i < v->size);
assert(j < v->size);
assert(i >= 0);
assert(j >= 0);
temp = v->data[i];
v->data[i] = v->data[j];
v->data[j] = temp;
}
void removeAtDynArr(struct DynArr *v, int idx){
int i;
assert(v!= 0);
assert(idx < v->size);
assert(idx >= 0);
//Move all elements up
for(i = idx; i < v->size-1; i++){
v->data[i] = v->data[i+1];
}
v->size--;
}
int main()
{
// struct DynArr *dictionary = createDynArr(2);
// dyArrayDictionaryPut(dictionary, "key1", 2);
//double result = dyArrayDictionaryGet(dictionary, "key1");
//dyArrayDictionaryContainsKey(struct DynArr *da, KEYTYPE key)
//dyArrayDictionaryRemove(struct DynArr *da, KEYTYPE key)
//printf("%f\n",result);
}

getDynArr is not declared before it is used, the declaration is further down in the file. The compiler should warn you about that.
Since the getDynArr is undeclared, the compiler doesn't know what parameters it takes or what it returns. The compiler then assumes some defaults, like a return type int, which leads to the error you're seeing.
To fix the problem, declare the function before you try to use it.

I'm not going to discuss the implementation as you haven't asked for it.
In order to compile you'll need to fix the following:
Missing function declarations for: getDynArr, dyArrayDictionaryRemove, dyArrayDictionaryContainsKey, addDynArr, removeAtDynArr; So you need to add the function signature just below the struct declarations, like:
struct association
{
KEYTYPE key;
VALUETYPE value;
};
struct DynArr
{
TYPE *data; /* pointer to the data array */
// struct association *data;
int size; /* Number of elements in the array */
int capacity; /* capacity ofthe array */
};
///////////////////dictionary Section
struct association getDynArr(struct DynArr *v, int pos);
void dyArrayDictionaryRemove(struct DynArr *da, KEYTYPE key);
int dyArrayDictionaryContainsKey(struct DynArr *da, KEYTYPE key);
void addDynArr(struct DynArr *v, TYPE val);
void removeAtDynArr(struct DynArr *v, int idx);
...
inside the function dyArrayDictionaryPut you need to call addDynArr passing the struct by value according to the function signature, so the call at line 54 would be:
addDynArr(vec, *ap);
You need to compile it as c99 code, otherwise you need to remove the variable initialization on every for loop (the gcc option is -std=c99 for instance);
Then let me give you a couple of suggestions you may find useful:
You may want to consider using typedef instead of define to create an alias for the struct association;
typedef struct
{
KEYTYPE key;
VALUETYPE value;
} association;
Then at this point you can use "association" as a type without the needs to mention it is a struct anymore (I guess you can find a better name for it as well);
Depending on the performance requirements, you may need to avoid returning or passing the struct by value around, using a pointer is much faster.

Related

cast from pointer to integer of different size [-Wpointer-to-int-cast] in linux

someone help me please i am stucked at this pointed at line 75,96,133 i am getting error warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
when at line 96 i replaced int with long then it resolved the issue but for other two it is still same someone please explain me what i am doing wrong here?
#include <linux/module.h>
#include <linux/list.h>
#include <linux/slab.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("WaSi");
int init(void);//initialization
int hashFunc(int);//Hash function
void addAllNodes(int[]);//Add all keyword nodes
void showAllNodes(void);//Print all keyword nodes
int search(int);//Query node address based on keywords
//Hash table length and hash remainder
#define N 8
//Keyword array length
#define LENGTH 20
//Node structure
struct hlist_data {
int key;
struct hlist_node hNode;
};
struct hlist_head* head;
//Initialize, apply for memory
int init(void) {
int index;
head = (struct hlist_head*)kmalloc(sizeof(struct hlist_head) * N, GFP_KERNEL);
if (!head) return 0;
printk("\nStart initializing the hash table!\n");
for (index = 0; index < N; index++) {
INIT_HLIST_HEAD(&head[index]);
}
return 1;
}
//The simplest hash function-remainder
int hashFunc(int key) {
return key % N;
}
//Insert all keyword nodes
void addAllNodes(int array[]) {
int index;
int i;
int hashAddr;//Address;
struct hlist_data* hd;
for (index = 0, i = 1; index < LENGTH; index++) {
//Apply for memory for keyword nodes
hd = (struct hlist_data*)kmalloc(sizeof(struct hlist_data), GFP_KERNEL);
INIT_HLIST_NODE(&(hd->hNode));
hd->key = array[index];
printk("Add node%d-----%d!\n", i++, array[index]);
//Keyword gets the hash address according the hash function
hashAddr = hashFunc(array[index]);
hlist_add_head(&(hd->hNode), &(head[hashAddr]));//Head insertion method
}
}
// Traverse and print all nodes
void showAllNodes(void) {
int index;
struct hlist_data* hd;
struct hlist_node* pos;
printk("\ntraversal print!\n");
//Loop array
for (index = 0; index < N; index++) {
printk("%d\n", index);
//Circular singly linked list
hlist_for_each(pos, &(head[index])) {
//Find out the first address of the linked list node pointed by pos
hd = hlist_entry(pos, struct hlist_data, hNode);
**printk("%d(%d)->", hd->key, int pos);**
}
printk("NULL");
printk("\n");
}
}
//Find the node address based on keywords
int search(int searchKey) {
int hashAddr;
struct hlist_data* hd;
struct hlist_node* pos;
printk("finding %d!\n", searchKey);
//Find the address
hashAddr = hashFunc(searchKey);
printk("According the hash function obtain the address=%d!\n", hashAddr);
hlist_for_each(pos, &(head[hashAddr])) {
hd = hlist_entry(pos, struct hlist_data, hNode);
**if (hd->key == searchKey) return (long)pos;**
}
return -1;
}
static int __init hlist_init(void) {
int keys[LENGTH] = { 1,2,3,4,5,6,7,16,18,20,31,44,47,51,55,60,66,69,72,73 };// A set of keywords
int addr;//Used when searching
int searchKey;
//Initialization
if (!init()) return -1;
//Insert the node as a hash function according the simple remainder
addAllNodes(keys);
//Print all nodes
showAllNodes();
//Give keywords
searchKey = 19;
addr = search(searchKey);
if (addr == -1) printk("Search failed\n\n");
else printk("Find the node address with key %d is %d\n\n", searchKey, addr);
return 0;
}
static void __exit hlist_exit(void) {
int index;
int i;
struct hlist_data* hd;
struct hlist_node* pos, * n;
for (index = 0, i = 1; index < N; index++) {
//The traversal here needs be safe
hlist_for_each_safe(pos, n, &(head[index])) {
hd = hlist_entry(pos, struct hlist_data, hNode);
**printk("Delete node%d-----%d, the address is%d\n", i++, hd->key, int pos);**
hlist_del(pos);
kfree(hd);
}
}
kfree(head);
printk("Deletion is complete!\n");
}
module_init(hlist_init);
module_exit(hlist_exit);

Implementing a generic arraylist in C [duplicate]

This question already has an answer here:
Making a generic ArrayLIst in C
(1 answer)
Closed 2 years ago.
I am trying to implement a java-like arraylist in C and now I am trying to make it generic. I am new to C and pointer arithmetic but I tried using void* pointer for container, then element size(for size of data type), capacity and size. I am trying to debug my code and it is giving a random value on the screen.
I cant seem to find what is wrong with my add method ? and how should I go about the printlist method as we are not sure about the data type. I think my printLIst is wrong.
I am new to C and playing around for educational purposes and any help is appreciated. Thank you
____________________________________________________________________
#ifndef ARRAYLIST_H
#define ARRAYLIST_H
typedef struct ArrayList ArrayList;
typedef int bool;
#define false 0
#define true 1
struct ArrayList {
void *con;
int elementSize;
int numElements;
int conSize;
};
ArrayList *createArrayList(int );
int remove(ArrayList *, int);
void freeArrayList(ArrayList *);
int add(ArrayList *, void*);
void *getAtIndex(ArrayList *, int);
void printList(ArrayList *);
void resize(ArrayList *);
bool isEmpty(ArrayList*);
int getNumElements(ArrayList*);
int getConSize(ArrayList*);
#endif
_______________________________________________________________________
#include<stdio.h>
#include<stdlib.h>
#include"Consts.h"
#include<memory.h>
#include "ArrayList.h"
#define CAPACITY 5
#define EXTRA 100
ArrayList *createArrayList(int elementSize) {
ArrayList *arrayList = malloc(sizeof(ArrayList));
arrayList->elementSize = elementSize;
arrayList->conSize = CAPACITY;
arrayList->numElements = 0;
arrayList->con = malloc(elementSize * CAPACITY);
return arrayList;
}
void freeArrayList(ArrayList * arrayList) {
if (arrayList == NULL) {
return;
}else {
free(arrayList->con);
free(arrayList);
}
}
int add(ArrayList *list, void *input) {
if (list != NULL && input != NULL) {
if (list->numElements >= list->conSize) {
resize(list);
printf("resized\n");
}
list->con = input;
memcpy((char*)list->con + (list->numElements*list->elementSize), input, list->elementSize);
list->numElements++;
return 1;
}
return -1;
}
void resize(ArrayList *list) {
void *temp = realloc(list->con, (list->conSize + EXTRA) * list->elementSize);
if (temp != NULL) {
list->conSize += 100;
list->con = temp;
}
}
int remove(ArrayList * list, int i) {
if (list != NULL) {
//find index of value to remove
int elementSize = list->elementSize;
int lenToMove = elementSize * (list->numElements - (i + 1));
memmove((char *)list->con + i*elementSize, (i+1)*elementSize, lenToMove);
list->numElements--;
return 1;
}
return -1;
}
void printList(ArrayList *list) {
if (list != NULL) {
char *p = list->con;
for (int i = 0; i < list->numElements; i++) {
void* val = getAtIndex(list, i);
printf("%d \n", val);
}
}
}
void *getAtIndex(ArrayList *listptr, int index) {
return (char*)listptr->con + index * (listptr->elementSize);
}
int getNumElements(ArrayList * list) {
return list->numElements;
}
int getConSize(ArrayList * list) {
return list->conSize;
}
bool isEmpty(ArrayList * list) {
return list->numElements == 0;
}
___________________________________________________
#include<stdio.h>
#include<stdlib.h>
#include"ArrayList.h"
#include "Consts.h"
#pragma warning(disable : 4996)
int main() {
ArrayList * list = createArrayList(sizeof(int));
int x = 5;
add(list, &x);
printf("%d",(int *)getAtIndex(list, 0));
freeArrayList(list);
system("pause");
return 0;
}
Pay attention to the comments above. I know you're new to the site, but it's worth while getting to know how it works.
Anyway the problem is in this line of code:
printf("%d",(int *)getAtIndex(list, 0));
getAtIndex() returns a pointer so you need to dereference it to get the value. It should be:
printf("%d",*(int *)getAtIndex(list, 0));

Generic ArrayList in C

I have made a Java like ArrayList class in C for educational purposes however currently it is only good for integers. I want to make it Generic so it can take any type of data. How do I go about it. I read somewhere about creating a typedef void pointer. Any thoughts ?
........................................................................................................
Here is My code
#ifndef ARRAYLIST_H
#define ARRAYLIST_H
typedef struct ArrayList ArrayList;
typedef int bool;
#define false 0
#define true 1
struct ArrayList {
int *con;
int numElements;
int conSize;
};
ArrayList *createArrayList();
void freeArrayList(ArrayList *);
void add(ArrayList *, int);
void printList(ArrayList *);
void resize(ArrayList *);
int remove(ArrayList *, int);
bool isEmpty(ArrayList*);
int getNumElements(ArrayList*);
int getConSize(ArrayList*);
#endif
_____________________________________
#include<stdio.h>
#include<stdlib.h>
#include"Consts.h"
#include "ArrayList.h"
#define CAPACITY 5
ArrayList *createArrayList() {
ArrayList *arrayList = malloc(sizeof(ArrayList));
arrayList->conSize = CAPACITY;
arrayList->numElements = 0;
arrayList->con = malloc(sizeof(int) * CAPACITY);
return arrayList;
}
void freeArrayList(ArrayList * arrayList) {
if (arrayList == NULL) {
return;
}else {
free(arrayList->con);
free(arrayList);
}
}
void add(ArrayList *arrayList, int input) {
//printf("Num elements in add method before adding %d \n", arrayList->numElements);
if (arrayList->numElements >= arrayList->conSize) {
resize(arrayList);
printf("resized\n");
}
int size = arrayList->numElements;
//add element to the last
arrayList->con[size] = input;
arrayList->numElements = arrayList->numElements + 1
}
void resize(ArrayList *arrayList) {
int num = arrayList->numElements;
int oldSize = arrayList->conSize;
int newSize = oldSize + 50;
int *temp = realloc(arrayList->con, sizeof(type) * newSize);
if (temp != NULL) {
arrayList->con = temp;
arrayList->conSize = newSize;
}
}
int remove(ArrayList * arrayList, int val) {
int i = 0;
while (arrayList->con[i] != val) {
i++;
}
//remove this index
if (i == arrayList->conSize) {
return -1;
}
else {
int removedVal = arrayList->con[i]; int j;
for (j = i; j < arrayList->numElements ; j++) {
arrayList->con[j] = arrayList->con[j + 1];
}
arrayList->con[j + 1] = NULL;
arrayList->numElements = arrayList->numElements - 1;
return removedVal;
}
}
If you want the array list be able to store any type of data, you need to
1) make con a void pointer. void *con;
2) store additional metadata in the struct about the memory alignment of the type
3) add one more parameter to the constructor of array list, which is the additional metadata mentioned in 2)
4) when allocating memory, use the stored metadata instead of sizeof(whatever), like temp=malloc(stored_metadata_about_type*50);
Also notice that it is not usually a good idea to hardcode 50, and better declare it as a constant like buffer_size.

Hash table init_hash in c

I need to initialized the hash table with the size i get, i have a problem here t->arr_table[i]->key = NULL;
#include <stdio.h>
typedef struct element{
char * key;
char * value;
}element;
typedef struct HashTable{
int size; // size of the arr
element **arr_table; //arr of elements
}HashTable;
void init_hash(int size, HashTable * t)
{
if (size < 1)
return;
t->size = size;
t->arr_table = (element **)malloc(sizeof(element*)*size);
if (t->arr_table == NULL) // out memory
return;
int i;
for (i = 0; i < size; i++)
{ // initial list
t->arr_table[i]->key = NULL;
t->arr_table[i]->value = NULL;
}
}
void main()
{
HashTable *ht = (HashTable*)malloc(1*sizeof(HashTable));
int size_ht = 9;
init_hash(size_ht, ht);
printf("...\n");
return;
}
What you've made is an array of pointers to elements. However, the init_hash function seems to expect an array of elements. To create an array of elements the code should be as shown below. I've added some comments to highlight some of the changes.
typedef struct element{
char *key;
char *value;
}element;
typedef struct HashTable{
int size;
element *arr_table; // <-- only one '*', not two, to declare a pointer to an array of elements
}HashTable;
void init_hash(int size, HashTable *t)
{
if (size < 1)
return;
t->size = size;
t->arr_table = malloc(sizeof(element) * size); // <-- allocate memory for the elements, note 'sizeof(element)' not 'sizeof(element *)'
if (t->arr_table == NULL)
return;
int i;
for (i = 0; i < size; i++)
{
t->arr_table[i].key = NULL; // <-- table[i] is a structure, use dot notation
t->arr_table[i].value = NULL;
}
}
int main( void ) // <-- declare main with the correct signature
{
HashTable *ht = malloc(sizeof(HashTable)); // <-- don't cast the return value from malloc
int size_ht = 9;
init_hash(size_ht, ht);
printf("...\n");
}

Having issues with element assignment using TYPE

I am attempting to utilize TYPE for a generic array and don't seem to be getting the syntax quite right. I can get the code to work using int, but when I convert to TYPE the statement assigning values stops working.
Here is my Array creation:
struct DynArr
{
TYPE *data; /* pointer to the data array */
int size; /* Number of elements in the array */
int capacity; /* capacity ofthe array */
};
void initDynArr(DynArr *v, int capacity)
{
assert(capacity > 0);
assert(v!= 0);
v->data = (TYPE *) malloc(sizeof(TYPE) * capacity);
assert(v->data != 0);
v->size = 0;
v->capacity = capacity;
}
DynArr* createDynArr(int cap)
{
assert(cap > 0);
DynArr *r = (DynArr *)malloc(sizeof( DynArr));
assert(r != 0);
initDynArr(r,cap);
return r;
}
And here is my call to modify:
void addDynArr(DynArr *v, TYPE val)
{
/* Add Element */
*v->data = val;
v->size++;
}
The code is compiling, but val is not being assigned to the data fields.
Edit: In my test case I am passing TYPE as a double.
Test Function calls:
addDynArr(dyn, 3);
addDynArr(dyn, 4);
When Running the following val is reporting as 0:
printf("Val: %d ", val)
/* Add Element */
v->data[v->size] = val;
v->size++;
Your implementation of addDynArr() is wrong. You are always assigning val to the first element of data, not to the next available element at the end of data. It needs to look more like this instead:
void addDynArr(DynArr *v, TYPE val)
{
if (v->size < v->capacity)
{
/* Add Element */
v->data[v->size] = val;
v->size++;
}
}

Resources