From b74f99e10baf6baea3082da67c31a69a1b1f8073 Mon Sep 17 00:00:00 2001 From: b0rbor4d Date: Wed, 15 Apr 2026 00:26:05 +0200 Subject: [PATCH] Add Checkpoint solution: checkpoint_c.c --- exercises/checkpoint_c.c | 317 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 exercises/checkpoint_c.c diff --git a/exercises/checkpoint_c.c b/exercises/checkpoint_c.c new file mode 100644 index 0000000..760db69 --- /dev/null +++ b/exercises/checkpoint_c.c @@ -0,0 +1,317 @@ +// ============================================ +// Checkpoint C: Dynamische Liste (Vector) +// Lösung für Selbsttest nach Modul 5-6 +// Implementierung wie C++ std::vector +// ============================================ + +#include +#include +#include + +// ============================================ +// DATENSTRUKTUR: Vector (wie std::vector) +// ============================================ +typedef struct { + int* data; // Pointer zum Array + int size; // Aktuelle Anzahl Elemente + int capacity; // Maximale Kapazität +} Vector; + +// ============================================ +// KONSTRUKTOR / DESTRUKTOR +// ============================================ + +// Erstellt neuen Vector mit gegebener Kapazität +Vector* vector_create(int initial_capacity) { + Vector* vec = malloc(sizeof(Vector)); + if (!vec) return NULL; + + vec->data = malloc(initial_capacity * sizeof(int)); + if (!vec->data) { + free(vec); + return NULL; + } + + vec->size = 0; + vec->capacity = initial_capacity; + return vec; +} + +// Zerstört Vector und gibt Speicher frei +void vector_destroy(Vector* vec) { + if (vec) { + free(vec->data); // Array freigeben + free(vec); // Struct freigeben + } +} + +// ============================================ +// KAPAZITÄTS-MANAGEMENT +// ============================================ + +// Verdoppelt Kapazität wenn nötig (privat) +static void vector_grow(Vector* vec) { + if (vec->size >= vec->capacity) { + int new_capacity = vec->capacity * 2; + int* new_data = realloc(vec->data, new_capacity * sizeof(int)); + + if (new_data) { + vec->data = new_data; + vec->capacity = new_capacity; + printf("[Info] Kapazität erhöht: %d -> %d\n", vec->capacity / 2, vec->capacity); + } + } +} + +// ============================================ +// ELEMENT-OPERATIONEN +// ============================================ + +// Fügt Element am Ende hinzu +void vector_push_back(Vector* vec, int value) { + vector_grow(vec); // Automatisch wachsen + vec->data[vec->size] = value; + vec->size++; +} + +// Entfernt letztes Element +int vector_pop_back(Vector* vec) { + if (vec->size == 0) { + printf("[Fehler] Vector ist leer!\n"); + return -1; + } + vec->size--; + return vec->data[vec->size]; +} + +// Greift auf Element zu (mit Bounds-Check) +int vector_get(const Vector* vec, int index) { + if (index < 0 || index >= vec->size) { + printf("[Fehler] Index %d außerhalb [0, %d]!\n", index, vec->size - 1); + return -1; // Fehlerwert + } + return vec->data[index]; +} + +// Setzt Element (mit Bounds-Check) +void vector_set(Vector* vec, int index, int value) { + if (index < 0 || index >= vec->size) { + printf("[Fehler] Index %d außerhalb [0, %d]!\n", index, vec->size - 1); + return; + } + vec->data[index] = value; +} + +// Fügt Element an Position ein (verschiebt Rest) +void vector_insert(Vector* vec, int index, int value) { + if (index < 0 || index > vec->size) { + printf("[Fehler] Ungültiger Index!\n"); + return; + } + + vector_grow(vec); + + // Elemente verschieben + for (int i = vec->size; i > index; i--) { + vec->data[i] = vec->data[i - 1]; + } + + vec->data[index] = value; + vec->size++; +} + +// Entfernt Element an Position +void vector_erase(Vector* vec, int index) { + if (index < 0 || index >= vec->size) { + printf("[Fehler] Ungültiger Index!\n"); + return; + } + + // Elemente verschieben + for (int i = index; i < vec->size - 1; i++) { + vec->data[i] = vec->data[i + 1]; + } + + vec->size--; +} + +// Sucht Element, gibt Index zurück oder -1 +int vector_find(const Vector* vec, int value) { + for (int i = 0; i < vec->size; i++) { + if (vec->data[i] == value) { + return i; + } + } + return -1; +} + +// ============================================ +// HILFSFUNKTIONEN +// ============================================ + +// Gibt aktuelle Größe zurück +int vector_size(const Vector* vec) { + return vec->size; +} + +// Prüft ob leer +int vector_empty(const Vector* vec) { + return vec->size == 0; +} + +// Leert den Vector (ohne Speicher freizugeben) +void vector_clear(Vector* vec) { + vec->size = 0; +} + +// Gibt alle Elemente aus +void vector_print(const Vector* vec) { + printf("["); + for (int i = 0; i < vec->size; i++) { + printf("%d", vec->data[i]); + if (i < vec->size - 1) printf(", "); + } + printf("] (size=%d, capacity=%d)\n", vec->size, vec->capacity); +} + +// ============================================ +// TEST-FUNKTIONEN +// ============================================ + +void test_basic_operations() { + printf("\n=== TEST 1: Grundoperationen ===\n"); + + Vector* vec = vector_create(2); + + printf("Push: 10, 20, 30\n"); + vector_push_back(vec, 10); + vector_push_back(vec, 20); + vector_push_back(vec, 30); // Trigger grow + vector_print(vec); + + printf("Get[1]: %d\n", vector_get(vec, 1)); + printf("Set[1] = 25\n"); + vector_set(vec, 1, 25); + vector_print(vec); + + printf("Pop: %d\n", vector_pop_back(vec)); + vector_print(vec); + + vector_destroy(vec); + printf("✓ Test 1 bestanden\n\n"); +} + +void test_insert_erase() { + printf("=== TEST 2: Insert & Erase ===\n"); + + Vector* vec = vector_create(5); + vector_push_back(vec, 1); + vector_push_back(vec, 2); + vector_push_back(vec, 4); + vector_push_back(vec, 5); + + printf("Vorher: "); + vector_print(vec); + + printf("Insert 3 an Index 2\n"); + vector_insert(vec, 2, 3); + vector_print(vec); + + printf("Erase Index 1\n"); + vector_erase(vec, 1); + vector_print(vec); + + vector_destroy(vec); + printf("✓ Test 2 bestanden\n\n"); +} + +void test_edge_cases() { + printf("=== TEST 3: Edge Cases ===\n"); + + Vector* vec = vector_create(3); + + printf("Leerer Vector: "); + vector_print(vec); + printf("Empty? %s\n", vector_empty(vec) ? "Ja" : "Nein"); + + printf("Pop auf leerem Vector:\n"); + vector_pop_back(vec); // Sollte Fehler ausgeben + + printf("Get mit ungültigem Index:\n"); + int val = vector_get(vec, 0); // Sollte Fehler ausgeben + printf("Rückgabe: %d\n", val); + + printf("Fill bis zur Kapazität\n"); + for (int i = 1; i <= 10; i++) { + vector_push_back(vec, i); + } + vector_print(vec); + + printf("Find 7: Index %d\n", vector_find(vec, 7)); + printf("Find 99: Index %d\n", vector_find(vec, 99)); + + vector_destroy(vec); + printf("✓ Test 3 bestanden\n\n"); +} + +void test_clear() { + printf("=== TEST 4: Clear ===\n"); + + Vector* vec = vector_create(5); + for (int i = 0; i < 5; i++) { + vector_push_back(vec, i * 10); + } + + printf("Vor clear: "); + vector_print(vec); + + vector_clear(vec); + printf("Nach clear: "); + vector_print(vec); + + printf("Nochmal befüllen:\n"); + vector_push_back(vec, 100); + vector_print(vec); + + vector_destroy(vec); + printf("✓ Test 4 bestanden\n\n"); +} + +// ============================================ +// HAUPTPROGRAMM +// ============================================ +int main() { + printf("╔══════════════════════════════════════════════════════════╗\n"); + printf("║ CHECKPOINT C: DYNAMISCHE LISTE (LÖSUNG) ║\n"); + printf("║ Eigene Vector-Implementierung wie C++ STL ║\n"); + printf("╚══════════════════════════════════════════════════════════╝\n\n"); + + printf("Implementierte Funktionen:\n"); + printf(" ✓ vector_create / vector_destroy\n"); + printf(" ✓ vector_push_back (automatisch wachsen)\n"); + printf(" ✓ vector_pop_back\n"); + printf(" ✓ vector_get / vector_set (mit Bounds-Check)\n"); + printf(" ✓ vector_insert / vector_erase\n"); + printf(" ✓ vector_find\n"); + printf(" ✓ vector_size / vector_empty / vector_clear\n"); + printf(" ✓ vector_print\n\n"); + + // Alle Tests ausführen + test_basic_operations(); + test_insert_erase(); + test_edge_cases(); + test_clear(); + + printf("╔══════════════════════════════════════════════════════════╗\n"); + printf("║ ALLE TESTS BESTANDEN! ║\n"); + printf("╠══════════════════════════════════════════════════════════╣\n"); + printf("║ Lernziele erreicht: ║\n"); + printf("║ ✓ Dynamische Arrays (malloc/realloc/free) ║\n"); + printf("║ ✓ Automatische Kapazitätsverwaltung ║\n"); + printf("║ ✓ Bounds-Checking für Sicherheit ║\n"); + printf("║ ✓ Array-Elemente verschieben (insert/erase) ║\n"); + printf("║ ✓ Modularer Aufbau (struct + Funktionen) ║\n"); + printf("╚══════════════════════════════════════════════════════════╝\n"); + + return 0; +}