Got everything, just need to change comments and do the menu
This commit is contained in:
149
.gitignore
vendored
Normal file
149
.gitignore
vendored
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
##Doxygen
|
||||||
|
docs
|
||||||
|
Doxyfile
|
||||||
|
images
|
||||||
|
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Linker files
|
||||||
|
*.ilk
|
||||||
|
|
||||||
|
# Debugger Files
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
*.so.*
|
||||||
|
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# Build directories
|
||||||
|
build/
|
||||||
|
Build/
|
||||||
|
build-*/
|
||||||
|
out
|
||||||
|
out/Debug
|
||||||
|
|
||||||
|
# CMake generated files
|
||||||
|
CMakeFiles/
|
||||||
|
CMakeCache.txt
|
||||||
|
cmake_install.cmake
|
||||||
|
Makefile
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*.tmp
|
||||||
|
*.log
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# vcpkg
|
||||||
|
vcpkg_installed/
|
||||||
|
|
||||||
|
# debug information files
|
||||||
|
*.dwo
|
||||||
|
|
||||||
|
# test output & cache
|
||||||
|
Testing/
|
||||||
|
.cache/Doxygen
|
||||||
|
docs
|
||||||
|
Doxyfile
|
||||||
|
images
|
||||||
|
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Linker files
|
||||||
|
*.ilk
|
||||||
|
|
||||||
|
# Debugger Files
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
*.so.*
|
||||||
|
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
# Build directories
|
||||||
|
build/
|
||||||
|
Build/
|
||||||
|
build-*/
|
||||||
|
|
||||||
|
# CMake generated files
|
||||||
|
CMakeFiles/
|
||||||
|
CMakeCache.txt
|
||||||
|
cmake_install.cmake
|
||||||
|
Makefile
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*.tmp
|
||||||
|
*.log
|
||||||
|
*.bak
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# vcpkg
|
||||||
|
vcpkg_installed/
|
||||||
|
|
||||||
|
# debug information files
|
||||||
|
*.dwo
|
||||||
|
|
||||||
|
# test output & cache
|
||||||
|
Testing/
|
||||||
|
.cache/
|
||||||
33
CMakeLists.txt
Normal file
33
CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
project(LinkedList
|
||||||
|
VERSION 1.0
|
||||||
|
LANGUAGES CXX
|
||||||
|
)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
|
add_compile_options(
|
||||||
|
-Wall
|
||||||
|
-Wextra
|
||||||
|
-Wpedantic
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
add_executable(main_exec
|
||||||
|
src/main.cpp
|
||||||
|
src/utils.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(main_exec
|
||||||
|
PRIVATE
|
||||||
|
${PROJECT_SOURCE_DIR}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
add_subdirectory(test)
|
||||||
352
include/linkedlist.h
Normal file
352
include/linkedlist.h
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
#ifndef LINKEDLIST_H
|
||||||
|
#define LINKEDLIST_H
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <expected>
|
||||||
|
#include <new>
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Codigos de error para operaciones de LinkedList
|
||||||
|
*/
|
||||||
|
enum class LinkedListErr {
|
||||||
|
LINKEDLIST_OK, /**< Operacin exitosa */
|
||||||
|
LINKEDLIST_BAD_ALLOC, /**< Error al asignar memoria */
|
||||||
|
LINKEDLIST_OUT_OF_BOUNDS, /**< Índice fuera de rango */
|
||||||
|
LINKESLIST_INVALID_SIZE, /**< Tamaño inválido */
|
||||||
|
LINKEDLIST_NOT_FOUND, /**< Elemento no encontrado */
|
||||||
|
LINKEDLIST_EMPTY, /**< La lista está vacia */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Nodo de una lista enlazada
|
||||||
|
*
|
||||||
|
* @tparam T Tipo de dato almacenado en el nodo
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class Node {
|
||||||
|
public:
|
||||||
|
T data; /**< Dato almacenado en el nodo */
|
||||||
|
Node<T> *next; /**< Puntero al siguiente nodo */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Implementación de una lista enlazada simple
|
||||||
|
*
|
||||||
|
* Estructura de datos dinamica que almacena elementos de tipo T
|
||||||
|
* utilizando nodos enlazados mediante punteros.
|
||||||
|
*
|
||||||
|
* @tparam T Tipo de dato almacenado en la lista
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class LinkedList {
|
||||||
|
private:
|
||||||
|
size_t size; /**< Numero de elementos en la lista */
|
||||||
|
Node<T> *head; /**< Primer nodo de la lista */
|
||||||
|
Node<T> *tail; /**< Último nodo de la lista */
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor de la lista enlazada
|
||||||
|
*/
|
||||||
|
LinkedList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor de la lista
|
||||||
|
*
|
||||||
|
* Libera toda la memoria de los nodos.
|
||||||
|
*/
|
||||||
|
~LinkedList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Obtiene el elemento en una posicion específica
|
||||||
|
*
|
||||||
|
* @param index indice del elemento
|
||||||
|
* @return std::expected<T, LinkedListErr> Valor encontrado o error
|
||||||
|
*/
|
||||||
|
std::expected<T, LinkedListErr> get(size_t index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inserta un elemento al final de la lista
|
||||||
|
*
|
||||||
|
* @param value Valor a insertar
|
||||||
|
* @return LinkedListErr Cdigo de estado de la operacion
|
||||||
|
*/
|
||||||
|
LinkedListErr append(const T& value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Inserta un elemento al inicio de la lista
|
||||||
|
*
|
||||||
|
* @param value Valor a insertar
|
||||||
|
* @return LinkedListErr Codigo de estado
|
||||||
|
*/
|
||||||
|
LinkedListErr prepend(const T& value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Elimina y devuelve el ultimo elemento de la lista
|
||||||
|
*
|
||||||
|
* @return std::expected<T, LinkedListErr> Elemento eliminado o error
|
||||||
|
*/
|
||||||
|
std::expected<T, LinkedListErr> pop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Elimina el elemento en una posicion especifica
|
||||||
|
*
|
||||||
|
* @param index Indice del elemento a eliminar
|
||||||
|
* @return LinkedListErr Codigo de estado
|
||||||
|
*/
|
||||||
|
LinkedListErr remove(size_t index);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modifica el valor de un elemento en un indice
|
||||||
|
*
|
||||||
|
* @param index Índice del elemento
|
||||||
|
* @param value Nuevo valor
|
||||||
|
* @return LinkedListErr Código de estado
|
||||||
|
*/
|
||||||
|
LinkedListErr set(size_t index, const T& value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Busca un valor dentro de la lista
|
||||||
|
*
|
||||||
|
* @param value Valor a buscar
|
||||||
|
* @return std::expected<size_t, LinkedListErr> Índice del elemento o error
|
||||||
|
*/
|
||||||
|
std::expected<size_t, LinkedListErr> find(const T& value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Imprime los elementos de la lista
|
||||||
|
*
|
||||||
|
* @return LinkedListErr Código de estado
|
||||||
|
*/
|
||||||
|
LinkedListErr print();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Verifica si la lista esta vacia
|
||||||
|
*
|
||||||
|
* @return true si la lista no contiene elementos
|
||||||
|
*/
|
||||||
|
bool is_empty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Obtiene el numero de elementos de la lista
|
||||||
|
*
|
||||||
|
* @return size_t Tamaño de la lista
|
||||||
|
*/
|
||||||
|
size_t len();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
LinkedList<T>::LinkedList() {
|
||||||
|
size = 0;
|
||||||
|
head = nullptr;
|
||||||
|
tail = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
LinkedList<T>::~LinkedList() {
|
||||||
|
Node<T> *current = this->head;
|
||||||
|
|
||||||
|
while (current != nullptr) {
|
||||||
|
Node<T> *temp = current;
|
||||||
|
current = current->next;
|
||||||
|
delete temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::expected<T, LinkedListErr> LinkedList<T>::get(size_t index) {
|
||||||
|
if (index >= this->size) {
|
||||||
|
return std::unexpected(LinkedListErr::LINKEDLIST_OUT_OF_BOUNDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == this->size - 1) {
|
||||||
|
return tail->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node<T> *current = this->head;
|
||||||
|
for (size_t i = 0; i < index ; i++) {
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return current->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
LinkedListErr LinkedList<T>::set(size_t index, const T& val) {
|
||||||
|
if (index >= this->size) {
|
||||||
|
return LinkedListErr::LINKEDLIST_OUT_OF_BOUNDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == this->size - 1) {
|
||||||
|
this->tail->data = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node<T> *current = this->head;
|
||||||
|
for (size_t i = 0; i < index; i++) {
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
current->data = val;
|
||||||
|
return LinkedListErr::LINKEDLIST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
LinkedListErr LinkedList<T>::append(const T& value) {
|
||||||
|
Node<T> *new_node = nullptr;
|
||||||
|
|
||||||
|
try {
|
||||||
|
new_node = new Node<T>;
|
||||||
|
} catch(std::bad_alloc&) {
|
||||||
|
return LinkedListErr::LINKEDLIST_BAD_ALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_node->data = value;
|
||||||
|
new_node->next = nullptr;
|
||||||
|
|
||||||
|
if (this->head == nullptr && this->tail == nullptr) {
|
||||||
|
this->head = new_node;
|
||||||
|
this->tail = this->head;
|
||||||
|
} else {
|
||||||
|
this->tail->next = new_node;
|
||||||
|
this->tail = this->tail->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->size += 1;
|
||||||
|
|
||||||
|
return LinkedListErr::LINKEDLIST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
LinkedListErr LinkedList<T>::prepend(const T& value) {
|
||||||
|
Node<T> *new_node = nullptr;
|
||||||
|
|
||||||
|
try {
|
||||||
|
new_node = new Node<T>;
|
||||||
|
} catch(std::bad_alloc&) {
|
||||||
|
return LinkedListErr::LINKEDLIST_BAD_ALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_node->data = value;
|
||||||
|
new_node->next = nullptr;
|
||||||
|
|
||||||
|
if (this->head == nullptr && this->tail == nullptr) {
|
||||||
|
this->head = new_node;
|
||||||
|
this->tail = this->head;
|
||||||
|
} else {
|
||||||
|
new_node->next = this->head;
|
||||||
|
this->head = new_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->size += 1;
|
||||||
|
|
||||||
|
return LinkedListErr::LINKEDLIST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::expected<T, LinkedListErr> LinkedList<T>::pop() {
|
||||||
|
if (this->size == 0) {
|
||||||
|
return std::unexpected(LinkedListErr::LINKEDLIST_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->head->next == nullptr) {
|
||||||
|
T return_val = this->head->data;
|
||||||
|
delete this->head;
|
||||||
|
this->head = nullptr;
|
||||||
|
this->size--;
|
||||||
|
return return_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node<T>* current = this->head;
|
||||||
|
|
||||||
|
while (current->next->next != nullptr) {
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
T return_val = current->next->data;
|
||||||
|
delete current->next;
|
||||||
|
current->next = nullptr;
|
||||||
|
|
||||||
|
this->size--;
|
||||||
|
|
||||||
|
return return_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
LinkedListErr LinkedList<T>::remove(size_t index) {
|
||||||
|
if (index >= this->size) {
|
||||||
|
return LinkedListErr::LINKEDLIST_OUT_OF_BOUNDS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
Node<T>* tmp = this->head;
|
||||||
|
this->head = this->head->next;
|
||||||
|
delete tmp;
|
||||||
|
this->size--;
|
||||||
|
return LinkedListErr::LINKEDLIST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node<T>* current = this->head;
|
||||||
|
|
||||||
|
for (size_t i = 1; i < index; ++i) {
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node<T>* tmp = current->next;
|
||||||
|
current->next = tmp->next;
|
||||||
|
|
||||||
|
if(tmp == this->tail) {
|
||||||
|
this->tail = current;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete tmp;
|
||||||
|
this->size--;
|
||||||
|
|
||||||
|
return LinkedListErr::LINKEDLIST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::expected<size_t, LinkedListErr> LinkedList<T>::find(const T& value) {
|
||||||
|
Node<T> *current = this->head;
|
||||||
|
size_t count = 0;
|
||||||
|
while (current != nullptr) {
|
||||||
|
if (current->data == value) {
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
count++;
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::unexpected(LinkedListErr::LINKEDLIST_NOT_FOUND);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
LinkedListErr LinkedList<T>::print() {
|
||||||
|
if (this->size == 0) {
|
||||||
|
return LinkedListErr::LINKEDLIST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::println("[LL]");
|
||||||
|
std::println(" |\n v");
|
||||||
|
Node<T> *current = this->head;
|
||||||
|
while (current != nullptr) {
|
||||||
|
std::println("Node({})", current->data);
|
||||||
|
std::println(" |");
|
||||||
|
std::println(" v");
|
||||||
|
current = current->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::println("NULL");
|
||||||
|
return LinkedListErr::LINKEDLIST_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
size_t LinkedList<T>::len() {
|
||||||
|
return this->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // !
|
||||||
14
include/utils.h
Normal file
14
include/utils.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
void clear_screen();
|
||||||
|
void wait_enter();
|
||||||
|
void sleep_seconds(size_t s);
|
||||||
|
void read_string(const char *message, char **dest);
|
||||||
|
int read_int(const char *message, int *dest);
|
||||||
|
int read_double(const char *message, double *dest);
|
||||||
|
|
||||||
|
#endif // !
|
||||||
8
src/main.cpp
Normal file
8
src/main.cpp
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "linkedlist.h"
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <print>
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
std::print("hi");
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
129
src/utils.cpp
Normal file
129
src/utils.cpp
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
void clear_screen() {
|
||||||
|
printf("\033[2J\033[H");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait_enter() {
|
||||||
|
int c;
|
||||||
|
printf("Press Enter to continue...");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
while ((c = getchar()) != '\n' && c != EOF) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sleep_seconds(size_t s) {
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
Sleep(s * 1000);
|
||||||
|
#else
|
||||||
|
// #include <unistd.h>
|
||||||
|
// sleep(s);
|
||||||
|
#endif /* ifdef _WIN32
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_string(const char *message, char **dest) {
|
||||||
|
if (!dest) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s", message);
|
||||||
|
|
||||||
|
char buffer[256]; // I mean, should be enough
|
||||||
|
if (!fgets(buffer, sizeof(buffer), stdin))
|
||||||
|
return;
|
||||||
|
|
||||||
|
buffer[strcspn(buffer, "\n")] = '\0';
|
||||||
|
|
||||||
|
char *tmp = static_cast<char *>(malloc(strlen(buffer) + 1));
|
||||||
|
if (!tmp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(tmp, buffer);
|
||||||
|
|
||||||
|
free(*dest);
|
||||||
|
*dest = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_int(const char *message, int *dest) {
|
||||||
|
char buffer[64];
|
||||||
|
char *end;
|
||||||
|
long value;
|
||||||
|
|
||||||
|
printf("%s", message);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
if (!fgets(buffer, sizeof(buffer), stdin)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
value = strtol(buffer, &end, 10);
|
||||||
|
|
||||||
|
if (errno != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end == buffer) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*end != '\n' && *end != '\0') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < INT_MIN || value > INT_MAX) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest = (int)value;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int read_double(const char *message, double *dest) {
|
||||||
|
char buffer[64];
|
||||||
|
char *end;
|
||||||
|
double value;
|
||||||
|
|
||||||
|
printf("%s", message);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
if (!fgets(buffer, sizeof(buffer), stdin)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
value = strtod(buffer, &end);
|
||||||
|
|
||||||
|
if (errno != 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end == buffer) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*end != '\n' && *end != '\0') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isfinite(value)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest = value;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
38
test/CMakeLists.txt
Normal file
38
test/CMakeLists.txt
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
include(FetchContent)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
Catch2
|
||||||
|
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||||
|
GIT_TAG v3.5.3
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(Catch2)
|
||||||
|
|
||||||
|
add_executable(test_linkedlist
|
||||||
|
test_linkedlist.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(test_linkedlist
|
||||||
|
PRIVATE
|
||||||
|
${PROJECT_SOURCE_DIR}/include
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(test_linkedlist
|
||||||
|
PRIVATE
|
||||||
|
Catch2::Catch2WithMain
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_options(test_linkedlist PRIVATE
|
||||||
|
-fsanitize=address
|
||||||
|
-fno-omit-frame-pointer
|
||||||
|
-g
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_options(test_linkedlist PRIVATE
|
||||||
|
-fsanitize=address
|
||||||
|
)
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
include(Catch)
|
||||||
|
|
||||||
|
catch_discover_tests(test_linkedlist)
|
||||||
249
test/test_linkedlist.cpp
Normal file
249
test/test_linkedlist.cpp
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
#include "linkedlist.h"
|
||||||
|
#include <catch2/catch_test_macros.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("Append 3 items to linkedlist", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Prepend 3 items to linkedlist", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.prepend(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.prepend(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(0) == 9);
|
||||||
|
|
||||||
|
list.prepend(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(0) == 10);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Get out ouf bounds item", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
auto result = list.get(50);
|
||||||
|
REQUIRE(!result.has_value());
|
||||||
|
REQUIRE(result.error() == LinkedListErr::LINKEDLIST_OUT_OF_BOUNDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Set head to val", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
auto result = list.set(0, 90);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(result == LinkedListErr::LINKEDLIST_OK);
|
||||||
|
REQUIRE(list.get(0) == 90);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Set tail to val", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
auto result = list.set(2, 90);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(result == LinkedListErr::LINKEDLIST_OK);
|
||||||
|
REQUIRE(list.get(2) == 90);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Set to out of bounds", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
auto result = list.set(50, 90);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(result == LinkedListErr::LINKEDLIST_OUT_OF_BOUNDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Pop element", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
REQUIRE(list.pop() == 10);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Pop empty", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
auto result = list.pop();
|
||||||
|
REQUIRE(result.error() == LinkedListErr::LINKEDLIST_EMPTY);
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Remove head", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
auto result = list.remove(0);
|
||||||
|
REQUIRE(result == LinkedListErr::LINKEDLIST_OK);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(0) == 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Remove tail", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
auto result = list.remove(2);
|
||||||
|
REQUIRE(result == LinkedListErr::LINKEDLIST_OK);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Find 1 value present", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
auto result = list.find(9);
|
||||||
|
REQUIRE(result == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Find 1 value not present", "[linkedlist]") {
|
||||||
|
LinkedList<int> list = {};
|
||||||
|
|
||||||
|
REQUIRE(list.len() == 0);
|
||||||
|
|
||||||
|
list.append(8);
|
||||||
|
REQUIRE(list.len() == 1);
|
||||||
|
REQUIRE(list.get(0) == 8);
|
||||||
|
|
||||||
|
list.append(9);
|
||||||
|
REQUIRE(list.len() == 2);
|
||||||
|
REQUIRE(list.get(1) == 9);
|
||||||
|
|
||||||
|
list.append(10);
|
||||||
|
REQUIRE(list.len() == 3);
|
||||||
|
REQUIRE(list.get(2) == 10);
|
||||||
|
|
||||||
|
auto result = list.find(80);
|
||||||
|
REQUIRE(result.error() == LinkedListErr::LINKEDLIST_NOT_FOUND);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user