From 741fbd9a4c109cb32cbfdbfe9d88933ecc444495 Mon Sep 17 00:00:00 2001 From: iliya <iliya.saroukha@hes-so.ch> Date: Fri, 10 Nov 2023 10:58:51 +0100 Subject: [PATCH] feat: made implementation generic, goal finally achieved --- Makefile | 13 ++++--- struct/vec.c | 95 +++++++++++++++++++++++++++------------------------- struct/vec.h | 14 ++++---- vec_test.c | 16 +++++---- 4 files changed, 74 insertions(+), 64 deletions(-) diff --git a/Makefile b/Makefile index 780212b..4ef0dcd 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,11 @@ CC := clang -CFLAGS := -Wall -Wextra -g -pedantic -fPIC -fsanitize=address -fsanitize=leak -fsanitize=undefined -VPATH := struct -LDFLAGS := -L$(shell pwd)/ -lvector +CFLAGS := -g -pedantic -Wall -Wextra -Werror -fPIC +LDFLAGS := -fsanitize=address,leak,undefined -L$(shell pwd)/ -lvector SHELL := /bin/bash +VPATH := struct TARGET := vec_test +all: $(TARGET) $(TARGET): $(TARGET).o lib_dyn $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) @@ -23,8 +24,7 @@ lib_dyn: vec.o ln -s libvector.so.1.0.0 libvector.so; \ fi - -vec.o: vec.c vec.h +%.o: %.c $(CC) $(CFLAGS) -c $< .PHONY: clean @@ -32,3 +32,6 @@ vec.o: vec.c vec.h clean: rm -f $(TARGET) *.o libvector.so libvector.so.1 libvector.so.1.0.0 +.PHONY: rebuild + +rebuild: clean all diff --git a/struct/vec.c b/struct/vec.c index c791665..44ace6d 100644 --- a/struct/vec.c +++ b/struct/vec.c @@ -5,28 +5,28 @@ #include <stdlib.h> #include <string.h> -#define err_init(x) \ +#define ERR_INIT(x) \ if (x == NULL) { \ fprintf(stderr, "Function: %s [%s:%d]: `Vector not initialised!`\n\n", \ __func__, __FILE__, __LINE__); \ return; \ } -#define err_len_zero(x) \ +#define ERR_LEN_ZERO(x) \ if (x->len == 0) { \ fprintf(stderr, "Function: %s [%s:%d]: `Vector length is zero!`\n\n", \ __func__, __FILE__, __LINE__); \ return; \ } -#define print_arr(x, len) \ +#define PRINT_ARR(x, len) \ for (size_t i = 0; i < len; i++) { \ fprintf(stderr, "LOG:\tarr[%ld] -> %ld\n", i, x[i]); \ } \ fprintf(stderr, "\n"); struct _vec_t { - int64_t *data; + void **data; size_t len; size_t capacity; }; @@ -39,7 +39,6 @@ struct _vec_t { * @return Pointer to newly instantiated vector */ vec_t *vec_create(size_t init_capacity) { - if (init_capacity == 0) { fprintf(stderr, "Initial size of the vector has to be a non-zero\n"); return NULL; @@ -48,16 +47,16 @@ vec_t *vec_create(size_t init_capacity) { vec_t *vec = malloc(sizeof(vec_t)); if (vec == NULL) { - fprintf(stderr, "Allocation for new vector failed!\n"); + perror("malloc"); return NULL; } vec->len = 0; vec->capacity = init_capacity; - vec->data = malloc(init_capacity * sizeof(int64_t)); + vec->data = malloc(init_capacity * sizeof(void *)); if (vec->data == NULL) { - fprintf(stderr, "Allocation for data member failed!\n"); + perror("malloc"); return NULL; } @@ -92,16 +91,15 @@ ssize_t vec_length(vec_t *vec) { * @param idx Index in the vector * @return Value contained at the given index OR -1 in case of an error */ -int64_t vec_get(vec_t *vec, size_t idx) { - +void *vec_get(vec_t *vec, size_t idx) { if (vec == NULL) { fprintf(stderr, "Vector not initialised!\n"); - return -1; + return NULL; } if (idx > vec->capacity - 1) { fprintf(stderr, "Index out of bounds\n"); - return -1; + return NULL; } return vec->data[idx]; @@ -111,17 +109,15 @@ int64_t vec_get(vec_t *vec, size_t idx) { * @brief Function that inserts/pushes a value into an existing vector * * @param vec Vector in which we wish to insert a value - * @param data Value that we wish to insert */ -void vec_push(vec_t *vec, int64_t data) { - - err_init(vec); +void vec_push(vec_t *vec, void *data) { + ERR_INIT(vec); if (vec->len >= (size_t)(vec->capacity * 0.75)) { size_t new_capacity = 2 * vec->capacity; - vec->data = realloc(vec->data, new_capacity * sizeof(int64_t)); + vec->data = realloc(vec->data, new_capacity * sizeof(void *)); vec->capacity = new_capacity; } @@ -136,11 +132,9 @@ void vec_push(vec_t *vec, int64_t data) { * @param data Value that we wish to insert * @param idx Position in the vector */ -void vec_insert_at(vec_t *vec, int64_t data, size_t idx) { - - err_init(vec); - - err_len_zero(vec); +void vec_insert_at(vec_t *vec, void *data, size_t idx) { + ERR_INIT(vec); + ERR_LEN_ZERO(vec); if (idx > vec->capacity - 1) { fprintf(stderr, "Index out of bounds\n"); @@ -150,21 +144,22 @@ void vec_insert_at(vec_t *vec, int64_t data, size_t idx) { if (idx <= vec->len) { size_t size_to_copy = vec->len - idx; - int64_t incl_and_aftr_idx[size_to_copy]; + void **incl_and_aftr_idx = malloc(size_to_copy * sizeof(void *)); memcpy((void *)incl_and_aftr_idx, (void *)(vec->data + idx), - size_to_copy * sizeof(int64_t)); + size_to_copy * sizeof(void *)); for (size_t i = 0; i < size_to_copy; i++) { vec_pop(vec); } vec_push(vec, data); - // print_arr(aftr_idx, size_to_copy); for (size_t i = 0; i < size_to_copy; i++) { vec_push(vec, incl_and_aftr_idx[i]); } + + free(incl_and_aftr_idx); } } @@ -175,8 +170,7 @@ void vec_insert_at(vec_t *vec, int64_t data, size_t idx) { * @param data Value to check for * @return `true` if value was found otherwise, `false` */ -bool is_in_vec(vec_t *vec, int64_t data) { - +bool is_in_vec(vec_t *vec, void *data) { if (vec == NULL) { fprintf(stderr, "Vector not initialised\n"); return false; @@ -198,16 +192,15 @@ bool is_in_vec(vec_t *vec, int64_t data) { * @param vec Vector from which the value will be removed * @return Last element in the vector */ -int64_t vec_pop(vec_t *vec) { - +void *vec_pop(vec_t *vec) { if (vec == NULL) { fprintf(stderr, "Vector not initialised\n"); - return -1; + return NULL; } if (vec->len == 0) { fprintf(stderr, "Length of the vector is 0!\n"); - return -1; + return NULL; } // needs resizing // should be extracted into separate function @@ -215,7 +208,7 @@ int64_t vec_pop(vec_t *vec) { size_t new_size = vec->capacity / 2; - vec->data = realloc(vec->data, new_size * sizeof(int64_t)); + vec->data = realloc(vec->data, new_size * sizeof(void *)); vec->capacity = new_size; } @@ -231,10 +224,8 @@ int64_t vec_pop(vec_t *vec) { * @param idx Position in the vector */ void vec_remove(vec_t *vec, size_t idx) { - - err_init(vec); - - err_len_zero(vec); + ERR_INIT(vec); + ERR_LEN_ZERO(vec); if (idx > vec->len) { fprintf(stderr, "Index out of bounds!\n"); @@ -247,10 +238,10 @@ void vec_remove(vec_t *vec, size_t idx) { } size_t size_to_copy = vec->len - (idx + 1); - int64_t aftr_idx[size_to_copy]; + void **aftr_idx = malloc(size_to_copy * sizeof(void *)); memcpy((void *)aftr_idx, (void *)(vec->data + idx + 1), - size_to_copy * sizeof(int64_t)); + size_to_copy * sizeof(void *)); size_t size_to_pop = size_to_copy + 1; @@ -258,11 +249,24 @@ void vec_remove(vec_t *vec, size_t idx) { vec_pop(vec); } - // print_arr(aftr_idx, size_to_copy); - for (size_t i = 0; i < size_to_copy; i++) { vec_push(vec, aftr_idx[i]); } + + free(aftr_idx); +} + +char *print_int(void *element) { + int64_t data = (int64_t)element; + char *s = calloc(30, sizeof(char)); + + if (s == NULL) { + perror("calloc"); + return NULL; + } + + sprintf(s, "Data: %ld |\n", data); + return s; } /** @@ -271,23 +275,22 @@ void vec_remove(vec_t *vec, size_t idx) { * * @param vec */ -void vec_print(vec_t *vec) { - - err_init(vec); +void vec_print(vec_t *vec, char *(*print_entry)(void *data)) { + ERR_LEN_ZERO(vec); fprintf(stdout, " ========= Vector Data =========\n"); fprintf(stdout, " Capacity: %zu\tCurrent Size: %zu\n", vec->capacity, vec->len); fprintf(stdout, " ===============================\n"); - fprintf(stdout, " -------------------------------\n"); for (size_t i = 0; i < vec->len; i++) { - fprintf(stdout, "| Vector[%ld]\t->\tData: %ld |\n", i, vec->data[i]); + char *s = print_entry(vec->data[i]); + fprintf(stdout, "| Vector[%ld]\t->\t%s", i, s); + free(s); } fprintf(stdout, " -------------------------------\n"); fprintf(stdout, "\n"); } - /** * @brief Function that deallocates memory used up by the vector that was passed * as an argument to the function. Subsequently the pointer will be set to NULL, diff --git a/struct/vec.h b/struct/vec.h index 856226f..7ca9003 100644 --- a/struct/vec.h +++ b/struct/vec.h @@ -10,19 +10,21 @@ extern vec_t *vec_create(size_t init_len); extern ssize_t vec_length(vec_t *vec); -extern int64_t vec_get(vec_t *vec, size_t idx); +extern void *vec_get(vec_t *vec, size_t idx); -extern void vec_push(vec_t *vec, int64_t data); +extern void vec_push(vec_t *vec, void *data); -extern void vec_insert_at(vec_t *vec, int64_t data, size_t idx); +extern void vec_insert_at(vec_t *vec, void *data, size_t idx); -extern bool is_in_vec(vec_t *vec, int64_t data); +extern bool is_in_vec(vec_t *vec, void *data); extern void vec_remove(vec_t *vec, size_t idx); -extern int64_t vec_pop(vec_t *vec); +extern void *vec_pop(vec_t *vec); -extern void vec_print(vec_t *vec); +extern char *print_int(void *element); + +extern void vec_print(vec_t *vec, char *(*print_entry)(void *data)); extern void vec_destroy(vec_t **vec); diff --git a/vec_test.c b/vec_test.c index a785ff1..b497f98 100644 --- a/vec_test.c +++ b/vec_test.c @@ -1,9 +1,9 @@ +#include "struct/vec.h" #include <libgen.h> #include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> -#include <vec.h> #define NB_OPTIONS 6 void print_menu(void) { @@ -19,7 +19,6 @@ void print_menu(void) { } int main(int argc, char **argv) { - if (argc < 2) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\t./%s <initial length of vector>\n", @@ -69,7 +68,7 @@ int main(int argc, char **argv) { scanf("%ld", &to_push); fprintf(stdout, "\n"); - vec_push(new_vec, to_push); + vec_push(new_vec, (void *)to_push); break; case 2: fprintf(stdout, @@ -80,12 +79,13 @@ int main(int argc, char **argv) { vec_remove(new_vec, idx_to_drop); break; case 3: - item_poped = vec_pop(new_vec); + item_poped = (int64_t)vec_pop(new_vec); fprintf(stdout, "Last value in the vector: %ld was removed\n", item_poped); break; case 4: - vec_print(new_vec); + // vec_print(new_vec); + vec_print(new_vec, print_int); break; case 5: fprintf(stdout, @@ -97,13 +97,15 @@ int main(int argc, char **argv) { "Specify the index at which you wish to insert the number: "); scanf("%zu", &idx_to_insert); - vec_insert_at(new_vec, to_push, idx_to_insert); + vec_insert_at(new_vec, (void *)to_push, idx_to_insert); break; case 6: vec_destroy(&new_vec); - return EXIT_SUCCESS; + exit(EXIT_SUCCESS); default: break; } } + + return EXIT_SUCCESS; } -- GitLab