diff --git a/01_strings/anfangsbuchstabe.c b/01_strings/anfangsbuchstabe.c new file mode 100644 index 0000000..6989816 --- /dev/null +++ b/01_strings/anfangsbuchstabe.c @@ -0,0 +1,31 @@ +/* + * Schreiben Sie eine Funktion schreibeAnfangGross, die eine Zeichenkette übergeben bekommt, den Anfangsbuchstaben jedes Wortes groß + * schreibt und einen Zeiger auf den Anfang dieser Zeichenkette zurückgibt. Nutzen Sie für die Eingabe die Eingabefunktion aus + * einer der vorherigen Übungen. + * + * Möglicher Programmablauf: + * >> Geben Sie einen Text nur mit Kleinbuchstaben ein: das ist das haus vom nikolaus. und nebendran wohnt der weihnachtsmann. + * Der bearbeitete Text lautet: + * "Das Ist Das Haus Vom Nikolaus. Und Nebendran Wohnt Der Weihnachtsmann." + */ + +#include +#include +#include +#include +#include "eingabe.h" + +#define MAX_TEXT_LEN 100 + +char *schreibeAnfangGross(char *text, int maxZeichen); + +int main() +{ + char text[MAX_TEXT_LEN] = ""; + + gibTextEin("Geben Sie einen Text nur mit Kleinbuchstaben ein: ", text, MAX_TEXT_LEN); + + printf("Der bearbeitete Text lautet:\n\"%s\"\n", schreibeAnfangGross(text, MAX_TEXT_LEN)); + + return EXIT_SUCCESS; +} diff --git a/01_strings/eingabeTest.c b/01_strings/eingabeTest.c new file mode 100644 index 0000000..58cf7a0 --- /dev/null +++ b/01_strings/eingabeTest.c @@ -0,0 +1,42 @@ +/* + * Legen Sie in einer Datei eingabe.h bzw. eingabe.c die Funktion gibTextEin an, die eine Zeichenkette übergeben bekommt, + * die vor der Eingabe angezeigt wird, einen Puffer, in dem die eingelesene Zeichenkette gespeichert wird, + * und die Größe des Puffers, die die Anzahl an einzulesenden Zeichen darstellt (inklusive Zeilenumbruch und abschließendem + * Null-Zeichen). Die Funktion soll genau eine Zeile Text einlesen. Zudem soll die Funktion prüfen, ob noch Zeichen im + * Eingabepuffer liegen und in diesem Fall den Eingabepuffer leeren. Im Fehlerfall gibt die Funktion 0 zurück, ansonsten 1. Die + * eingelesene Zeichenkette soll den Zeilenumbruch zur Bestätigung der Eingabe nicht enthalten. Nutzen Sie zum Einlesen bitte fgets. + */ + +#include +#include +#include "eingabe.h" + +#define MAX_EINGABE_LEN 10 + +int main() +{ + char testChar; + char eingabeText[MAX_EINGABE_LEN]; + + printf("Zum Testen bitte bei einem Programmdurchlauf weniger und beim naechsten mehr als %d Zeichen eingeben und jeweils mit ENTER bestaetigen.\n", MAX_EINGABE_LEN-1); + + if(gibTextEin("Eingabe: ", eingabeText, MAX_EINGABE_LEN)) + { + printf("Die Eingabe lautet \"%s\". Es sollte kein Zeilenumbruch auftreten.\n", eingabeText); + printf("Wenn alles korrekt implementiert ist, sollte das Programm jetzt nur auf ein ENTER warten und die Ausgabe dann unten leer sein.\n"); + printf("Rest im Eingabepuffer: "); + while((testChar = getchar()) != '\n') + { + printf("%c", testChar); + } + printf("\n"); + } + else + { + printf("Beim Einlesen ist ein Fehler aufgetreten.\n"); + + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/01_strings/fehler.c b/01_strings/fehler.c new file mode 100644 index 0000000..86f73ef --- /dev/null +++ b/01_strings/fehler.c @@ -0,0 +1,78 @@ +/* + * Untersuchen Sie das folgende Programm zunächst ohne es zu kompilieren oder auszuführen. + * Welche Funktionen sind fehlerfrei? + * Handelt es sich im Falle eines Fehlers um einen Laufzeitfehler oder um einen Compiler-Fehler? + * + * Hinweise: + * Compiler-Fehler treten beim Kompilieren des Programms auf. Das Programm lässt sich also + * gar nicht erst übersetzen. + * Bei Laufzeitfehlern lässt sich das Programm (u.U. mit Warnungen) übersetzen. Der Fehler tritt + * erst zur Laufzeit auf. Auch wenn der Fehler nicht immer auftritt bzw. das Programm zum Absturz + * bringt, handelt es sich dennoch um einen Laufzeitfehler. Beliebte Laufzeitfehler sind z.B. Pufferüberläufe. + */ + +#include +#include + +void kopiereString1() +{ + char string1[] = "123456\n"; + char string2[] = "789\n"; + char *stringZgr1 = string1; + char *stringZgr2 = string2; + + while((*stringZgr2++ = *stringZgr1++) != '\0'); + + printf(string1); + printf(string2); +} + +void kopiereString2() +{ + char string1[] = "123456\n"; + char string2[] = "789\n"; + char *stringZgr1 = string1; + char *stringZgr2 = string2; + + while((*stringZgr1++ = *stringZgr2++) != '\0'); + + printf(string1); + printf(string2); +} + +void kopiereString3() +{ + char string1[] = "123456\n"; + char string2[] = "789\n"; + + while((*string1++ = *string2++) != '\0'); + + printf(string1); + printf(string2); +} + +void kopiereString4() +{ + char *string1 = "123456\n"; + char *string2 = "789\n"; + + while((*string1++ = *string2++) != '\0'); + + printf(string1); + printf(string2); +} + +int main() +{ + printf("kopiereString1:\n"); + kopiereString1(); + + printf("kopiereString2:\n"); + kopiereString2(); + + printf("kopiereString3:\n"); + kopiereString3(); + + printf("kopiereString4:\n"); + kopiereString4(); +} \ No newline at end of file diff --git a/01_strings/laengen.c b/01_strings/laengen.c new file mode 100644 index 0000000..39c363b --- /dev/null +++ b/01_strings/laengen.c @@ -0,0 +1,38 @@ +/* + * Was gibt folgendes Programm aus? Überlegen Sie sich erst Ihre Antworten. + * Kompilieren und führen Sie erst danach das Programm aus. + * Wie erklären Sie sich die Ausgaben? + */ + +#include +#include +#include + +void gibLaengenAus(char string[]); + +int main() +{ + char *string1 = "12345"; + char string2[] = "12345"; + char string3[10] = "12345"; + + printf("strlen(string1) = %2d\n", (int)strlen(string1)); + printf("strlen(string2) = %2d\n", (int)strlen(string2)); + printf("strlen(string3) = %2d\n", (int)strlen(string3)); + printf("\n"); + printf("sizeof(string1) = %2d\n", (int)sizeof(string1)); + printf("sizeof(string2) = %2d\n", (int)sizeof(string2)); + printf("sizeof(string3) = %2d\n", (int)sizeof(string3)); + printf("\n"); + printf("gibLaengenAus(string3):\n"); + + gibLaengenAus(string3); + + return EXIT_SUCCESS; +} + +void gibLaengenAus(char string[]) +{ + printf("strlen(string) = %2d\n", (int)strlen(string)); + printf("sizeof(string) = %2d\n", (int)sizeof(string)); +} diff --git a/02_pufferueberlaeufe/bufferOverflow.c b/02_pufferueberlaeufe/bufferOverflow.c new file mode 100644 index 0000000..4412e8a --- /dev/null +++ b/02_pufferueberlaeufe/bufferOverflow.c @@ -0,0 +1,27 @@ +#include +#include + +void showSecretInformation() +{ + printf("Erfolg!\n"); +} + +int checkPassword() +{ + char buffer[5]; + + printf("Bitte Passwort eingeben: "); + scanf("%s", buffer); + + return strcmp(buffer, "pass") == 0; +} + +int main() +{ + if(checkPassword()) + showSecretInformation(); + else + printf("Falsches Passwort!\n"); + + return 0; +} diff --git a/03_modultechnik/main.c b/03_modultechnik/main.c new file mode 100644 index 0000000..eaf8b70 --- /dev/null +++ b/03_modultechnik/main.c @@ -0,0 +1,80 @@ +/* + * 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. + * + */ + +#include +#include +#include +#include "namesarchive.h" + +#define MAX_BUFFER_LEN 100 + +char *inputName(const char *promptText, char *buffer, unsigned int bufferSize); + +int main() +{ + char buffer[MAX_BUFFER_LEN]; + + while((inputName("Namen hinzufuegen: ", buffer, MAX_BUFFER_LEN) != NULL) && (strlen(buffer) > 0)) + { + if(addName(buffer)) + printf("%s wurde dem Archiv hinzugefuegt.\n", buffer); + else + printf("Fehler! %s konnte nicht hinzugefuegt werden.\n", buffer); + } + + 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"); + + while((inputName("Namen entfernen: ", buffer, MAX_BUFFER_LEN) != NULL) && (strlen(buffer) > 0)) + { + if(removeName(buffer)) + printf("%s wurde aus dem Archiv entfernt.\n", buffer); + else + printf("Fehler! %s konnte nicht gefunden werden.\n", buffer); + } + + printf("\nNach Entfernen:\n"); + printNames(); + + return EXIT_SUCCESS; +} + +char *inputName(const char *promptText, char *buffer, unsigned int bufferSize) +{ + printf("%s", promptText); + if(fgets(buffer, bufferSize, stdin) != NULL) + { + if(buffer[strlen(buffer)-1] == '\n') + buffer[strlen(buffer)-1] = '\0'; + else + while(getchar() != '\n') {} + + return buffer; + } + else + { + return NULL; + } +} \ No newline at end of file diff --git a/03_modultechnik/makefile b/03_modultechnik/makefile new file mode 100644 index 0000000..e8014a9 --- /dev/null +++ b/03_modultechnik/makefile @@ -0,0 +1,16 @@ +namesarchive: main.o libnamesarchive.so + gcc -Wall -o namesarchive main.o libnamesarchive.so + +main.o: main.c + gcc -c -Wall main.c + +namesarchive.o: namesarchive.c namesarchive.h + gcc -c -Wall namesarchive.c + +libnamesarchive.so: namesarchive.o + gcc -shared -o libnamesarchive.so namesarchive.o + +clean: + del /f namesarchive.exe *.o *.so +# Comment line above and uncomment line below for UNIX systems +# rm -f namesarchive *.o *.so \ No newline at end of file diff --git a/03_modultechnik/namesarchive.c b/03_modultechnik/namesarchive.c new file mode 100644 index 0000000..0a83680 --- /dev/null +++ b/03_modultechnik/namesarchive.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include "namesarchive.h" + +// 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) +{ + return 0; +} + +// Wie addName. Fügt Namen aber direkt sortiert hinzu. Voraussetzung ist ein bereits sortiertes Archiv. +int addNameSorted(const char *name) +{ + return 0; +} + +// Entfernt den angegebenen Namen. Gibt bei Erfolg 1 zurück, ansonsten 0 (Name konnte nicht gefunden werden). +int removeName(const char *name) +{ + return 0; +} + +// Sortiert die Namen im Archiv aufsteigend. +void sortNames() +{ + +} + +// Gibt die Namen zeilenweise aus. +void printNames() +{ + +} \ No newline at end of file diff --git a/03_modultechnik/namesarchive.h b/03_modultechnik/namesarchive.h new file mode 100644 index 0000000..93b4542 --- /dev/null +++ b/03_modultechnik/namesarchive.h @@ -0,0 +1,22 @@ +#ifndef NAMEARCHIVE_H +#define NAMEARCHIVE_H + +// Maximale Namenslänge +#define MAX_NAME_LEN 10 + +// Maximale Anzahl an Namen +#define MAX_NAMES 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(); + +#endif \ No newline at end of file diff --git a/04_dateien/main.c b/04_dateien/main.c new file mode 100644 index 0000000..707755c --- /dev/null +++ b/04_dateien/main.c @@ -0,0 +1,80 @@ +/* + * 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) + * + */ + +#include +#include +#include +#include "namesarchive.h" + +#define MAX_BUFFER_LEN 100 + +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)) + { + printf("Die Textdatei %s konnte nicht geladen werden.\n", filePath); + } + + printf("\nNach Laden:\n"); + printNames(); + printf("\n"); + + while((inputName("Namen entfernen: ", buffer, MAX_BUFFER_LEN) != NULL) && (strlen(buffer) > 0)) + { + if(removeName(buffer)) + printf("%s wurde aus dem Archiv entfernt.\n", buffer); + else + printf("Fehler! %s konnte nicht gefunden werden.\n", buffer); + } + + 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"); + + return EXIT_SUCCESS; +} + +char *inputName(const char *promptText, char *buffer, unsigned int bufferSize) +{ + printf("%s", promptText); + if(fgets(buffer, bufferSize, stdin) != NULL) + { + if(buffer[strlen(buffer)-1] == '\n') + buffer[strlen(buffer)-1] = '\0'; + else + while(getchar() != '\n') {} + + return buffer; + } + else + { + return NULL; + } +} \ No newline at end of file diff --git a/04_dateien/makefile b/04_dateien/makefile new file mode 100644 index 0000000..e8014a9 --- /dev/null +++ b/04_dateien/makefile @@ -0,0 +1,16 @@ +namesarchive: main.o libnamesarchive.so + gcc -Wall -o namesarchive main.o libnamesarchive.so + +main.o: main.c + gcc -c -Wall main.c + +namesarchive.o: namesarchive.c namesarchive.h + gcc -c -Wall namesarchive.c + +libnamesarchive.so: namesarchive.o + gcc -shared -o libnamesarchive.so namesarchive.o + +clean: + del /f namesarchive.exe *.o *.so +# Comment line above and uncomment line below for UNIX systems +# rm -f namesarchive *.o *.so \ No newline at end of file diff --git a/04_dateien/namesarchive.c b/04_dateien/namesarchive.c new file mode 100644 index 0000000..0424bcd --- /dev/null +++ b/04_dateien/namesarchive.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include "namesarchive.h" + +// Fügt einen Namen hinzu. Im Fehlerfall soll 0, ansonsten 1 zurückgegeben werden. +int addName(const char *name) +{ + return 0; +} + +// Entfernt den angegebenen Namen. Gibt bei Erfolg 1 zurück, ansonsten 0 (Name konnte nicht gefunden werden). +int removeName(const char *name) +{ + return 0; +} + +// 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) +{ + return 0; +} + +// Speichert das Archiv zeilenweise in einer Textdatei. Gibt 1 bei Erfolg zurück. +int saveArchive(const char *path) +{ + return 0; +} diff --git a/04_dateien/namesarchive.h b/04_dateien/namesarchive.h new file mode 100644 index 0000000..0dd121a --- /dev/null +++ b/04_dateien/namesarchive.h @@ -0,0 +1,20 @@ +#ifndef NAMEARCHIVE_H +#define NAMEARCHIVE_H + +#define MAX_NAME_LEN 100 + +// 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. +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); +// 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. +int saveArchive(const char *path); + +#endif \ No newline at end of file