Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions test_2_1/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ project(test_2_1)
set(testName "${PROJECT_NAME}")

add_subdirectory(task_1)
add_subdirectory(task_2)
6 changes: 6 additions & 0 deletions test_2_1/task_2/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
project("${testName}_task_2")

add_library(hashset hashset.c)

add_executable(${PROJECT_NAME}_test test.c)
target_link_libraries(${PROJECT_NAME}_test hashset)
81 changes: 81 additions & 0 deletions test_2_1/task_2/hashset.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include "hashset.h"

#include <stdlib.h>
#include <string.h>

typedef struct Hashset {
char *elements[HASHSET_SIZE];
} Hashset;

bool createHashset(Hashset **hashset) {
*hashset = malloc(sizeof(Hashset));
if (*hashset == NULL) {
return false;
}

for (int i = 0; i < HASHSET_SIZE; ++i) {
(*hashset)->elements[i] = NULL;
}

return true;
}

static unsigned int getStringHash(const char *string) {
unsigned int hash = 0;
for (int i = 0; string[i] != '\0'; ++i) {
hash = hash * 57 + string[i];
}
return hash;
}

bool addToHashset(Hashset *hashset, const char *string) {
if (string == NULL) {
return false;
}

unsigned int elementIndex = getStringHash(string) % HASHSET_SIZE;

int counter = 0;
while (hashset->elements[elementIndex] != NULL) {
elementIndex = (elementIndex + 1) % HASHSET_SIZE;
++counter;
if (counter >= HASHSET_SIZE) {
return false;
}
}

char *stringCopy = strdup(string);
if (stringCopy == NULL) {
return false;
}

hashset->elements[elementIndex] = stringCopy;

return true;
}

bool containedInHashset(Hashset *hashset, const char *string) {
unsigned int elementIndex = getStringHash(string) % HASHSET_SIZE;

if (hashset->elements[elementIndex] == NULL) {
return false;
}

int counter = 0;
while (strcmp(hashset->elements[elementIndex], string) != 0) {
elementIndex = (elementIndex + 1) % HASHSET_SIZE;
++counter;
if (counter >= HASHSET_SIZE) {
return false;
}
}

return true;
}

void disposeHashset(Hashset *hashset) {
for (int i = 0; i < HASHSET_SIZE; ++i) {
free(hashset->elements[i]);
}
free(hashset);
}
27 changes: 27 additions & 0 deletions test_2_1/task_2/hashset.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#define HASHSET_SIZE 256

/// @brief Hashset of strings
typedef struct Hashset Hashset;

/// @brief Creates new hashset
/// @param hashset Pointer to store new hashset to
/// @return `true` if created successfully, `false` otherwise (allocation failed)
bool createHashset(Hashset **hashset);

/// @brief Adds string to hashtable
/// @param hashset Hashset to add string to
/// @param string String to add
/// @return `true` if added successfully, `false` otherwise (string was `NULL`, allocation failed, no space for new entries left)
bool addToHashset(Hashset *hashset, const char *string);

/// @brief Searchs for specified string
/// @param hashset Hashset to search string in
/// @param string String to search
/// @return `true` if found, `false` otherwise
bool containedInHashset(Hashset *hashset, const char *string);

/// @brief Disposes hashtable
/// @param hashset Hashtable to dispose
void disposeHashset(Hashset *hashset);
78 changes: 78 additions & 0 deletions test_2_1/task_2/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#define CTEST_MAIN
#define CTEST_SEGFAULT
#include "../../ctest/ctest.h"

#include <stdlib.h>

#include "hashset.h"

int main(int argc, const char *argv[]) {
return ctest_main(argc, argv);
}

Hashset *createNewHashset(void) {
Hashset *hashset = NULL;
ASSERT_TRUE(createHashset(&hashset));
return hashset;
}

CTEST(hashsetTests, createTest) {
Hashset *hashset = createNewHashset();
disposeHashset(hashset);
}

CTEST(hashsetTests, singleElemenTest) {
Hashset *hashset = createNewHashset();

ASSERT_FALSE(containedInHashset(hashset, "element"));
ASSERT_TRUE(addToHashset(hashset, "element"));
ASSERT_TRUE(containedInHashset(hashset, "element"));
ASSERT_FALSE(containedInHashset(hashset, "not_element"));

disposeHashset(hashset);
}

CTEST(hashsetTests, randomElementsTest) {
char *elements[HASHSET_SIZE] = { 0 };

const char *elementTemplate = "key_000";
const int elementOffset = strlen("key_");
const int digitsCount = strlen(elementTemplate) - elementOffset;

for (int i = 0; i < HASHSET_SIZE; ++i) {
char *element = strdup(elementTemplate);

ASSERT_NOT_NULL(element);

elements[i] = element;

int number = i;
for (int j = digitsCount - 1; j >= 0; --j) {
char digit = (number % 10) + '0';
element[elementOffset + j] = digit;
number /= 10;
}
}

Hashset *hashset = createNewHashset();

srand(453563458);
for (int i = 0; i < HASHSET_SIZE; ++i) {
int index = (rand() % (HASHSET_SIZE - i)) + i;

ASSERT_TRUE(addToHashset(hashset, elements[i]));
}

for (int i = 0; i < HASHSET_SIZE; ++i) {
ASSERT_TRUE(containedInHashset(hashset, elements[i]));
}

ASSERT_FALSE(containedInHashset(hashset, "random_element"));
ASSERT_FALSE(containedInHashset(hashset, "does_not_exist"));

for (int i = 0; i < HASHSET_SIZE; ++i) {
free(elements[i]);
}

disposeHashset(hashset);
}