Skip to main content

Übersicht

Erweiterter C-Lernplan mit Übungsaufgaben

1. Grundlagen

1.1 Einführung in C

  • Aufgabe 1: Recherchieren Sie die Geschichte von C und erstellen Sie eine kurze Zeitlinie der wichtigsten Ereignisse.
  • Aufgabe 2: Installieren Sie eine C-Entwicklungsumgebung (z.B. GCC und VS Code) und kompilieren Sie ein einfaches "Hello, World!"-Programm.

1.2 Erste Schritte

  • Aufgabe 1: Schreiben Sie ein Programm, das Ihren Namen und Ihr Alter ausgibt.
  • Aufgabe 2: Modifizieren Sie das Programm so, dass es den Benutzer nach seinem Namen und Alter fragt und dann eine personalisierte Begrüßung ausgibt.

2. Variablen und Datentypen

2.1 Variablen und Konstanten

  • Aufgabe 1: Deklarieren Sie Variablen für Ihr Geburtsdatum (Tag, Monat, Jahr) und geben Sie diese aus.
  • Aufgabe 2: Definieren Sie eine Konstante für Pi (3.14159) und berechnen Sie den Umfang eines Kreises mit einem vom Benutzer eingegebenen Radius.

2.2 Grundlegende Datentypen

  • Aufgabe 1: Schreiben Sie ein Programm, das die Größe (in Bytes) aller grundlegenden Datentypen ausgibt (int, float, double, char).
  • Aufgabe 2: Erstellen Sie ein Programm, das die maximalen und minimalen Werte für int und unsigned int ausgibt.

2.3 Typumwandlungen

  • Aufgabe 1: Schreiben Sie ein Programm, das eine Gleitkommazahl einliest und sie in einen Integer umwandelt. Geben Sie beide Werte aus.
  • Aufgabe 2: Erstellen Sie ein Programm, das zwei Integerwerte dividiert und das Ergebnis sowohl als Integer als auch als Gleitkommazahl ausgibt.

3. Operatoren und Ausdrücke

3.1 Arithmetische Operatoren

  • Aufgabe 1: Schreiben Sie ein Programm, das den Benutzer nach zwei Zahlen fragt und alle grundlegenden arithmetischen Operationen (+, -, *, /, %) damit durchführt.
  • Aufgabe 2: Implementieren Sie einen einfachen Taschenrechner, der zwei Zahlen und einen Operator als Eingabe nimmt und das Ergebnis ausgibt.

3.2 Vergleichsoperatoren

  • Aufgabe 1: Schreiben Sie ein Programm, das zwei vom Benutzer eingegebene Zahlen vergleicht und ausgibt, ob sie gleich, ungleich, größer oder kleiner sind.
  • Aufgabe 2: Erstellen Sie ein Programm, das prüft, ob ein eingegebenes Jahr ein Schaltjahr ist.

3.3 Logische Operatoren

  • Aufgabe 1: Schreiben Sie ein Programm, das prüft, ob eine eingegebene Zahl zwischen 1 und 100 (inklusive) liegt.
  • Aufgabe 2: Implementieren Sie ein einfaches Login-System, das Benutzername und Passwort überprüft (mit vordefinierten korrekten Werten).

3.4 Bitweise Operatoren

  • Aufgabe 1: Schreiben Sie ein Programm, das zwei Zahlen bitweise AND, OR und XOR verknüpft und die Ergebnisse ausgibt.
  • Aufgabe 2: Implementieren Sie eine Funktion, die prüft, ob eine gegebene Zahl eine Zweierpotenz ist, unter Verwendung bitweiser Operationen.

3.5 Zuweisungsoperatoren

  • Aufgabe 1: Schreiben Sie ein Programm, das eine Variable mit verschiedenen zusammengesetzten Zuweisungsoperatoren (+=, -=, *=, /=, %=) modifiziert und nach jeder Operation ausgibt.
  • Aufgabe 2: Implementieren Sie einen Zähler, der mit verschiedenen Zuweisungsoperatoren hoch- und runterzählt.

4. Kontrollstrukturen

4.1 if...else Anweisung

  • Aufgabe 1: Schreiben Sie ein Programm, das eine Note (0-100) einliest und die entsprechende Bewertung (A, B, C, D, F) ausgibt.
  • Aufgabe 2: Implementieren Sie einen einfachen Taschenrechner mit if...else, der je nach eingegebenem Operator (+, -, *, /) die entsprechende Operation ausführt.

4.2 switch Anweisung

  • Aufgabe 1: Schreiben Sie ein Programm, das einen Wochentag als Zahl (1-7) einliest und den entsprechenden Namen ausgibt.
  • Aufgabe 2: Erstellen Sie ein Menüsystem für ein einfaches Spiel (z.B. "1. Spielen", "2. Regeln", "3. Beenden") mit switch.

4.3 for Schleife

  • Aufgabe 1: Schreiben Sie ein Programm, das die Summe aller Zahlen von 1 bis n berechnet (n vom Benutzer eingegeben).
  • Aufgabe 2: Implementieren Sie ein Programm, das die ersten n Fibonacci-Zahlen ausgibt.

4.4 while Schleife

  • Aufgabe 1: Schreiben Sie ein Programm, das den Benutzer wiederholt nach einer Zahl fragt, bis eine negative Zahl eingegeben wird.
  • Aufgabe 2: Implementieren Sie ein einfaches Ratespiel, bei dem der Computer eine Zufallszahl generiert und der Benutzer sie erraten muss.

4.5 do...while Schleife

  • Aufgabe 1: Schreiben Sie ein Programm, das den Benutzer nach einem Passwort fragt und dies so lange wiederholt, bis das richtige Passwort eingegeben wurde.
  • Aufgabe 2: Implementieren Sie ein Menüsystem, das nach jeder Operation fragt, ob der Benutzer fortfahren möchte.

4.6 break und continue

  • Aufgabe 1: Schreiben Sie ein Programm, das die ersten 10 Primzahlen findet und dabei break verwendet, um die Schleife zu beenden.
  • Aufgabe 2: Implementieren Sie eine Schleife, die alle Zahlen von 1 bis 100 ausgibt, aber Vielfache von 3 überspringt (mit continue).

5. Funktionen

5.1 Funktionsdefinition und -deklaration

  • Aufgabe 1: Definieren Sie eine Funktion, die den Umfang eines Kreises berechnet, und verwenden Sie sie in einem Hauptprogramm.
  • Aufgabe 2: Schreiben Sie ein Programm mit separaten Funktionen für Addition, Subtraktion, Multiplikation und Division.

5.2 Funktionsaufrufe

  • Aufgabe 1: Implementieren Sie eine Funktion, die prüft, ob eine Zahl prim ist, und rufen Sie diese für die Zahlen 1 bis 20 auf.
  • Aufgabe 2: Schreiben Sie ein Programm, das Funktionen für verschiedene geometrische Berechnungen (Fläche, Umfang) für Kreis, Rechteck und Dreieck enthält und diese aufruft.

5.3 Parameterübergabe

  • Aufgabe 1: Schreiben Sie eine Funktion, die zwei Zahlen als Parameter erhält und deren Summe, Differenz, Produkt und Quotient zurückgibt.
  • Aufgabe 2: Implementieren Sie eine Funktion, die ein Array und dessen Größe als Parameter erhält und den Durchschnitt der Elemente berechnet.

5.4 Rückgabewerte

  • Aufgabe 1: Schreiben Sie eine Funktion, die prüft, ob ein Jahr ein Schaltjahr ist, und einen booleschen Wert zurückgibt.
  • Aufgabe 2: Implementieren Sie eine Funktion, die die n-te Fibonacci-Zahl berechnet und zurückgibt.

5.5 Rekursion

  • Aufgabe 1: Schreiben Sie eine rekursive Funktion zur Berechnung der Fakultät einer Zahl.
  • Aufgabe 2: Implementieren Sie den Euklidischen Algorithmus zur Berechnung des größten gemeinsamen Teilers zweier Zahlen rekursiv.

5.6 Speicherklassen

  • Aufgabe 1: Schreiben Sie eine Funktion mit einer statischen Variable, die zählt, wie oft die Funktion aufgerufen wurde.
  • Aufgabe 2: Implementieren Sie ein Programm, das globale, lokale und statische Variablen verwendet und deren Unterschiede demonstriert.

6. Arrays

6.1 Eindimensionale Arrays

  • Aufgabe 1: Schreiben Sie ein Programm, das die Elemente eines Arrays von Integern in umgekehrter Reihenfolge ausgibt.
  • Aufgabe 2: Implementieren Sie eine Funktion, die das größte und kleinste Element in einem Array findet.

6.2 Mehrdimensionale Arrays

  • Aufgabe 1: Erstellen Sie ein Programm, das eine 3x3-Matrix erstellt, mit Werten füllt und ausgibt.
  • Aufgabe 2: Implementieren Sie die Addition zweier 2x2-Matrizen.

6.3 Arrays und Funktionen

  • Aufgabe 1: Schreiben Sie eine Funktion, die ein Array als Parameter erhält und dessen Elemente verdoppelt.
  • Aufgabe 2: Implementieren Sie eine Funktion zum Sortieren eines Arrays (z.B. Bubble Sort).

6.4 Zeichenketten (Strings) als Arrays

  • Aufgabe 1: Schreiben Sie ein Programm, das einen String einliest und ihn rückwärts ausgibt.
  • Aufgabe 2: Implementieren Sie eine Funktion, die zählt, wie oft ein bestimmter Buchstabe in einem String vorkommt.

7. Zeiger

7.1 Einführung in Zeiger

  • Aufgabe 1: Schreiben Sie ein Programm, das den Wert einer Variable und ihre Adresse ausgibt.
  • Aufgabe 2: Implementieren Sie eine Funktion, die zwei Variablen mittels Zeigern vertauscht.

7.2 Zeiger und Arrays

  • Aufgabe 1: Schreiben Sie ein Programm, das ein Array mittels Zeigerarithmetik durchläuft und ausgibt.
  • Aufgabe 2: Implementieren Sie eine Funktion, die ein Array mittels Zeiger sortiert.

7.3 Zeiger und Funktionen

  • Aufgabe 1: Schreiben Sie eine Funktion, die zwei Zahlen als Zeiger erhält und ihre Summe an eine dritte Adresse schreibt.
  • Aufgabe 2: Implementieren Sie eine Funktion, die ein Array und dessen Größe als Parameter erhält und das größte Element mittels Zeiger findet.

7.4 Zeiger auf Zeiger

  • Aufgabe 1: Schreiben Sie ein Programm, das einen Zeiger auf einen Zeiger verwendet, um den Wert einer Variable zu ändern.
  • Aufgabe 2: Implementieren Sie eine Funktion, die ein 2D-Array mittels Zeiger auf Zeiger verarbeitet.

7.5 Funktionszeiger

  • Aufgabe 1: Schreiben Sie ein Programm, das Funktionszeiger verwendet, um verschiedene mathematische Operationen durchzuführen.
  • Aufgabe 2: Implementieren Sie ein einfaches Callback-System mit Funktionszeigern.

7.6 Zeigerarithmetik

  • Aufgabe 1: Schreiben Sie ein Programm, das ein Array mittels Zeigerarithmetik rückwärts durchläuft.
  • Aufgabe 2: Implementieren Sie eine Funktion, die zwei sortierte Arrays zu einem neuen sortierten Array zusammenführt, unter Verwendung von Zeigerarithmetik.

8. Speicherverwaltung

8.1 Stack und Heap

  • Aufgabe 1: Schreiben Sie ein Programm, das den Unterschied zwischen Stackvariablen und Heapvariablen demonstriert.
  • Aufgabe 2: Implementieren Sie eine Funktion, die eine große Datenmenge auf dem Heap alloziert und wieder freigibt.

8.2 Dynamische Speicherzuweisung

  • Aufgabe 1: Schreiben Sie ein Programm, das ein dynamisches Array erstellt, dessen Größe zur Laufzeit bestimmt wird.
  • Aufgabe 2: Implementieren Sie eine einfache verkettete Liste mit dynamischer Speicherzuweisung.

9. Strukturen und Unions

9.1 Strukturen definieren und verwenden

  • Aufgabe 1: Definieren Sie eine Struktur für einen Studenten (Name, Matrikelnummer, Notendurchschnitt) und erstellen Sie ein Array von Studenten.
  • Aufgabe 2: Implementieren Sie ein Adressbuch mit einer Struktur für Kontakte und Funktionen zum Hinzufügen und Anzeigen von Kontakten.

9.2 Strukturen und Funktionen

  • Aufgabe 1: Schreiben Sie eine Funktion, die eine Studentenstruktur als Parameter erhält und die Daten ausgibt.
  • Aufgabe 2: Implementieren Sie Funktionen zum Sortieren eines Arrays von Strukturen (z.B. nach Namen oder Matrikelnummer).

9.3 Strukturen und Zeiger

  • Aufgabe 1: Schreiben Sie ein Programm, das Zeiger auf Strukturen verwendet, um Daten zu ändern.
  • Aufgabe 2: Implementieren Sie eine verkettete Liste mit Strukturen und Zeigern.

9.4 Unions

  • Aufgabe 1: Definieren Sie eine Union, die verschiedene Datentypen (int, float, char) speichern kann, und demonstrieren Sie ihre Verwendung.
  • Aufgabe 2: Implementieren Sie ein Programm, das eine Union verwendet, um Daten effizient zu speichern (z.B. für verschiedene Fahrzeugtypen).

9.5 Aufzählungen (enums)

  • Aufgabe 1: Definieren Sie eine Aufzählung für Wochentage und verwenden Sie sie in einem switch-Statement.
  • Aufgabe 2: Implementieren Sie ein einfaches Statussystem für eine Aufgabenverwaltung mit enums (z.B. TODO, IN_PROGRESS, DONE).

10. Dateien und I/O-Operationen

10.1 Standardeingabe und -ausgabe

  • Aufgabe 1: Schreiben Sie ein Programm, das Benutzereingaben formatiert einliest (z.B. Name, Alter, Größe) und sie formatiert ausgibt.
  • Aufgabe 2: Implementieren Sie ein einfaches Quizprogramm, das Fragen aus der Standardeingabe liest und Antworten überprüft.

10.2 Dateioperationen

  • Aufgabe 1: Schreiben Sie ein Programm, das einen Text in eine Datei schreibt und ihn dann wieder ausliest und anzeigt.
  • Aufgabe 2: Implementieren Sie ein Programm, das Daten aus einer CSV-Datei einliest und in Strukturen speichert.

10.3 Fehlerbehandlung bei Dateioperationen

  • Aufgabe 1: Erweitern Sie das Programm aus 10.2, Aufgabe 1, um Fehler beim Öffnen und Schließen der Datei abzufangen und zu behandeln.
  • Aufgabe 2: Schreiben Sie ein Programm, das versucht, mehrere Dateien zu öffnen und zu lesen, und eine Zusammenfassung der Erfolge und Fehler ausgibt.

11. Präprozessor und Makros

11.1 #include Direktive

  • Aufgabe 1: Erstellen Sie eine eigene Header-Datei mit Funktionsdeklarationen und verwenden Sie sie in einem Hauptprogramm.
  • Aufgabe 2: Implementieren Sie ein Projekt mit mehreren .c und .h Dateien und verwenden Sie die #include Direktive, um sie zu verbinden.

11.2 Makrodefinitionen

  • Aufgabe 1: Definieren Sie Makros für einfache mathematische Operationen (z.B. SQUARE, CUBE) und verwenden Sie sie in einem Programm.
  • Aufgabe 2: Implementieren Sie ein DEBUG-Makro, das bedingte Kompilierung für Debug-Ausgaben ermöglicht.

11.3 Bedingte Kompilierung

  • Aufgabe 1: Schreiben Sie ein Programm, das je nach definiertem Makro unterschiedliche Funktionalität kompiliert (z.B. für verschiedene Betriebssysteme).
  • Aufgabe 2: Implementieren Sie verschiedene Versionen einer Funktion (z.B. sortieren) und verwenden Sie bedingte Kompilierung, um zwischen ihnen zu wählen.

12. Fortgeschrittene Themen

12.1 Verkettete Listen

  • Aufgabe 1: Implementieren Sie eine einfach verkettete Liste mit Funktionen zum Einfügen, Löschen und Anzeigen von Elementen.
  • Aufgabe 2: Erweitern Sie die verkettete Liste zu einer doppelt verketteten Liste und implementieren Sie eine Funktion zum Rückwärtsdurchlaufen.

12.2 Binäre Bäume

  • Aufgabe 1: Implementieren Sie einen binären Suchbaum mit Funktionen zum Einfügen und Suchen von Elementen.
  • Aufgabe 2: Erweitern Sie den binären Suchbaum um eine Funktion zur In-Order-Traversierung und zum Löschen von Elementen.

12.3 Bitmasken und Bitmanipulation

  • Aufgabe 1: Schreiben Sie Funktionen zum Setzen, Löschen und Überprüfen einzelner Bits in einer Integer-Variablen.
  • Aufgabe 2: Implementieren Sie ein einfaches Rechte-Management-System mit Bitmasken (z.B. Lese-, Schreib-, Ausführungsrechte).

12.4 Multithreading-Grundlagen

  • Aufgabe 1: Schreiben Sie ein Programm, das zwei Threads erstellt, die jeweils eine Zählervariable inkrementieren.
  • Aufgabe 2: Implementieren Sie ein Producer-Consumer-Problem mit Threads und einem gemeinsamen Puffer.

13. Beste Praktiken und Optimierung

13.1 Codeformatierung und -stil

  • Aufgabe 1: Nehmen Sie ein früheres Projekt und formatieren Sie es nach einem konsistenten Stil (z.B. K&R oder GNU).
  • Aufgabe 2: Schreiben Sie ein Skript oder Programm, das einfache Stilüberprüfungen in C-Code durchführt (z.B. Einrückung, Klammern).

13.2 Debugging-Techniken

  • Aufgabe 1: Fügen Sie Debug-Ausgaben zu einem komplexeren Programm hinzu, um den Programmablauf nachzuverfolgen.
  • Aufgabe 2: Verwenden Sie einen Debugger wie GDB, um Schritt für Schritt durch ein Programm zu gehen und Variablenwerte zu überwachen.

13.3 Performanceoptimierung

  • Aufgabe 1: Profilen Sie ein rechenintensives Programm und identifizieren Sie Engpässe.
  • Aufgabe 2: Optimieren Sie einen Sortieralgorithmus und vergleichen Sie die Leistung vor und nach der Optimierung.

13.4 Sicherheitsaspekte in C

  • Aufgabe 1: Überprüfen Sie ein bestehendes Programm auf potenzielle Pufferüberläufe und beheben Sie diese.
  • Aufgabe 2: Implementieren Sie sichere Versionen von Funktionen wie strcpy und strcat, die Puffergrößen berücksichtigen.

14. Projekte und Anwendungen

14.1 Kleine Projekte

  • Aufgabe 1: Entwickeln Sie ein Terminverwaltungssystem mit Datei-I/O zur Speicherung von Terminen.
  • Aufgabe 2: Implementieren Sie ein einfaches Verschlüsselungsprogramm (z.B. Caesar-Chiffre) mit Ver- und Entschlüsselungsfunktionen.

14.2 Fortgeschrittene Projekte

  • Aufgabe 1: Entwickeln Sie eine einfache Datenbankanwendung zur Verwaltung einer Bibliothek (Bücher, Ausleihen, Benutzer).
  • Aufgabe 2: Implementieren Sie einen einfachen Texteditor mit grundlegenden Funktionen wie Öffnen, Bearbeiten, Speichern und Suchen.

15. Standardbibliothek

15.1 Überblick über wichtige Standardbibliotheksfunktionen

  • Aufgabe 1: Schreiben Sie ein Programm, das verschiedene String-Funktionen aus string.h demonstriert (z.B. strlen, strcpy, strcat).
  • Aufgabe 2: Implementieren Sie ein Programm, das die Zeit- und Datumsfunktionen aus time.h verwendet, um einen einfachen Kalender zu erstellen.

15.2 Detaillierte Betrachtung ausgewählter Bibliotheken

  • Aufgabe 1: Verwenden Sie die math.h Bibliothek, um ein Programm zu schreiben, das verschiedene mathematische Berechnungen durchführt (z.B. Trigonometrie, Logarithmen).
  • Aufgabe 2: Implementieren Sie ein Programm, das die stdlib.h Funktionen zur dynamischen Speicherverwaltung und Zufallszahlengenerierung nutzt.