From 45336b083c48ec823bb405d69b39c5260af8c0a8 Mon Sep 17 00:00:00 2001 From: paulusja Date: Thu, 29 Oct 2026 11:15:04 +0100 Subject: [PATCH] Add file io solutions. --- 04_dateien/main.c | 54 +++++++++--------- 04_dateien/namesarchive.c | 113 ++++++++++++++++++++++++++++++++++---- 04_dateien/namesarchive.h | 17 ++++-- 3 files changed, 143 insertions(+), 41 deletions(-) diff --git a/04_dateien/main.c b/04_dateien/main.c index 707755c..849cc64 100644 --- a/04_dateien/main.c +++ b/04_dateien/main.c @@ -1,11 +1,8 @@ /* - * Verwenden Sie Ihre Lösung für das Namensarchiv mittels eines binären Suchbaums. Ergänzen Sie das Modul um zwei Funktionen, - * mit denen das bestehende Archiv um Namen erweitert wird, die in einer vorhandenen Textdatei stehen, bzw. den Inhalt des Archivs - * in eine bestimmte Textdatei sortiert speichern. Details entnehmen Sie wieder der namesarchive.h. - * - * Welcher Nachteil ergibt sich für einen binären Suchbaum, wenn beliebige Namen zunächst aus einer Datei eingelesen werden, - * sortiert wieder in Datei geschrieben werden und anschließend wieder neu aus der Datei geladen werden? - * (Also im Prinzip bei der zweiten Ausführung des untenstehenden Programms) + * Vervollständigen Sie das untenstehende Programm, indem Sie das Modul namesarchive in der + * namesarchive.h bzw. namesarchive.c implementieren. + * Die öffentlichen Schnittstellen mit genaueren Details entnehmen Sie der namesarchive.h. + * Das Programm soll das Modul als dynamische Laufzeitbibliothek nutzen. * */ @@ -21,14 +18,34 @@ char *inputName(const char *promptText, char *buffer, unsigned int bufferSize); int main() { char buffer[MAX_BUFFER_LEN]; - const char *filePath = "names.txt"; - if(!loadArchive(filePath)) + loadArchive("archive.txt"); + + while((inputName("Namen hinzufuegen: ", buffer, MAX_BUFFER_LEN) != NULL) && (strlen(buffer) > 0)) { - printf("Die Textdatei %s konnte nicht geladen werden.\n", filePath); + if(addName(buffer)) + printf("%s wurde dem Archiv hinzugefuegt.\n", buffer); + else + printf("Fehler! %s konnte nicht hinzugefuegt werden.\n", buffer); } - printf("\nNach Laden:\n"); + printf("\nNach Eingabe:\n"); + printNames(); + + printf("\nNach Sortierung:\n"); + sortNames(); + printNames(); + printf("\n"); + + while((inputName("Namen sortiert hinzufuegen: ", buffer, MAX_BUFFER_LEN) != NULL) && (strlen(buffer) > 0)) + { + if(addNameSorted(buffer)) + printf("%s wurde dem Archiv hinzugefuegt.\n", buffer); + else + printf("Fehler! %s konnte nicht hinzugefuegt werden.\n", buffer); + } + + printf("\nNach sortierter Eingabe:\n"); printNames(); printf("\n"); @@ -42,21 +59,8 @@ int main() printf("\nNach Entfernen:\n"); printNames(); - printf("\n"); - if(saveArchive(filePath)) - { - printf("Archiv erfolgreich unter %s gespeichert.\n", filePath); - } - else - { - printf("Fehler beim Speichern des Archivs unter %s.\n", filePath); - } - - printf("\nGebe Speicher frei ...\n"); - clearArchive(); - - printf("Beende Programm ...\n"); + saveArchive("archive.txt"); return EXIT_SUCCESS; } diff --git a/04_dateien/namesarchive.c b/04_dateien/namesarchive.c index 0424bcd..bfd1aa8 100644 --- a/04_dateien/namesarchive.c +++ b/04_dateien/namesarchive.c @@ -3,8 +3,30 @@ #include #include "namesarchive.h" -// Fügt einen Namen hinzu. Im Fehlerfall soll 0, ansonsten 1 zurückgegeben werden. +static char names[MAX_PERSONS][MAX_NAME_LEN]; +static unsigned int numberOfPersons = 0; + +static int findPersonIdx(const char *name); +static void removePersonByIdx(unsigned int idx); +static int compareNames(const void *arg1, const void *arg2); + +// Fügt einen Namen hinzu. Im Fehlerfall (Archiv ist voll) soll 0, ansonsten 1 zurückgegeben werden. +// Ist der angegebene Name länger als die zulässige Namenslänge, wird der Name abgeschnitten hinzugefügt. Rückgabe ist dann 1. int addName(const char *name) +{ + if(numberOfPersons < MAX_PERSONS) + { + strncpy(names[numberOfPersons], name, MAX_NAME_LEN); + names[numberOfPersons][MAX_NAME_LEN-1] = '\0'; + numberOfPersons++; + return 1; + } + else + return 0; +} + +// Wie addName. Fügt Namen aber direkt sortiert hinzu. Voraussetzung ist ein bereits sortiertes Archiv. +int addNameSorted(const char *name) { return 0; } @@ -12,29 +34,98 @@ int addName(const char *name) // Entfernt den angegebenen Namen. Gibt bei Erfolg 1 zurück, ansonsten 0 (Name konnte nicht gefunden werden). int removeName(const char *name) { - return 0; + int nameIdx = findPersonIdx(name); + + if(nameIdx >= 0) + { + removePersonByIdx(nameIdx); + return 1; + } + else + return 0; +} + +int findPersonIdx(const char *name) +{ + for(int i = 0; i < numberOfPersons; i++) + { + if(strcmp(names[i], name) == 0) + { + return i; + } + } + return -1; +} + +void removePersonByIdx(unsigned int idx) +{ + for(unsigned i = idx+1; i < numberOfPersons; i++) + { + strncpy(names[i-1], names[i], MAX_NAME_LEN); + names[i-1][MAX_NAME_LEN-1] = '\0'; + } + numberOfPersons--; +} + +int compareNames(const void *arg1, const void *arg2) +{ + const char (*name1)[MAX_NAME_LEN] = arg1; + const char (*name2)[MAX_NAME_LEN] = arg2; + + return strcmp(*name1, *name2); +} + +// Sortiert die Namen im Archiv aufsteigend. +void sortNames() +{ + qsort(names, numberOfPersons, sizeof(names[0]), compareNames); } // Gibt die Namen zeilenweise aus. void printNames() { - -} - -// Leert das Archiv -void clearArchive() -{ - + for(int i = 0; i < numberOfPersons; i++) + { + printf("%s\n", names[i]); + } } // Lädt den Inhalt einer Textdatei zeilenweise in das Archiv. Gibt 1 bei Erfolg zurück. int loadArchive(const char *path) { - return 0; + FILE *file = fopen(path, "r"); + char buffer[MAX_NAME_LEN]; + + if(file != NULL) + { + while(fgets(buffer, sizeof(buffer), file) != NULL) + { + if(buffer[strlen(buffer)-1] == '\n') + buffer[strlen(buffer)-1] = '\0'; + + addName(buffer); + } + + fclose(file); + } + + return file != NULL; } // Speichert das Archiv zeilenweise in einer Textdatei. Gibt 1 bei Erfolg zurück. int saveArchive(const char *path) { - return 0; + FILE *file = fopen(path, "w"); + + if(file != NULL) + { + for(int i = 0; i < numberOfPersons; i++) + { + fprintf(file, "%s\n", names[i]); + } + + fclose(file); + } + + return file != NULL; } diff --git a/04_dateien/namesarchive.h b/04_dateien/namesarchive.h index 0dd121a..a553dfc 100644 --- a/04_dateien/namesarchive.h +++ b/04_dateien/namesarchive.h @@ -1,17 +1,24 @@ #ifndef NAMEARCHIVE_H #define NAMEARCHIVE_H -#define MAX_NAME_LEN 100 +// Maximale Namenslänge +#define MAX_NAME_LEN 10 -// Fügt einen Namen hinzu. Im Fehlerfall (kein Speicher mehr) soll 0, ansonsten 1 zurückgegeben werden. -// Der Name soll in beliebiger Länge gespeichert werden können. +// Maximale Anzahl an Namen +#define MAX_PERSONS 100 + +// Fügt einen Namen hinzu. Im Fehlerfall (Archiv ist voll) soll 0, ansonsten 1 zurückgegeben werden. +// Ist der angegebene Name länger als die zulässige Namenslänge, wird der Name abgeschnitten hinzugefügt. Rückgabe ist dann 1. int addName(const char *name); +// Wie addName. Fügt Namen aber direkt sortiert hinzu. Voraussetzung ist ein bereits sortiertes Archiv. +int addNameSorted(const char *name); // Entfernt den angegebenen Namen. Gibt bei Erfolg 1 zurück, ansonsten 0 (Name konnte nicht gefunden werden). int removeName(const char *name); +// Sortiert die Namen im Archiv aufsteigend. +void sortNames(); // Gibt die Namen zeilenweise aus. void printNames(); -// Leert das Archiv -void clearArchive(); + // Lädt den Inhalt einer Textdatei zeilenweise in das Archiv. Gibt 1 bei Erfolg zurück. int loadArchive(const char *path); // Speichert das Archiv zeilenweise in einer Textdatei. Gibt 1 bei Erfolg zurück.