I have 2 structures in my C code. I want to write a hash function with these 2 structures. So I want to initialize my data null in first case. My code is
struct HashNode
{
char username[20];
char password[20];
};
struct HashTable
{
int size;
struct HashNode *table;
};
HashTable *initializeTable(int size)
{
HashTable *htable;
if (size < MIN_TABLE_SIZE)
{
printf("Table Size Small\n");
return NULL;
}
htable = (HashTable *)malloc(sizeof(Hashtable));
if (htable == NULL)
{
printf("memory allocation pblm\n");
return NULL;
}
htable->size = size;
}
How can I allocate memory for htable->table with that size? I have code in C++ like htable->table = new HashNode [htable->size];. How can I write this in C using malloc?
You can allocate the memory in this way
htable->table = malloc(size*sizeof(HashNode))
Related
I have this hashmap I want to implement.
typedef void * Data;
typedef struct {
Data data; //Data pointer to the data
char * key; //char pointer to the string key
} HashMapItem;
typedef struct hashmap {
HashMapItem * items; //items of the hashmaps
size_t size; //size of the hashmaps
int count; //how many elements are in the hashmap
} HashMap;
I declare it like so:
HashMap * create_hashmap(size_t key_space){
if(key_space == 0)
return NULL;
HashMap * hm = malloc(sizeof(HashMap)); //allocate memory to store hashmap
hm->items = calloc(key_space, sizeof(HashMapItem)); //allocate memory to store every item inside the map, null it
hm->size = key_space; //set sitze of hashmap
hm->count = 0; //empty at the begining
return hm;
}
When i try to iterate through it, it says that
expression must have arithmetic or pointer type but has type "HashMapItem" even though i declare it as a pointer of HashMapItems
if((hm->items)[index] != NULL)
Any idea?
typedef void * Data;
Never hide pointers behind typedefs. It is a very, very bad practice.
How to iterate.
typedef struct {
void *data; //Data pointer to the data
char * key; //char pointer to the string key
} HashMapItem;
typedef struct hashmap {
HashMapItem * items; //items of the hashmaps
size_t size; //size of the hashmaps
size_t count; //how many elements are in the hashmap
} HashMap;
void foo(HashMap *map)
{
for(size_t i = 0; i < map -> count; i ++)
{
puts(map -> items[i].key);
}
}
PS count member should be also size_t
EDIT. Below is wrong as hm->items)[index] has type HashMapItem and it is not pointer. You cant compare it to NULL.
if((hm->items)[index] != NULL)
I'm trying to implement a simple hash table in C, where I have two structures, one for the entries, and one for the table itself:
typedef struct hash_table_entry {
int key;
int data;
struct hash_table_entry *next;
} HT_ENTRY;
typedef struct hash_table {
int size;
int entry_count;
HT_ENTRY **table;
} HT;
My mallocs when creating the table:
if ((ht_table = (HT*)malloc(sizeof(HT))) == NULL)
return NULL;
if ((ht_table->table = (HT_ENTRY**)malloc(size * (sizeof(HT_ENTRY*)))) == NULL)
return NULL;
for (i = 0; i < size; i++) {
if ((ht_table->table[i] = (HT_ENTRY*)malloc(sizeof(HT_ENTRY))) == NULL)
return NULL;
}
When allocating the table, my second malloc doesn't create the array of pointers in the desired size I would like him to do: pic of debugger
Why does my malloc do this and what would be the correct syntax?
You are allocating individual entries in the hash table but there is no data associated to these entries, indeed they are uninitialized, causing undefined behavior when you try and use the hash table. You should instead just initialize the array of pointers pointed to by ht_table->table with NULL pointers:
ht_table->size = size;
ht_table->entry_count = 0;
for (i = 0; i < size; i++) {
ht_table->table[i] = NULL;
}
Or simply allocate the array with calloc():
ht_table->size = size;
ht_table->entry_count = 0;
if ((ht_table->table = (HT_ENTRY**)calloc(size, sizeof(HT_ENTRY*))) == NULL)
return NULL;
Also not that in C, casting the return value of malloc and calloc is not required. A safer way to allocate the array is:
if ((ht_table->table = calloc(size, sizeof(*ht_table->table))) == NULL)
return NULL;
I am reading the script on the implementation of malloc (first-fit), and I am a little confused about the value assignment of metadata structure. Could anyone give some explanations why the malloc returns flag_block->ptr (as a pointer to the allocated memory)? As far as I can see, there is no specific assignment to it.
typedef struct _metadata {
size_t size;
char free;
struct _metadata* next;
struct _metadata* prev;
char ptr[];
} metadata;
metadata* flag_block = NULL;
void *malloc(size_t size)
{
if (size==0) {
return NULL;
}
if (flag_block == NULL) {
flag_block = sbrk(size);
sbrk(sizeof(metadata));
if (flag_block == (void *)-1) {
return NULL;
}
flag_block->free = 0;
flag_block->next=NULL;
flag_block->prev=NULL;
flag_block->size = size;
return flag_block->ptr;
} else {
/*
....
*/
}
}
The ptr is called a flexible array member; it's an array without a size, and can only appear at the end of a struct.
So basically this:
return flag_block->ptr;
is equivalent to
return &flag_block->ptr[0];
So it's returning the address of the first byte after the rest of the members in the struct.
typedef struct {
List *table;
unsigned int size;
} HashTable;
typedef struct node {
Data data;
struct node *next;
} NODE;
struct listptrs {
NODE *tail;
NODE *head;
NODE *prev;
NODE *current;
};
typedef struct listptrs List;
HashTable createHashTable(unsigned int size) {
//HashTable htable = { 0 };
//return htable;
int i;
HashTable *htable = NULL;
htable = malloc(sizeof(HashTable) * size);
for (i = 0; i < size; i++) {
htable[i].table = malloc(sizeof(List));
htable[i].table->current = NULL;
htable[i].table->head = NULL;
htable[i].table->prev = NULL;
htable[i].table->tail = NULL;
htable[i].size = size;
}
return *htable;//???
}
Then in main:
HashTable htable = createHashTable(tableSize);
htable doesn't act like an array at all. Any ideas how to solve it without changing any return value from the function and arguments for functions? This is part of a school assignment and only the contents of the function createHashTable may be changed. The rest of the program is not here because it isn't relevant to the question.
You maybe want this:
HashTable *createHashTable(unsigned int size)
{
//HashTable htable = { 0 };
//return htable;
int i;
HashTable* htable = NULL;
htable = malloc(sizeof(HashTable)* size);
for(i=0; i<size; i++)
{
htable[i].table = malloc(sizeof(List));
htable[i].table->current = NULL;
htable[i].table->head = NULL;
htable[i].table->prev = NULL;
htable[i].table->tail = NULL;
htable[i].size = size;
}
return htable;
}
As you allocate the array dynamically, you can simply return the newly allocated pointer. Returning a HashTable as you were trying doesn't make senses, because this would allow you to return one single HashTable, but you want to return a whole array of HashTables.
Usage:
Instead of:
HashTable htable = createHashTable(tableSize);
You need this:
HashTable *htable = createHashTable(100);
...
... // when done you need to delete the hashtable
deleteHashTable(htable);
The deleteHashTable is yet to be written, It essentially needs to free the table pointer and to free the table itself.
Now if you really are allowed to change only the contents of the createHashTable function but not the function signature, then your question doesn't make sense because with the function signature HashTable createHashTable(unsigned int size) you can only return one HashTable but not an array of HashTables.
But then maybe you actually want this:
HashTable createHashTable(unsigned int size)
{
HashTable htable = { 0 };
int i;
for(i=0; i<size; i++)
{
htable[i].table = malloc(sizeof(List));
htable[i].table->current = NULL;
htable[i].table->head = NULL;
htable[i].table->prev = NULL;
htable[i].table->tail = NULL;
htable[i].size = size;
}
return htable;
}
With this second solution, you still need to write the function that deletes the hash table.
The hash table itself isn't supposed to "behave like an array", and this:
return *htable;
makes no sense, it returns the first element from your array of hash tables.
You're not supposed to create an array of hash tables though, you're supposed to create a single hash table, which might contain an array (that's the table). It also has a size variable for instance, so there's more than the array itself to the hash table.
You should do
htable = malloc(sizeof *htable);
to allocate a single instance, then initialize that as needed and return it.
There seems to be some confusion here: createHashTable() is not supposed to allocate an array of hash tables, but a HashTable structure with an initial size for its embedded table member.
Furthermore, it is non standard practice to return the structure by value. You should instead return the pointer to the allocated HashTable or possibly take a pointer to HashTable structure allocated dynamically or statically by the caller and initialize that.
Here is a modified version of the code for this approach:
#include <stdlib.h>
typedef struct {
List *table;
unsigned int size;
} HashTable;
typedef struct node {
Data data;
struct node *next;
} NODE;
struct listptrs {
NODE *tail;
NODE *head;
NODE *prev;
NODE *current;
};
typedef struct listptrs List;
HashTable *createHashTable(unsigned int size) {
HashTable *htable = malloc(sizeof(*htable));
if (htable == NULL)
return NULL;
}
htable->size = size;
htable->table = NULL;
if (size == 0) {
return htable;
}
htable->table = malloc(sizeof(*htable->table) * size);
if (htable->table == NULL) {
free(htable);
return NULL;
}
for (unsigned int i = 0; i < size; i++) {
htable->table[i].head = NULL;
htable->table[i].tail = NULL;
htable->table[i].prev = NULL;
htable->table[i].current = NULL;
}
return htable;
}
Calling from main():
HashTable *htable = createHashTable(100);
I'm learning hashtable data structures and I want to make a hashtable with a flexible length array of pointers to struct Link (linked list pieces), so that hashtable initialization will set the array to be a length input into the initialization function.
At first I was getting the error "flexible array not at the end of struct". When its at the end (as shown) the program crashes (but it still compiles). This is my code:
typedef struct Link{
int key;
char *name;
struct Link *next;
} Link;
typedef struct HashTable{
int numberOfEntries;
int numberOfBuckets;
Link *Table[];
} HashTable;
HashTable *hashtableInit(int size){
HashTable *newHT = malloc(sizeof(HashTable));
if (newHT != NULL){
newHT->numberOfEntries = 0;
newHT->numberOfBuckets = size;
for (int i = 0; i < newHT->numberOfBuckets; i += 1){
newHT->Table[i] = NULL;
}
return newHT;
} else {
printf("Error in memory allocation.\n");
fflush(stdout);
return NULL;
}
}
}
It works if I set the array to a constant and input the same value into the init function:
#define SIZE 11
typedef struct Link{
int key;
char *name;
struct Link *next;
} Link;
typedef struct HashTable{
Link *Table[SIZE];
int numberOfEntries;
int numberOfBuckets;
} HashTable;
HashTable *hashtableInit(int size){ // works if SIZE is passed into function as size parameter
HashTable *newHT = malloc(sizeof(HashTable));
if (newHT != NULL){
newHT->numberOfEntries = 0;
newHT->numberOfBuckets = size;
for (int i = 0; i < newHT->numberOfBuckets; i += 1){
newHT->Table[i] = NULL;
}
return newHT;
} else {
printf("Error in memory allocation.\n");
fflush(stdout);
return NULL;
}
}
}
The second code block works perfectly. Any insights would be greatly appreciated. Thanks for your time.
Chris
You should allocate memory as
HashTable *newHT = malloc(sizeof *newHT + size * sizeof newHT->Table[0]);
Your
HashTable *newHT = malloc(sizeof(HashTable));
is wrong, because no space is given for the flexible array member. Should probably be
HashTable *newHT = malloc(sizeof(HashTable)+size*sizeof(Link*));