I am trying to implement a generic hashmap in c
but it fails inserting the bucket into the bucket list.
I dont know why the program exits without any error.
Please help me.
I need to use this hashmap for Implementing LRU cache for my cs project.
typedef struct Bucket Bucket;
struct Bucket
{
void *Key;
void *Value;
};
typedef struct HashMap HashMap;
struct HashMap
{
Bucket *BucketList;
size_t Size;
size_t KeySize;
size_t ValueSize;
int Entries;
};
HashMap *insert(HashMap *map, void *key, void *value)
{
if (isOverLoad(map->Entries, map->Size, LOADFACTOR))
{
printf("\nMap is Overloaded.. Rehasing");
map = reHash(map);
}
int bucketindex = hash(map->Size, key);
printf("\nBucket index: %d",bucketindex);
if (map->BucketList[bucketindex].Value != NULL)
{
printf("\nCollision! ");
// printf("%s and %s", (char *)map->BucketList[bucketindex].Key, (char *)key);
}
else
{
printf("\nEntering value");
map->BucketList[bucketindex].Key = malloc(map->KeySize);
for (int i = 0; i < map->KeySize; i++)
{
*(((char *)map->BucketList[bucketindex].Key) + i) = *(((char *)key) + i);
}
map->BucketList[bucketindex].Value = malloc(map->ValueSize);
for (int i = 0; i < map->ValueSize; i++)
{
*(((char *)map->BucketList[bucketindex].Value) + i) = *(((char *)value) + i);
}
map->Entries++;
}
return map;
}
In order to give you a better answer I should see also the code for the the other functions, like reHash().
But I can can give you two suggestions: first check if reHash() failed and therefore map == NULL; if this is not the case, you can try to run the code with valgrind to have a better understanding about what's going on.
Related
I wrote a lightweight dictionary for a quick project with C, and I am getting the error: realloc(): invalid next size. I know this means my heap is corrupted somehow, but I'm not sure what I did wrong, it seems like my code is super simple.
The realloc always fails the fourth access, ie when dict->num_kvs = 4
Below is my code. It includes the dict library as well as the function that is using it. Any help would be much appreciated
Offending function:
int* get_letter_frequencies(char* stream) {
Dict* dict = Dict_initialize();
for(int i = 0; i < strlen(stream); i++) {
Dict_increment_or_add_key(dict, stream[i]);
}
int* to_return = Dict_get_values_array(dict);
Dict_free();
return to_return;
}
simple_dict.c (plus the struct definitions)
typedef struct kv_pair {
char key;
int value;
} KV_Pair;
typedef struct dict_ {
struct kv_pair* kv_pairs;
int num_kvs;
} Dict;
Dict* Dict_initialize() {
Dict* to_return = malloc(sizeof(Dict));
to_return->num_kvs = 0;
to_return->kv_pairs = NULL;
return to_return;
}
void Dict_free(Dict* dict) {
free(dict->kv_pairs);
free(dict);
}
int Dict_add_key(Dict* dict, char key) {
dict->num_kvs++;
printf("next size: %d\n", dict->num_kvs);
dict->kv_pairs = realloc(dict->kv_pairs, dict->num_kvs * sizeof(KV_Pair));
printf("realloc passed \n");
dict->kv_pairs[dict->num_kvs].value = 1;
return 0;
}
int Dict_find_key(Dict* dict, char key){
for(int i = 0; i < dict->num_kvs; i++) {
char cur_key = dict->kv_pairs[i].key;
if(cur_key == key) {
return i;
}
}
return -1;
}
int Dict_increment_or_add_key(Dict* dict, char key) {
int key_index = Dict_find_key(dict, key);
if(key_index == -1) {
Dict_add_key(dict, key);
} else {
dict->kv_pairs[key_index].value++;
}
}
int* Dict_get_values_array (Dict* dict) {
int* to_return = malloc(dict->num_kvs * sizeof(int));
for(int i = 0; i < dict->num_kvs; i++) {
to_return[i] = dict->kv_pairs[i].value;
}
if(dict->num_kvs > 26) {
printf("more than 26 kvs: %d", dict->num_kvs);
}
return to_return;
}
When you try to add the first element, you are incrementing dict->num_kvs to 1, then you allocate a single element. Then this line:
dict->kv_pairs[dict->num_kvs].value = 1;
It will try to write to the [1] element, instead of [0] element. This is out of bounds. You should use:
dict->kv_pairs[dict->num_kvs-1].value = 1;
PS: If you're using GCC or Clang, AddressSanitizer is a great tool to help you detect these type of bugs.
I am new to C programming and I am trying to create a key value structure as in Perl Programming. I saw one solution like :-
struct key_value
{
int key;
char* value;
};
struct key_value kv;
kv.key = 1;
kv.value = "foo";
But I don't know how to access these values from this structure. Can someone enlight on this ?
Here is an example:
#include <stdio.h>
#include <stdlib.h>
struct key_value
{
int key;
char* value;
};
int main(void)
{
int number_of_keys = 2;
struct key_value *kv = malloc(sizeof(struct key_value) * number_of_keys);
if (kv == NULL) {
perror("Malloc");
exit(EXIT_FAILURE);
}
kv[0].key = 8;
kv[0].value = "Test 8 key!";
kv[1].key = 6;
kv[1].value = "Test 6 key!";
printf("Key = %d\nKey value = %s\n", kv[0].key, kv[0].value);
printf("Key = %d\nKey value = %s\n", kv[1].key, kv[1].value);
free(kv);
return 0;
}
What you are missing is a collection. Most languages have a data type called a dictionary or a map or an associative array or some variation thereof. C does not have a data structure of this type; in fact, the only collection type you have built in to C is the array. So, if you want something where you can supply a key and get the value, you have to roll your own or find one on the Internet. The latter is probably preferable because you are likely to make mistakes and produce a slow data structure if you roll your own (especially if you are a beginner).
To give you a flavour of what you'll end up with, here's a simple example:
You'll need something to represent the collection; call it a ListMap for now:
struct ListMap;
The above is called an incomplete type. For now, we are not concerned with what's in it. You can't do anything with it except pass pointers to instances around.
You need a function to insert items into your collection. Its prototype would look something like this:
bool listMapInsert(struct ListMap* collection, int key, const char* value);
// Returns true if insert is successful, false if the map is full in some way.
And you need a function to retrieve the value for any one key.
const char* listMapValueForKey(struct ListMap* collection, int key);
You also need a function to initialise the collection:
struct ListMap* newListMap();
and to throw it away:
void freeListMap(struct ListMap* listMap);
The hard bit is implementing how those functions do what they do. Anyway, here's how you would use them:
struct ListMap* myMap = newListMap();
listMapInsert(myMap, 1, "foo");
listMapInsert(myMap, 1729, "taxi");
listMapInsert(myMap, 28, "perfect");
char* value = listMapValueForKey(myMap, 28); // perfect
freeListMap(myMap);
Here's a simple implementation. This is just for illustration because I haven't tested it and searching for entries increases linearly with the number of entries (you can do much better than that with hash tables and other structures).
enum
{
listMapCapacity = 20
};
struct ListMap
{
struct key_value kvPairs[listMapCapacity];
size_t count;
};
struct ListMap* newListMap()
{
struct ListMap* ret = calloc(1, sizeof *ret);
ret->count = 0; // not strictly necessary because of calloc
return ret;
}
bool listMapInsert(struct ListMap* collection, int key, const char* value)
{
if (collection->count == listMapCapacity)
{
return false;
}
collection->kvPairs[count].key = key;
collection->kvPairs[count].value = strdup(value);
count++;
return true;
}
const char* listMapValueForKey(struct ListMap* collection, int key)
{
const char* ret = NULL;
for (size_t i = 0 ; i < collection->count && ret == NULL ; ++i)
{
if (collection->kvPairs[i].key == key)
{
ret = kvPairs[i].value;
}
}
return ret;
}
void freeListMap(struct ListMap* listMap)
{
if (listMap == NULL)
{
return;
}
for (size_t i = 0 ; i < listMap->count ; ++i)
{
free(listMap->kvPair[i].value);
}
free(listMap);
}
typedef struct key_value
{
int key;
char* value;
}List;
struct key_value k1;
struct key_value k2;
struct key_value k3;
k1.key = 1;
k1.value = "foo";
k2.key = 2;
k2.value = "sec";
k3.key = 3;
k3.value = "third";
You will need to create N times the struct and give them values the way you did the first one. Or create array with N structs and iterate assign it values with a loop.
Array:
List arr[29];
int i;
for(i = 0;i<=28;i++){
arr[i].key = i;
arr[i].value = "W/e it needs to be";
}
The functionality you are looking for needs your own implementation in C; e.g. an array of your struct-type.
Here is an example of how to read the value for a key, without knowing anything about at which array-index the key will be found.
I have the keys numbered backward in order to illustrate that.
Note that more sophisticated API definitions are needed for special cases such as non-existing key; I just blindly return the last entry to keep things easy here.
#include <stdio.h>
#define MAPSIZE 30
struct key_value
{
int key;
char* value;
};
struct key_value kvmap[MAPSIZE];
void initmap(void)
{
int i;
for(i=0; i<MAPSIZE; i++)
{
kvmap[i].key=MAPSIZE-i-1;
kvmap[i].value="unset";
}
kvmap[0].value="zero";
kvmap[1].value="one";
kvmap[2].value="two";
kvmap[3].value="three";
kvmap[4].value="four";
kvmap[5].value="five";
kvmap[6].value="six";
kvmap[7].value="seven";
kvmap[8].value="eight";
kvmap[24].value="find this"; // it has the key "5"
}
char* readmap(int key)
{
int i=0;
while ((i<MAPSIZE-1) && (kvmap[i].key!=key))
{ printf("Not in %d\n", i);
++i;}
// will return last entry if key is not present
return kvmap[i].value;
}
int main(void)
{
initmap();
printf("%s\n", readmap(5));
return 0;
}
"I have to store 30 key/value pair"
Create an array of struct e.g., key_value.
struct key_value
{
int key;
char* value;
};
struct key_value kv[30];
kv[0].key = 1;
kv[0].value = "foo";
printf("%s", kv[0].value);
You can loop through to assign values to keys and values.
Access to whatever is in kv is simple.
int i = kv[0].key`;// copy value of k[0].key to i
char *v = kv[0].value; // copy value of k[0].value to v;
Your code already have the method to acess the values.
kv.key = 1
kv.value = "foo"
To get the values assigned is simple
kv.key
kv.value
It is a simple struct, if you wanna something like python dict you will need to implement a hash struct which will be more complicated.
I hope I have not oversimplified my code, but what I am basically trying to do is to find the existence of an element in a container, and return the pointer to it.
I have structures like
typedef struct INHs{
int ID;
} INHs;
typedef struct sub_container{
INHs** list_inh;
int nb_list;
} sub_container;
typedef struct container {
sub_container* cont;
int nb_elem;
} container;
And then in my main method I have a container allocated (I will leave it out for simplicity, and a given ID; and for now I won't to iterate over the sub-containers to find my target INHs structure).
INHs** test_INH = NULL;
INHs** return_val = NULL;
int ID = 10;
container* cont; //allocated on all memory
for (uint n=0; !test_INH && n<container_nb_elem; n++){
return_val = find_ptr(&cont[n], ID, &test_INH);
}
INHs** find_ptr(sub_container* sub_cont, int ID, INHs*** test){
INHs** res = NULL;
for (uint i=0; !res && i<sub_cont->nb_list; i++){
if (sub_cont->list_inh[i].ID == ID) {
(*test) = &(sub_cont->list_inh[i]);
res = &(sub_cont->list_inh[i]);
}
return res;
}
I know I don't need both a return value to my element and another one as a function parameter, but these are the two versions I have tried. I don't know what I am doing wrong but valgrind crashes telling me that either "test_INH" or "result_val" are non-initialized, although I am setting them on null.
Does someone see what I am missing here?
typedef struct INHs{
int id;
} INHs;
typedef struct sub_container{
INHs **ptrs;
int nb_list;
} sub_container;
typedef struct container {
sub_container *items;
int nb_elem;
} container;
int main(void)
{
INHs **found = NULL;
int id = 10;
container *cont; //allocated on all memory
for (uint n=0; n < cont->nb_elem; n++){
found = find_ptr( &cont->items[n], id);
if (found) break; /* found it! */
}
if(found) {
/* do something useful with *found ... */
}
return 0;
}
INHs **find_ptr(sub_container *sub_cont, int id)
{
for (uint i=0; i < sub_cont->nb_list; i++){
if (sub_cont->ptrs[i]->id != id) continue;
return &sub_cont->ptrs[i];
}
return NULL;
}
BTW: I find the array of pointers to one integer structures rather strange.
Are these structures all malloc()d separately?
I trying to use a dynamic array, when i finish using it, i try to free the memory used and i get this error.
free(): invalid next size (fast): 0x00652098
This are the declarations of the struct variables:
struct player {
int played_time;
int min_time;
int max_time;
int errors;
int color;
};
struct Players {
struct player *array;
size_t player_number;
size_t size;
};
typedef struct Players Player_list;
This are the method used to manage the dynamic array:
void initArray(Player_list *list, size_t initialSize) {
list->array = (struct player *) malloc(initialSize * sizeof(struct player));
list->player_number = 0;
list->size = initialSize;
}
void insertArray(Player_list *list, struct player element) {
if (list->player_number == list->size) {
list->size *= 2;
list->array = (struct player *) realloc(list->array,
list->size * sizeof(struct player));
}
list->array[list->player_number++] = element;
}
void freeArray(Player_list *list) {
free(list->array);
list->array = NULL;
list->player_number = list->size = 0;
}
int disqualified(Player_list *list, int errors) {
int i = 0;
for (i = 0; i < list->player_number; i++) {
if (list->array[i].errors >= errors) {
return 1;
}
}
return 0;
}
And here is how i use it in the main:
/**
* When button is pressed 1 add an error to a random player
*/
void button_s_isr(void) {
int index = rand() % (players.player_number);
point_players->array[index].errors = point_players->array[index].errors + 1;
}
...
int main(void) {
...
// set up of GPIO
// get with scanf NUMBER_OF_PLAYERS and MAX_ERRORS values
int i;
for (i = 0; i < NUMBER_OF_PLAYERS; i++) {
struct player player;
player.color = PLAYER_COLORS[i];
player.errors = 0;
player.max_time = 0;
player.min_time = 0;
player.played_time = 0;
insertArray(&players, player);
}
while (disqualified(&players, MAX_ERRORS) != 1) {
// wait
}
printf("\n Se ha acabdo el juego: ");
freeArray(point_players);
return EXIT_SUCCESS;
}
I must say i am quite new to C, sorry if it is difficult to understand.
What i want to do is a dynamic list of struct (players), where each player has own parameters (played_time, min_time , max_time, errors, color). And inside the main i want to have a game where i can control this parameters from each player.
Any help to improve the code is appreciated.
the posted code:
does not compile
is missing definitions for PLAYER_COLORS[i], which is a bad idea to use as the number of players could exceed the available colours in the array.
incorrectly calculates the size needed for the realloc()
fails to check the returned values from functions like malloc() and realloc()
contains a confusing (even for the OP) naming of variables and struct instances
is missing the definition for num_jugadores
incorrectly tries to assign a struct rather than copying the struct
fails to declare an instance of struct Players
and now, corrected code that compiles cleanly:
caveat: not fully tested
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memcpy()
struct player
{
int played_time;
int min_time;
int max_time;
int errors;
int color;
};
struct Players
{
struct player *array;
size_t player_number;
size_t numPlayers;
};
//This are the method used to manage the dynamic array:
void freeArray(struct Players *pArray)
{
free(pArray->array);
pArray->array = NULL;
pArray->player_number = pArray->numPlayers = 0;
}
void initArray( struct Players *pArray )
{
if( NULL == (pArray->array = malloc(sizeof(struct player)) ) )
{ // then malloc failed
freeArray( pArray );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
pArray->player_number = 0;
pArray->numPlayers = 1;
}
size_t sizeof_array(size_t size)
{
return size * sizeof(struct player);
}
void insertArray(struct Players *pArray, struct player *element)
{
if (pArray->player_number == pArray->numPlayers)
{ // then currently allocated memory for array of players is full
struct player *temp = NULL;
if( NULL == (temp = realloc(pArray->array, sizeof_array(pArray->numPlayers)*2) ) )
{ // then, realloc failed
freeArray( pArray );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
pArray->numPlayers *= 2;
pArray->array = temp;
}
memcpy( &(pArray->array[pArray->player_number]), element, sizeof( struct player ) );
pArray->player_number++;
}
//and here is how i use it in the main method:
#define num_jugadores (20)
int main( void )
{
int i;
struct Players playerList;
initArray(&playerList);
for (i = 0; i < num_jugadores; i++)
{
struct player myPlayer;
//player.color = PLAYER_COLORS[i];
myPlayer.errors = 0;
myPlayer.max_time = 0;
myPlayer.min_time = 0;
myPlayer.played_time = 0;
insertArray(&playerList, &myPlayer);
}
//...
freeArray(&playerList);
} // end function: main
An error like this usually occurs because you are writing past the end of declared memory. While we could probably find the bug by carefully pouring over every line of code, valgrind would find it much faster for you.
Try compiling your code in debug mode, without optimizations, (gcc -g -O0 if you are using gcc) and run your program under valgrind (e.g., valgrind myprog -my-prog-options). It should flag the error right away.
All this assumes you are running a variant of linux. If you are using visual studio, there will probably be a similar memory checker, but I don't know what it is or how to run it.
Good Luck!
In my binary search tree I want to create a function that can get all words starting with a prefix and store all words in an array called results
this is my tree
struct BinarySearchTree_t
{
char *mot,*def;
struct BinarySearchTree_t *left;
struct BinarySearchTree_t *right;
};
typedef struct BinarySearchTree_t BinarySearchTree;
my function :
size_t findWordsByPrefix(BinarySearchTree* tree, char* prefix, char*** results)
{
BinarySearchTree *tmp;
tmp=tree;
static int size=0;
if (!tmp)
return 0;
else if (strncmp(tmp->mot,prefix,strlen(prefix))==0)
{
(*results)= realloc(*results,(1+size)*sizeof(*(*results)));
(*(*results+size))= malloc(strlen(tmp->mot)*sizeof(char));
strcpy((*results)[size],tmp->mot);
size++;
return (1 + findWordsByPrefix(tmp->left,prefix, &results) + findWordsByPrefix(tmp->right,prefix, &results));
}
else
return (strncmp(tmp->mot,prefix,strlen(prefix))<0)?findWordsByPrefix(tmp->right,prefix, &results):findWordsByPrefix(tmp->left,prefix, &results) ;
}
This function should return a number of words starting with the given prefix.
my problem is that the program crash when it is run , and I don't how to resize my array results
so every time I found a word I should increase the size of the results array .
and I would know how exacly manipulate the pointer of pointer of pointer given in arg of this function (char ***results) : what exactly means?
If I simply compile your code, I get severe compiler warnings including:
1>binarysearchtree.c(98) : warning C4047: 'function' : 'char ***' differs in levels of indirection from 'char ****'
1>binarysearchtree.c(98) : warning C4024: 'findWordsByPrefix' : different types for formal and actual parameter 3
This alone will cause a crash -- you are calling your own function recursively with the wrong arguments.
Next, I believe you need to allocate one more than the length of the string, to hold a copy of a string:
malloc((strlen(tmp->mot) + 1 )*sizeof(char))
Next, you're passing around an array of strings of variable size -- and storing the size in a static variable. It's impossible to know if this will work, so don't do it.
Instead, if you want to use a dynamic array of strings, I suggest extracting out a struct to hold them, like so:
struct ResultTable_t
{
int size;
char **results;
};
typedef struct ResultTable_t ResultTable;
void InitializeResults(ResultTable *p_table)
{
p_table->size = 0;
p_table->results = NULL;
}
void AddResult(ResultTable *p_table, char *result)
{
if (result == NULL)
return;
p_table->size++;
p_table->results = realloc(p_table->results, p_table->size * sizeof(*p_table->results));
p_table->results[p_table->size-1] = malloc((strlen(result) + 1) * sizeof(**p_table->results));
strcpy(p_table->results[p_table->size-1], result);
}
void FreeResults(ResultTable *p_table)
{
if (p_table->results != NULL)
{
int i;
for (i = 0; i < p_table->size; i++)
{
free(p_table->results[i]);
}
free(p_table->results);
}
p_table->size = 0;
p_table->results = NULL;
}
(As an improvement, you might consider using geometric growth instead of linear growth for your table of results.)
Then your function becomes:
size_t findWordsByPrefix(BinarySearchTree* tree, char* prefix, ResultTable *p_table)
{
if (!tree)
return 0;
else if (strncmp(tree->mot,prefix,strlen(prefix))==0)
{
AddResult(p_table, tree->mot);
return (1 + findWordsByPrefix(tree->left,prefix, p_table) + findWordsByPrefix(tree->right,prefix, p_table));
}
else if (strncmp(tree->mot,prefix,strlen(prefix))<0)
{
return findWordsByPrefix(tree->right,prefix, p_table);
}
else
{
return findWordsByPrefix(tree->left,prefix, p_table);
}
}
And you would use it like:
ResultTable results;
InitializeResults(&results);
// Get some prefix to search for.
char prefix = GetSomePrefix();
int size = findWordsByPrefix(tree, prefix, &results);
// Do something with the results
// Free all memory of the results
FreeResults(&results);
Update
If the ResultTable is distasteful for some reason, you can pass the dynamic array and array sizes in directly:
void AddResult(char ***p_results, int *p_size, char *word)
{
if (word == NULL)
return;
(*p_size)++;
(*p_results) = realloc(*p_results, ((*p_size)+1) * sizeof(**p_results));
(*p_results)[(*p_size)-1] = malloc((strlen(word) + 1) * sizeof(***p_results));
strcpy((*p_results)[(*p_size)-1], word);
}
void FreeResults(char ***p_results, int *p_size)
{
int i;
if (p_results == NULL || *p_results == NULL)
return;
for (i = 0; i < (*p_size); i++)
{
free ((*p_results)[i]);
}
free (*p_results);
*p_results = NULL;
*p_size = 0;
}
size_t findWordsByPrefix(BinarySearchTree* tree, char* prefix, char ***p_results, int *p_size)
{
if (!tree)
return 0;
else if (strncmp(tree->mot,prefix,strlen(prefix))==0)
{
AddResult(p_results, p_size, tree->mot);
return (1 + findWordsByPrefix(tree->left,prefix, p_results, p_size) + findWordsByPrefix(tree->right,prefix, p_results, p_size));
}
else if (strncmp(tree->mot,prefix,strlen(prefix))<0)
{
return findWordsByPrefix(tree->right,prefix, p_results, p_size);
}
else
{
return findWordsByPrefix(tree->left,prefix, p_results, p_size);
}
}
and use like:
char **results = NULL;
int tablesize = 0;
// Get some prefix to search for.
char prefix = GetSomePrefix();
int size = findWordsByPrefix(tree, prefix, &results, &tablesize);
// Do something with the results
// Free all memory of the results
FreeResults(&results, &tablesize);