Last active
October 16, 2021 11:41
-
-
Save bert/265933 to your computer and use it in GitHub Desktop.
Hash table for key-value pairs example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* \file main.c | |
* | |
* \brief Example code of using a hash table for key-value pairs. | |
*/ | |
#include <glib.h> | |
#include <stdio.h> | |
/*! | |
* \brief Create a hash table from file. | |
*/ | |
int | |
create_hash_table_from_file (gchar *filename, GHashTable *table) | |
{ | |
FILE *fp; | |
char buf[1024]; | |
/* Just a standard way to open files. */ | |
fp = fopen (filename, "r"); | |
/* If file does not exist, exit. */ | |
if (!fp) | |
{ | |
exit (1); | |
} | |
/* Read file line by line. */ | |
while (fgets (buf, sizeof (buf), fp)) | |
{ | |
char *key; | |
char *value; | |
/* Get the first and the second field. */ | |
key = strtok (buf, "\t"); | |
if (!key) | |
continue; | |
value = strtok (NULL, "\t"); | |
if (!value) | |
continue; | |
/* Look up the table for an existing key. | |
* If it exists replace it by inserting the new ke-value pair and | |
* freeing the old key-value pair */ | |
char *old_key = NULL; | |
char *old_value = NULL; | |
/* Try looking up this key. */ | |
if (g_hash_table_lookup_extended (table, key, (gpointer *) old_key, (gpointer *) old_value)) | |
{ | |
/* Insert the new value */ | |
g_hash_table_insert (table, g_strdup (key), g_strdup (value)); | |
/* Just free the key and value */ | |
g_free (old_key); | |
g_free (old_value); | |
} | |
else | |
{ | |
/* Insert into our hash table it is not a duplicate. */ | |
g_hash_table_insert (table, g_strdup (key), g_strdup (value)); | |
} | |
} | |
/* Close the file when done. */ | |
fclose (fp); | |
return (EXIT_SUCCESS); | |
} | |
/*! | |
* \brief Dispose of the hash table. | |
*/ | |
int | |
destroy_hash_table (GHashTable *table) | |
{ | |
g_hash_table_destroy (table); | |
return (EXIT_SUCCESS); | |
} | |
/*! | |
* \brief Remove the entry with the passed key from the hash table. | |
*/ | |
int | |
remove_entry (GHashTable *table, char *key) | |
{ | |
int result = EXIT_FAILURE; | |
char *old_key = NULL; | |
char *old_value = NULL; | |
/* Try looking up this key */ | |
if (g_hash_table_lookup_extended (table, key, (gpointer *) old_key, (gpointer *) old_value)) | |
{ | |
/* Remove the entry in the hash table. */ | |
g_hash_table_remove (table, key); | |
/* Just free the key and value. */ | |
g_free( old_key); | |
g_free (old_value); | |
result = EXIT_SUCCESS; | |
} | |
else | |
{ | |
fprintf (stderr, "Did not find passed key."); | |
} | |
return (result); | |
} | |
/*! | |
* \brief Free a key-value pair inside the hash table. | |
*/ | |
static void | |
free_a_hash_table_entry (gpointer key, gpointer value, gpointer user_data) | |
{ | |
g_free (key); | |
g_free (value); | |
} | |
/*! | |
* \brief Free all key-value entries in the hash table. | |
*/ | |
int | |
free_all_key_value_entries (GHashTable *table) | |
{ | |
g_hash_table_foreach (table, free_a_hash_table_entry, NULL); | |
return EXIT_SUCCESS; | |
} | |
static gboolean | |
remove_keys_with_A (gpointer key, gpointer value, gpointer user_data) | |
{ | |
char *char_value = (char *) value; | |
if (char_value[0] == 'A') | |
{ | |
g_free (key); | |
g_free (value); | |
return TRUE; | |
} | |
else | |
{ | |
return FALSE; | |
} | |
} | |
/*! | |
* \brief Let's have a main function. | |
*/ | |
int | |
main () | |
{ | |
/* Intialise the hash table. */ | |
GHashTable *table = g_hash_table_new (g_str_hash, g_str_equal); | |
int deleted; | |
gchar *file_name = strdup ("test.txt"); | |
create_hash_table_from_file (file_name, table); | |
/* Do something with the hash table here. */ | |
deleted = g_hash_table_foreach_remove (table, remove_keys_with_A, NULL); | |
printf ("Deleted %d items!\n", deleted); | |
free_all_key_value_entries (table); | |
destroy_hash_table (table); | |
} | |
/* EOF */ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CFLAGS = -Wall -g `pkg-config --cflags glib-2.0` | |
LDFLAGS = `pkg-config --libs glib-2.0` | |
all: main.c | |
$(CC) -o main main.c $(CFLAGS) $(LDFLAGS) | |
clean: | |
rm -f *~ | |
rm -f *.o | |
rm -f main |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name bert | |
location home | |
website github | |
first A | |
double AA | |
last Z |
Hi nice code however it doesn't compile
FILE *fp <- missing semicolon
char buf[1024];
main doesn't return anything
Ась?
How can one insert values other than char *value;
e.g. int
to th table?
Have a look at: https://docs.gtk.org/glib/type_func.HashTable.new.html
methinks something like:
GHashTable table = g_hash_table_new (g_int_hash, g_int_equal); / untested */
I did some debugging, it now compiles and gives expected output.
Also added a test file and debugged the Makefile.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@ya1gaurav,
GHashTable
doesn't copy keys and values. I.e. both key and value are references to something (that developer should keep).g_strdup
result is allocated memory that should be freed usingg_free
. It's possible to use g_hash_table_new_full:In this example
g_free
-s are destroy callbacks for keys and values. This way strings (keys and values) created usingg_strdup
will be deallocated after deleting.