From 9db7d84a67c2fe1c811989e3e1a616242d1bdec0 Mon Sep 17 00:00:00 2001 From: Orestis <orestis.malaspinas@pm.me> Date: Fri, 14 Jan 2022 23:10:15 +0100 Subject: [PATCH] added hashmap example for live code --- examples/hashmap/.gitignore | 2 + examples/hashmap/Makefile | 24 +++++++ examples/hashmap/hm.c | 123 ++++++++++++++++++++++++++++++++++++ examples/hashmap/hm.h | 30 +++++++++ examples/hashmap/main.c | 21 ++++++ 5 files changed, 200 insertions(+) create mode 100644 examples/hashmap/.gitignore create mode 100644 examples/hashmap/Makefile create mode 100644 examples/hashmap/hm.c create mode 100644 examples/hashmap/hm.h create mode 100644 examples/hashmap/main.c diff --git a/examples/hashmap/.gitignore b/examples/hashmap/.gitignore new file mode 100644 index 0000000..87e54c2 --- /dev/null +++ b/examples/hashmap/.gitignore @@ -0,0 +1,2 @@ +main +*.o diff --git a/examples/hashmap/Makefile b/examples/hashmap/Makefile new file mode 100644 index 0000000..604c269 --- /dev/null +++ b/examples/hashmap/Makefile @@ -0,0 +1,24 @@ +CC=gcc +CFLAGS=-g -std=gnu11 -Wall -Wextra -pedantic -fsanitize=address -fsanitize=leak -fsanitize=undefined +LDFLAGS=-fsanitize=address -fsanitize=leak -fsanitize=undefined +SOURCES=$(wildcard *.c) +OBJECTS=$(SOURCES:.c=.o) + +TARGET = main + +all: $(TARGET) + +exec_tests: + make -C tests/ exec_tests + +$(TARGET): $(OBJECTS) + $(CC) $^ -o $@ $(LDFLAGS) + +hashmap.c: hashmap.h + +.PHONY = clean tests + +clean: + rm -f $(OBJECTS) $(TARGET) + make clean -C tests + diff --git a/examples/hashmap/hm.c b/examples/hashmap/hm.c new file mode 100644 index 0000000..97c1303 --- /dev/null +++ b/examples/hashmap/hm.c @@ -0,0 +1,123 @@ +#include "hm.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static bool is_not_allocated(hm h) { + return (h.table == NULL || h.capacity < 1 || h.size < 0); +} + +static size_t hash(hm h, char key[MAX_LEN]) { + int index = 0; + for (size_t i = 0; i < strlen(key); ++i) { + index = (index + key[i] * 43) % h.capacity; + } + return index; +} + +static int rehash(char *key) { + return 1; +} + +static int find_index(hm h, char key[MAX_LEN], bool insert) { + int try = 0; + int index = hash(h, key); + while (try < h.capacity) { + switch (h.table[index].state) { + case occupied: + if (strncmp(h.table[index].key, key, MAX_LEN) == 0) { + return index; + } + break; + case empty: + return index; + break; + case deleted: + if (insert) { + return index; + } + break; + default: + return -1; + break; + } + index = (index + rehash(key)) % h.capacity; + try += 1; + } + return -1; +} + +static bool is_empty(hm h) { + return h.size == 0; +} + +void hm_init(hm *h, int capacity) { + h->capacity = capacity; + h->size = 0; + h->table = malloc(h->capacity * sizeof(*h->table)); + for (int i = 0; i < h->capacity; ++i) { + h->table[i].state = empty; + } +} + +void hm_destroy(hm *h) { + h->capacity = -1; + h->size = -1; + free(h->table); + h->table = NULL; +} + +bool hm_set(hm *h, char *key, char *value) { + if (is_not_allocated(*h)) { + return false; + } + + int index = find_index(*h, key, true); + if (index < 0) { + return false; + } + /* printf("%d\n", index); */ + strncpy(h->table[index].value, value, MAX_LEN); + strncpy(h->table[index].key, key, MAX_LEN); + h->table[index].state = occupied; + h->size += 1; + return true; +} + +bool hm_get(hm h, char *key, char *value) { + int index = find_index(h, key, false); + if (index >= 0 && h.table[index].state == occupied) { + strncpy(value, h.table[index].value, MAX_LEN); + return true; + } + return false; +} +bool hm_remove(hm *h, char *key, char *value) { + int index = find_index(*h, key, false); + if (index >= 0 && h->table[index].state == occupied) { + h->table[index].state = deleted; + strncpy(value, h->table[index].value, MAX_LEN); + h->size -= 1; + return true; + } + return false; +} + +bool hm_search(hm h, char *key) { + int index = find_index(h, key, false); + return (index >= 0 && h.table[index].state == occupied); +} + +void hm_print(hm h) { + if (is_not_allocated(h)) { + printf("Well this hashmap is not allocated n00b.\n"); + } + if (is_empty(h)) { + printf("The hashmap is empty.\n"); + } + for (int i = 0; i < h.capacity; ++i) { + printf("index: %d, key: %s, value: %s\n", i, h.table[i].key, + h.table[i].value); + } +} + diff --git a/examples/hashmap/hm.h b/examples/hashmap/hm.h new file mode 100644 index 0000000..7572fd8 --- /dev/null +++ b/examples/hashmap/hm.h @@ -0,0 +1,30 @@ +#ifndef _HM_H_ +#define _HM_H_ + +#include <stdbool.h> + +#define MAX_LEN 80 + +typedef enum { empty, occupied, deleted } state_t; + +typedef struct _cell_t { + char key[MAX_LEN]; + char value[MAX_LEN]; + state_t state; +} cell_t; + +typedef struct _hm { + cell_t *table; + int capacity; + int size; +} hm; + +void hm_init(hm *h, int capacity); +void hm_destroy(hm *h); +bool hm_set(hm *h, char *key, char *value); +bool hm_get(hm h, char *key, char *value); +bool hm_remove(hm *h, char *key, char *value); +bool hm_search(hm h, char *key); +void hm_print(hm h); + +#endif diff --git a/examples/hashmap/main.c b/examples/hashmap/main.c new file mode 100644 index 0000000..b8f5927 --- /dev/null +++ b/examples/hashmap/main.c @@ -0,0 +1,21 @@ +#include "hm.h" +#include <stdio.h> + +int main() { + char key[80], value[80]; + hm h; + hm_init(&h, 5); + for (int i = 0; i < 6; ++i) { + scanf("%s", key); + scanf("%s", value); + hm_set(&h, key, value); + hm_print(h); + if (hm_search(h, "orestis")) { + printf("orestis found.\n"); + } + if (hm_remove(&h, "orestis", value)) { + printf("orestis removed: %s.\n", value); + } + } + hm_destroy(&h); +} -- GitLab