16 KiB
🎓 Interaktiver Programmierkurs: Von C zu universellen Konzepten
Ein Kurs für C/C++-Einsteiger mit Fokus auf übertragbare Programmierkonzepte
📋 Kursübersicht
Zielgruppe: Student mit C-Grundlagen, geplantem C++-Umstieg
Kursdauer: 8 Wochen (selbstgewähltem Tempo)
Lernziel: Sprachunabhängige Programmierkonzepte verstehen und auf beliebige Sprachen anwenden
🗺️ Modul-Struktur
Woche 1-2: Grundlagen & Denkweisen
├── Modul 1: Das Memory-Modell (Stack vs Heap)
├── Modul 2: Datentypen als Konzepte (nicht Syntax)
└── Checkpoint A: Selbsteinschätzung
Woche 3-4: Kontrollstrukturen & Logik
├── Modul 3: Flusskontrolle universell
├── Modul 4: Funktionen als Abstraktion
└── Checkpoint B: Mini-Projekt #1
Woche 5-6: Datenstrukturen
├── Modul 5: Arrays, Listen, Strukturen
├── Modul 6: Pointer & Referenzen verstehen
└── Checkpoint C: Datenstruktur-Implementierung
Woche 7-8: OOP & Fortgeschrittenes
├── Modul 7: Von structs zu Objekten (C → C++ → Konzept)
├── Modul 8: Modularisierung & Design Patterns
└── Final-Projekt: Sprachunabhängige Anwendung
🧠 Modul 1: Das Memory-Modell
Konzept: Speicher ist universell
In C:
int stack_var = 42; // Stack - automatisch verwaltet
int* heap_var = malloc(4); // Heap - manuell verwaltet
*heap_var = 42;
free(heap_var); // Nicht vergessen!
Das universelle Konzept:
Stack = Kurzlebig, automatisch, schnell
Heap = Langfristig, manuell/verwaltet, flexibel
🎯 Interaktive Übung 1.1: Memory-Map
Zeichne ein Diagramm:
┌─────────────────┐ High Address
│ Stack │ ← Wachst nach unten (lokal vars)
│ ↓ │
│ │
│ ↑ │
│ Heap │ ← Wachst nach oben (malloc/new)
│ (freier │
│ Speicher) │
│ │
│ Static/Data │ ← Globale Variablen, Strings
│ (Programm) │
└─────────────────┘ Low Address
Frage: Was passiert bei dieser C-Code Sequenz?
void foo() {
int a = 10; // Wo landet das?
int *b = malloc(sizeof(int)); // Und das?
*b = 20;
// b vergessen zu free()
}
Antwort anzeigen
a→ Stack (automatisch gelöscht nach foo())b→ Stack (nur der Pointer!)*b(der Wert 20) → Heap- ⚠️ Memory Leak: *b bleibt im Heap, weil free() vergessen wurde
Universelles Konzept: Jede Sprache hat Stack/Heap. Python/Java haben Garbage Collection, C/C++ nicht, Rust hat Ownership.
🔢 Modul 2: Datentypen als Konzepte
Konzept: Typen sind Speicher + Operationen
Nicht lernen: "int ist 4 Bytes"
Lernen: "int ist ein ganzzahliger Typ mit begrenztem Bereich"
🎯 Interaktive Übung 2.1: Typ-Universum
Ordne diese Konzepte zu:
| Konzept | C | C++ | Python | Java | JavaScript |
|---|---|---|---|---|---|
| Ganzzahl (fix) | int |
int |
- | int |
Number |
| Ganzzahl (beliebig) | long long |
long long |
int |
BigInteger |
BigInt |
| Fließkomma | float |
float |
float |
float |
Number |
| Hochpräzision | double |
double |
float |
double |
- |
| Wahrheitswert | bool (C99) |
bool |
bool |
boolean |
boolean |
| Text | char[] |
string |
str |
String |
string |
Erkenntnis: Konzepte sind gleich, Syntax variiert!
🧪 Praxis 2.2: Typische Fehler
// C-Fehler
int a = 2147483647;
int b = a + 1; // Was ist b nun?
Antwort: Überlauf (Overflow). b wird -2147483648 (Integer Overflow)
Universelles Konzept: Alle Typen haben Grenzen. Kenne deine Grenzen!
🔄 Modul 3: Flusskontrolle universell
Konzept: Programme = Sequenz + Auswahl + Wiederholung
Strukturdiagramm:
SEQUENZ
│
▼
┌──────┐
│Aktion│
└──────┘
│
▼
┌──────┐
│Aktion│
└──────┘
AUSWAHL (if/else)
│
▼
┌────────┐
│Bedingung?│
└────────┘
│Ja │Nein
▼ ▼
┌────┐ ┌────┐
│Dann│ │Sonst│
└────┘ └────┘
WIEDERHOLUNG (loops)
│
▼
┌──────────┐
│Bedingung?│←────┐
└──────────┘ │
│Ja │Nein
▼ │
┌──────┐ │
│Body │─────────┘
└──────┘
🎯 Interaktive Übung 3.1: Struktur erkennen
Welche Struktur hat dieser Code?
// Code A
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) continue;
printf("%d ", i);
}
// Code B
int x = 5;
if (x > 0) {
if (x < 10) {
printf("Im Bereich");
}
}
// Code C
while (1) {
char c = getchar();
if (c == 'q') break;
process(c);
}
Lösungen
- Code A: Wiederholung (for) + Auswahl (if) + Sprung (continue)
- Code B: Verschachtelte Auswahl (nested if)
- Code C: Endlosschleife (while(1)) + Abbruchbedingung (break)
Universell: for, while, if, break, continue existieren in fast allen Sprachen mit ähnlicher Semantik.
🔧 Modul 4: Funktionen als Abstraktion
Konzept: Funktionen kapseln Komplexität
Analogie: Funktion = Rezept
- Eingabe: Zutaten (Parameter)
- Prozess: Anleitung (Funktionskörper)
- Ausgabe: Gericht (Return-Wert)
🎯 Interaktive Übung 4.1: Black-Box-Denken
Betrachte diese Funktion:
int mystery(int a, int b) {
int result = 0;
while (b != 0) {
if (b & 1) result += a;
a <<= 1;
b >>= 1;
}
return result;
}
Ohne Code zu analysieren: Was könnte diese Funktion tun?
Tipp + Lösung
Tipp: Teste mit Werten:
mystery(3, 4)→ ?mystery(5, 5)→ ?
Lösung: Es ist die ägyptische Multiplikation (schnelle Multiplikation ohne *).
Konzept: Funktionen sind Black Boxes. Verstehe Input/Output, nicht unbedingt Implementation.
🧪 Praxis 4.2: Design by Contract
/**
* Berechnet den Durchschnitt eines Arrays.
*
* PRECONDITION: array != NULL, size > 0
* POSTCONDITION: Rückgabe = Summe(array) / size
*
* @param array Nicht-leeres Array von double
* @param size Anzahl der Elemente (> 0)
* @return Durchschnittswert
*/
double average(const double* array, size_t size);
Universelles Konzept: Design by Contract (Eiffel, aber überall anwendbar)
📦 Modul 5: Datenstrukturen
Konzept: Strukturen organisieren Daten
Evolution:
// 1. Primitive
int score = 100;
// 2. Array (Sammlung gleicher Typen)
int scores[5] = {100, 95, 87, 92, 88};
// 3. Struct (Zusammengesetzter Typ)
typedef struct {
char name[50];
int scores[5];
float average;
} Student;
// 4. Dynamische Struktur (Linked List)
typedef struct Node {
Student data;
struct Node* next;
} Node;
Universelle Datenstrukturen:
| Struktur | Verwendung | Sprachen |
|---|---|---|
| Array | Indexierter Zugriff | Alle |
| Linked List | Einfügen/Löschen | C, C++, Java |
| Stack | LIFO (Undo, Parsing) | Alle (meist builtin) |
| Queue | FIFO (Scheduling) | Alle |
| Hash Map | Schlüssel-Wert Lookup | Python, JS, Java, C++ |
| Tree | Hierarchien | Alle |
🎯 Interaktive Übung 5.1: Struktur wählen
Szenarien: Welche Datenstruktur?
- Browser-History (Back/Forward) → ?
- Druck-Warteschlange → ?
- Wörterbuch (Wort → Definition) → ?
- DOM-Elemente einer Webseite → ?
Antworten
- Stack (LIFO - letzter Besuch zuerst zurück)
- Queue (FIFO - erste Anfrage zuerst drucken)
- Hash Map/Dictionary (O(1) Lookup)
- Tree (hierarchische Struktur, Parent-Child)
Konzept: Datenstrukturen sind sprachunabhängige Muster!
🎯 Modul 6: Pointer & Referenzen
Konzept: Indirektion ist universell
Die 3 Ebenen:
Wert ──────→ Variable ──────→ Pointer
│ │ │
│ │ │
▼ ▼ ▼
42 int x int* p
x = 42 p = &x
*p = 42
In verschiedenen Sprachen:
| Sprache | Konzept | Syntax |
|---|---|---|
| C | Pointer | int* p = &x; |
| C++ | Reference | int& r = x; |
| Python | Name/Referenz | a = b (referenziert selbes Objekt) |
| Java | Reference | Object o = obj; |
| Rust | Borrowing | &x (immutable), &mut x (mutable) |
| Go | Pointer | p := &x |
🎯 Interaktive Übung 6.1: Pointer-Diagramm
Zeichne für diesen Code:
int a = 5;
int b = 10;
int* p = &a;
int* q = &b;
p = q;
*p = 20;
Fragen:
- Was ist
a? - Was ist
b? - Was ist
*p? - Was ist
*q?
Diagramm + Lösung
Initial:
┌─────┐ ┌─────┐
│ a │ 5 │ b │ 10
│(0x100)│ │(0x104)│
└─────┘ └─────┘
p = &a:
┌─────┐
│ p │───→ ┌─────┐
│(0x200)│ │ a │ 5
└─────┘ └─────┘
q = &b:
┌─────┐
│ q │───→ ┌─────┐
│(0x204)│ │ b │ 10
└─────┘ └─────┘
p = q:
┌─────┐
│ p │──┐
│(0x200)│ │
└─────┘ │
┌─────┐ │
│ q │─┼┘
│(0x204)│ ┌─────┐
└─────┘ └──→│ b │ 10
│(0x104)│
└─────┘
*p = 20:
┌─────┐
│ b │ 20 ←── p und q zeigen hierhin!
│(0x104)│
└─────┘
Antworten:
a= 5 (unverändert!)b= 20 (verändert via *p)*p= 20*q= 20
Konzept: Pointer sind Adressen. Mehrere Pointer können auf dieselbe Adresse zeigen (Aliasing).
🏗️ Modul 7: Von structs zu Objekten
Konzept: Daten + Verhalten = Objekt
Evolution in C → C++:
// C: Daten und Funktionen getrennt
typedef struct {
float x, y;
} Point;
float point_distance(Point* a, Point* b) {
return sqrt((a->x - b->x) ** 2 + ...);
}
// C++: Daten und Verhalten zusammen
class Point {
private:
float x, y;
public:
Point(float x, float y) : x(x), y(y) {}
float distanceTo(const Point& other) const {
return sqrt((x - other.x) ** 2 + ...);
}
};
Universelles OOP-Konzept:
- Kapselung: Daten schützen (private/public)
- Abstraktion: Wie etwas funktioniert ist egal
- Vererbung: "Ein Hund IST EIN Tier"
- Polymorphie: Gleiche Schnittstelle, verschiedene Implementationen
🎯 Interaktive Übung 7.1: OOP-Konzepte zuordnen
class Animal {
public:
virtual void speak() = 0; // Was ist das?
};
class Dog : public Animal { // Was ist das?
private:
string name; // Was ist das?
public:
void speak() override { // Was ist das?
cout << "Wuff!" << endl;
}
};
Lösungen
virtual ... = 0→ Abstrakte Methode (Polymorphie)class Dog : public Animal→ Vererbung (Dog IST EIN Animal)private: string name→ Kapselung (Daten geschützt)void speak() override→ Polymorphe Implementation
Konzept: Diese 4 Prinzipien existieren in Python, Java, C#, Ruby, Swift... nur Syntax variiert!
🎨 Modul 8: Modularisierung & Design
Konzept: Trennung von Belangen (Separation of Concerns)
Schichten-Architektur (universell):
┌─────────────────────────────┐
│ Presentation │ ← UI, Output
│ (View/Controller) │
├─────────────────────────────┤
│ Business Logic │ ← Verarbeitung
│ (Model/Services) │
├─────────────────────────────┤
│ Data Access │ ← Datenbank, Files
│ (Repository/DAO) │
├─────────────────────────────┤
│ Infrastructure │ ← Logging, Config
│ (Utils/Helpers) │
└─────────────────────────────┘
In C:
src/
├── main.c # Einstieg
├── ui/ # Presentation
│ ├── display.c
│ └── input.c
├── core/ # Business Logic
│ ├── calculator.c
│ └── validator.c
├── data/ # Data Access
│ ├── file_io.c
│ └── database.c
└── utils/ # Infrastructure
├── logger.c
└── config.c
In C++:
src/
├── main.cpp
├── view/ # Presentation (MVC)
├── controller/ # Flow Control
├── model/ # Business Logic
├── repository/ # Data Access
└── utils/ # Infrastructure
🎯 Interaktive Übung 8.1: Design Patterns
Wähle das passende Pattern:
| Problem | Pattern | Beschreibung |
|---|---|---|
| Genau eine DB-Verbindung | Singleton | Nur eine Instanz erlaubt |
| Verschiedene Zahlungsmethoden | Strategy | Austauschbare Algorithmen |
Objekte ohne new erstellen |
Factory | Zentralisierte Erstellung |
| Schritte A → B → C ausführen | Template Method | Algorithmus-Skelett |
Konzept: Design Patterns sind sprachunabhängige Lösungen für wiederkehrende Probleme!
🚀 Final-Projekt: Sprachunabhängige Anwendung
Aufgabe: Todo-App mit mehreren Implementationen
Anforderungen (sprachunabhängig):
- CRUD-Operationen für Todos
- Speicherung (File oder Memory)
- CLI-Interface
- Modularer Aufbau
Implementiere in:
- Version A: C (Structs, Function Pointers)
- Version B: C++ (Klassen, STL)
- (Optional) Version C: Python oder JavaScript
Der Test: Vergleiche die Implementationen. Welche Konzepte sind gleich? Was unterscheidet sich?
📝 Checkpoints & Selbsteinschätzung
Checkpoint A (nach Modul 2)
Fragen:
- Ich kann Stack vs Heap erklären
- Ich kenne die Grenzen primitiver Typen
- Ich verstehe, warum Konzepte wichtiger sind als Syntax
Checkpoint B (nach Modul 4)
Mini-Projekt: Schreibe einen Taschenrechner mit:
- Menü (Sequenz/Auswahl)
- Mathematische Funktionen (Abstraktion)
- Fehlerbehandlung
Checkpoint C (nach Modul 6)
Datenstruktur: Implementiere eine dynamische Liste (wie std::vector oder Python list) in C mit:
void list_append(List* list, int value)int list_get(List* list, size_t index)void list_remove(List* list, size_t index)
Final Check
- Ich kann Konzepte auf neue Sprachen übertragen
- Ich verstehe OOP-Prinzipien
- Ich kann modularen Code strukturieren
📚 Ressourcen & Weiterführendes
Bücher
- "The C Programming Language" (K&R) - Klassiker
- "C++ Primer" (Lippman) - Umfassend
- "Clean Code" (Martin) - Sprachunabhängig!
- "Design Patterns" (Gang of Four) - Das Original
Online
- exercism.org - Sprachübergreifende Übungen
- leetcode.com - Algorithmen in beliebiger Sprache
- codewars.com - Katas für verschiedene Sprachen
Praxis-Tipp
Lerne eine zweite Sprache parallel! Wenn du C lernst, schau dir Python-Äquivalente an. Die Kontraste machen die Konzepte klarer.
🎯 Abschluss
Die wichtigste Erkenntnis:
Programmieren ist nicht das Lernen von Syntax. Es ist das Verstehen von Konzepten, die in jeder Sprache wiederkehren – nur mit anderem "Akzent".
Wenn du diesen Kurs durchgearbeitet hast, kannst du:
- Jede neue Sprache schneller lernen (Konzepte bereits bekannt)
- Bessere Architektur-Entscheidungen treffen
- Sprachübergreifend als Entwickler arbeiten
Viel Erfolg! 🚀