From 70cdab95d12092636c3c24597b18177df8b6bf64 Mon Sep 17 00:00:00 2001 From: Samuel Oberhofer Date: Sat, 18 Jun 2022 14:51:31 +0200 Subject: [PATCH] 4.1 --- Uebung 4/Uebung4_1/Makefile | 51 ++++++++++++++++++ Uebung 4/Uebung4_1/Ware.cpp | 9 ++++ Uebung 4/Uebung4_1/Ware.h | 46 +++++++++++++++++ Uebung 4/Uebung4_1/hashTable.cpp | 89 ++++++++++++++++++++++++++++++++ Uebung 4/Uebung4_1/hashTable.h | 54 +++++++++++++++++++ Uebung 4/Uebung4_1/main.cpp | 44 ++++++++++++++++ 6 files changed, 293 insertions(+) create mode 100644 Uebung 4/Uebung4_1/Makefile create mode 100644 Uebung 4/Uebung4_1/Ware.cpp create mode 100644 Uebung 4/Uebung4_1/Ware.h create mode 100644 Uebung 4/Uebung4_1/hashTable.cpp create mode 100644 Uebung 4/Uebung4_1/hashTable.h create mode 100644 Uebung 4/Uebung4_1/main.cpp diff --git a/Uebung 4/Uebung4_1/Makefile b/Uebung 4/Uebung4_1/Makefile new file mode 100644 index 0000000..b9b2de7 --- /dev/null +++ b/Uebung 4/Uebung4_1/Makefile @@ -0,0 +1,51 @@ + +# Name of the binary for Development +BINARY = main +# Name of the binary for Release +FINAL = prototyp +# Object files +OBJS = Ware.o hashTable.o main.o +# Compiler flags +CFLAGS = -Werror -Wall -std=c++17 -fsanitize=address,undefined -g +# Linker flags +LFLAGS = -fsanitize=address,undefined +#Which Compiler to use +COMPILER = c++ + + +# all target: builds all important targets +all: binary + +final : ${OBJS} + ${COMPILER} ${LFLAGS} -o ${FINAL} ${OBJS} + +binary : ${OBJS} + ${COMPILER} ${LFLAGS} -o ${BINARY} ${OBJS} + +# Links the binary +${BINARY} : ${OBJS} + ${COMPILER} ${LFLAGS} -o ${BINARY} ${OBJS} + + +# Compiles a source-file (any file with file extension .c) into an object-file +# +# "%" is a wildcard which matches every file-name (similar to * in regular expressions) +# Such a rule is called a pattern rule (because it matches a pattern, see https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html), +# which are a form of so called implicit rules (see https://www.gnu.org/software/make/manual/html_node/Implicit-Rules.html) +# "$@" and "$<" are so called automatic variables (see https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html) +%.o : %.cpp + ${COMPILER} -c ${CFLAGS} -o $@ $< + + +# Rules can not only be used for compiling a program but also for executing a program +run: ${BINARY} + ./${BINARY} + + +# Delete all build artifacts +clean : + rm -rf ${BINARY} ${OBJS} + + +# all and clean are a "phony" targets, meaning they are no files +.PHONY : all clean diff --git a/Uebung 4/Uebung4_1/Ware.cpp b/Uebung 4/Uebung4_1/Ware.cpp new file mode 100644 index 0000000..5bfd735 --- /dev/null +++ b/Uebung 4/Uebung4_1/Ware.cpp @@ -0,0 +1,9 @@ +#include "Ware.h" + +std::ostream &operator<<(std::ostream &out, const Ware &ware) { + out << "Name: " << ware.getBezeichnung() << ", SN: " << ware.getSeriennummer() + << ", Gewicht: " << ware.getGewicht() + << ", EK: " << ware.getEinkaufspreis() + << ", VK: " << ware.getVerkaufspreis(); + return out; +} \ No newline at end of file diff --git a/Uebung 4/Uebung4_1/Ware.h b/Uebung 4/Uebung4_1/Ware.h new file mode 100644 index 0000000..b072d56 --- /dev/null +++ b/Uebung 4/Uebung4_1/Ware.h @@ -0,0 +1,46 @@ +#pragma once +#include +#include + +class Ware { +private: + std::string bezeichnung; + int seriennummer; + double gewicht; + double einkaufspreis; + double verkaufspreis; + +public: + std::string getBezeichnung() const { return this->bezeichnung; } + + void setBezeichnung(std::string bezeichnung) { + this->bezeichnung = bezeichnung; + } + + int getSeriennummer() const { return this->seriennummer; } + + void setSeriennummer(int seriennummer) { this->seriennummer = seriennummer; } + + double getGewicht() const { return this->gewicht; } + + void setGewicht(double gewicht) { this->gewicht = gewicht; } + + double getEinkaufspreis() const { return this->einkaufspreis; } + + void setEinkaufspreis(double einkaufspreis) { + this->einkaufspreis = einkaufspreis; + } + + double getVerkaufspreis() const { return this->verkaufspreis; } + + void setVerkaufspreis(double verkaufspreis) { + this->verkaufspreis = verkaufspreis; + } + + Ware(std::string bezeichnung, int seriennummer, double gewicht, + double einkaufspreis, double verkaufspreis) + : bezeichnung(bezeichnung), seriennummer(seriennummer), gewicht(gewicht), + einkaufspreis(einkaufspreis), verkaufspreis(verkaufspreis) {} +}; + +std::ostream &operator<<(std::ostream &out, const Ware &ware); \ No newline at end of file diff --git a/Uebung 4/Uebung4_1/hashTable.cpp b/Uebung 4/Uebung4_1/hashTable.cpp new file mode 100644 index 0000000..c7abcb6 --- /dev/null +++ b/Uebung 4/Uebung4_1/hashTable.cpp @@ -0,0 +1,89 @@ +#include "hashTable.h" +#include + +HashTable::HashTable() { + this->size = 0; + this->entries = nullptr; + this->setHashFunction("firstTwoLetters"); +} + +HashTable::HashFunction::HashFunction(std::string name, + hashFunctionPtr algorithm, int size) { + this->name = name; + this->algorithm = algorithm; + this->size = size; +} + +void HashTable::insert(Ware *entry) { + int hashValue = this->hashFunction(entry->getBezeichnung()); + hashValue = hashValue % this->size; + HashNode node; + node.key = entry->getBezeichnung(); + node.ware = entry; + this->entries[hashValue].push_back(node); +} + +void HashTable::print() { + std::cout << "=====================================" << std::endl; + for (int i = 0; i < this->size; i++) { + std::cout << i << " :\t"; + for (auto it = this->entries[i].begin(); it != this->entries[i].end(); + it++) { + if (it != this->entries[i].begin()) { + std::cout << "\t|\t"; + } + std::cout << it->key; + } + std::cout << std::endl; + } + std::cout << "=====================================" << std::endl; +} + +void HashTable::setHashFunction(std::string algorithmName) { + for (int i = 0; i < 5; i++) { + if (this->availableAlgorithms[i].name == algorithmName) { + this->hashFunction = this->availableAlgorithms[i].algorithm; + this->size = this->availableAlgorithms[i].size; + if (this->entries != nullptr) { + delete[] this->entries; + } + this->entries = new std::list[this->size]; + return; + } + } + + std::cerr << "The Hash Function provided was not found!" << std::endl; +} + +const Ware *HashTable::search(std::string key) { + int hashValue = this->hashFunction( + key); // key is "hashed" and stored in the variable int hashValue + hashValue = hashValue % this->size; + for (auto it = this->entries[hashValue].begin(); + it != this->entries[hashValue].end(); it++) { + if (it->key == key) { + return it->ware; + } + } + std::cout << "Ware with bezeichnung " << key << " not found!" << std::endl; + return nullptr; +} + +bool HashTable::deleteItem(std::string key) { + int hashValue = this->hashFunction(key); + hashValue = hashValue % this->size; + + for (auto it = this->entries[hashValue].begin(); + it != this->entries[hashValue].end(); it++) { + if (it->key == key) { + delete it->ware; + it = this->entries[hashValue].erase(it); + return true; + } + } + return false; +} + +int firstTwoLetters(std::string bezeichnung) { + return (int)(bezeichnung[0] + bezeichnung[1]); +} diff --git a/Uebung 4/Uebung4_1/hashTable.h b/Uebung 4/Uebung4_1/hashTable.h new file mode 100644 index 0000000..fed6a83 --- /dev/null +++ b/Uebung 4/Uebung4_1/hashTable.h @@ -0,0 +1,54 @@ +#include "Ware.h" +#include +#include + +#pragma once +typedef int (*hashFunctionPtr)( + std::string); // typedefinition of a pointer for a hashfunction; they all + // need conform to the guideline: int + // (std::string ) + +int mod17(std::string telNr); // hash algorithm that takes a given telNr mod17 + +int firstTwoLetters(std::string bezeichnung); + +class HashTable { +private: + class HashFunction { // private inner class to make hash functions managable + public: + int size; + std::string name; + hashFunctionPtr algorithm; + + HashFunction(std::string name, hashFunctionPtr algorithm, + int size); // constructor + }; + + HashFunction availableAlgorithms[1] = { + {"firstTwoLetters", firstTwoLetters, 100}}; + + class HashNode { // private inner class for HashNodes that have a key (which + // will be the telephone number) and a value of type Ware + public: + std::string key = ""; + Ware *ware; + }; + +public: + int size; // m in lecture + int numberOfEntries; // n in lecture + std::list *entries; // nodes of the hash table + hashFunctionPtr hashFunction; // pointer to the hash algorithm used is stored + // in a private variable of type + // hashFunctionPtr - see beginning of this file + + void insert(Ware *entry); + const Ware *search(std::string key); + bool deleteItem(std::string key); + void print(); + void setHashFunction(std::string name); + + HashTable(); // default constructor + + int getHash(std::string bezeichnung) const; +}; \ No newline at end of file diff --git a/Uebung 4/Uebung4_1/main.cpp b/Uebung 4/Uebung4_1/main.cpp new file mode 100644 index 0000000..b70bb82 --- /dev/null +++ b/Uebung 4/Uebung4_1/main.cpp @@ -0,0 +1,44 @@ +#include "Ware.h" +#include "hashTable.h" +#include +#include + +// Function to generate random strings for our Wares. See: +// https://stackoverflow.com/a/12468109 +std::string random_string(size_t length) { + auto randchar = []() -> char { + const char charset[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + const size_t max_index = (sizeof(charset) - 1); + return charset[rand() % max_index]; + }; + std::string str(length, 0); + std::generate_n(str.begin(), length, randchar); + return str; +} + +int main() { + HashTable ht; + + // Insert 100 random Wares + for (int i = 0; i < 100; i++) { + ht.insert(new Ware(random_string(5), 123, 2.0, 2.0, 2.0)); + } + // Insert 2 additional ones with known Names + ht.insert(new Ware("Testware", 123, 2.0, 2.0, 2.0)); + ht.insert(new Ware("Foo", 123, 2.0, 2.0, 2.0)); + + ht.print(); + + // Search for one that should exist and print it. + const Ware *s1 = ht.search("Testware"); + std::cout << *s1 << std::endl; + + // Delete the Ware we found + bool test = ht.deleteItem("Testware"); + std::cout << test << std::endl; + + // Try to delete a Ware which does not exist. + bool test2 = ht.deleteItem("Bar"); + std::cout << test2 << std::endl; +}