Skip to content

Instantly share code, notes, and snippets.

@bert
Last active October 16, 2021 11:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save bert/265933 to your computer and use it in GitHub Desktop.
Save bert/265933 to your computer and use it in GitHub Desktop.
Hash table for key-value pairs example
/*!
* \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 */
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
name bert
location home
website github
first A
double AA
last Z
@ya1gaurav
Copy link

what will happen to memory returned by g_strdup() ?

@logrusorgru
Copy link

@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 using g_free. It's possible to use g_hash_table_new_full:

GHashTable = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);

In this example g_free-s are destroy callbacks for keys and values. This way strings (keys and values) created using g_strdup will be deallocated after deleting.

@stuart13091987
Copy link

Hi nice code however it doesn't compile

FILE *fp <- missing semicolon
char buf[1024];

main doesn't return anything

@Globik
Copy link

Globik commented Apr 28, 2018

Ась?

Copy link

ghost commented Oct 16, 2021

How can one insert values other than char *value; e.g. int to th table?

@bert
Copy link
Author

bert commented Oct 16, 2021

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 */

@bert
Copy link
Author

bert commented Oct 16, 2021

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