Abschnitt 1 von 17

Selbsttest C-Programmierung

Ausgangssituation

Heute ist dein Realitätscheck.

In einer Stunde weißt du, wo du wirklich stehst – nicht wo du hoffst zu stehen. Wer sich heute selbst belügt, macht es sich nur schwerer.

Programmieren ist kein Wissen, das man lernen kann. Es ist eine Fähigkeit, die man üben muss. Du kannst nicht Ende Februar anfangen und hoffen, dass es reicht. Das ist, als würdest du zwei Wochen vor einem Marathon anfangen zu trainieren.

Deine ehrlichen Antworten helfen uns, besser zu verstehen, was für den Lernerfolg wirklich hilft – und was nicht.

Bitte kreuze an, was auf dich zutrifft:

Block 1: Grundlagen

Aufgabe 1/12: Division

2:00

Aufgabe: Schreibe Code, der den Ausdruck 17 / 5 berechnet, in einem int speichert und das Ergebnis auf einer eigenen Zeile ausgibt. Auf #include und main(...) kannst du verzichten. Was wird ausgegeben?

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

int result = 17 / 5;
printf("%d\n", result);  // gibt 3 aus (nicht 3.4)

Integer-Division schneidet Nachkommastellen ab.

Konntest du die Aufgabe in der Zeit lösen?

Aufgabe 2/12: Bereichsprüfung

2:00

Aufgabe: Schreibe Code, der prüft: Enthält die int-Variable x eine Zahl zwischen 1 und 10 (inklusive)? Wenn ja, soll "Gültig" ausgegeben werden, sonst nichts. Auf #include und main(...) kannst du verzichten.

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

if (x >= 1 && x <= 10) {
    printf("Gültig\n");
}

Häufige Fehler: || statt &&, oder 1 <= x <= 10 (syntaktisch gültig, aber semantisch falsch)

Konntest du die Aufgabe in der Zeit lösen?

Aufgabe 3/12: Maximum-Funktion

2:00

Aufgabe: Schreibe eine Funktion int max(int a, int b), die die größere der beiden Zahlen zurückgibt.

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

int max(int a, int b) {
    if (a > b) {
        return a;
    }
    return b;
}

// oder mit ternärem Operator:
int max(int a, int b) {
    return (a > b) ? a : b;
}

Konntest du die Aufgabe in der Zeit lösen?

Reflexion 1: Lernverhalten

Wie lernst du für diesen Kurs? Kreuze alle Aktivitäten an, die du regelmäßig (mind. 1x pro Woche) machst:

Stell dir vor, du sollst eine neue Programmierdatei erstellen. Was trifft am ehesten auf dich zu?

Wann hast du zuletzt selbst C-Code geschrieben?

Block 2: Schleifen und I/O

Aufgabe 4/12: Eingabe und Ausgabe

3:00

Aufgabe: Schreibe Code, der eine Ganzzahl vom Benutzer von der Standardeingabe einliest (cs50.h ist eingebunden) und dann das Doppelte dieser Zahl ausgibt.

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

// Mit cs50.h:
int n = get_int("Zahl: ");
printf("%d\n", n * 2);

// Alternativ mit scanf (ohne cs50.h):
int n;
scanf("%d", &n);
printf("%d\n", n * 2);

Beide Varianten sind korrekt. Mit scanf muss man &n übergeben (Adresse der Variable).

Konntest du die Aufgabe in der Zeit lösen?

Aufgabe 5/12: Gerade Zahlen

3:00

Aufgabe: Schreibe eine for-Schleife, die die geraden Zahlen von 2 bis 20 ausgibt (also 2, 4, 6, ... 20). Auf #include und main(...) kannst du verzichten.

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

// Variante 1: Schrittweite 2
for (int i = 2; i <= 20; i += 2) {
    printf("%d\n", i);
}

// Variante 2: Multiplikation
for (int i = 1; i <= 10; i++) {
    printf("%d\n", i * 2);
}

// Variante 3: Mit Modulo
for (int i = 1; i <= 20; i++) {
    if (i % 2 == 0) {
        printf("%d\n", i);
    }
}

Alle drei Varianten sind korrekt. Die Modulo-Variante prüft mit i % 2 == 0, ob eine Zahl gerade ist (Rest bei Division durch 2 ist 0).

Konntest du die Aufgabe in der Zeit lösen?

Aufgabe 6/12: File I/O

5:00

Aufgabe: Schreibe eine main-Funktion, die die erste Zeile aus einer Datei einliest, deren Dateiname deinem Programm als erster Kommandozeilenparameter übergeben wurde, und diese Zeile ausgibt. Auf #include kannst du verzichten. Triff sinnvolle Annahmen.

Hinweise zu den Funktionssignaturen:

FILE *fopen(const char *filename, const char *mode);
char *fgets(char *str, int n, FILE *stream);
// Liest bis zu n-1 Zeichen in str, stoppt bei Newline oder EOF

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

int main(int argc, char *argv[]) {
    FILE *f = fopen(argv[1], "r");
    if (f == NULL) {
        return 1;  // Datei konnte nicht geöffnet werden
    }
    char line[1024];
    if (fgets(line, 1024, f) != NULL) {
        printf("%s", line);  // fgets behält \n, daher kein \n nötig
    }
    fclose(f);
}

Zu treffende Annahme: Die maximale Zeilenlänge muss angenommen werden. Im Beispiel sind es 1024 Zeichen - ein anderer Wert (z.B. 256, 512, 4096) wäre auch OK gewesen.

Alternative mit malloc (Heap statt Stack):

int main(int argc, char *argv[]) {
    FILE *f = fopen(argv[1], "r");
    if (f == NULL) {
        return 1;
    }
    char *line = malloc(1024);
    if (line == NULL) {
        fclose(f);
        return 1;
    }
    if (fgets(line, 1024, f) != NULL) {
        printf("%s", line);
    }
    free(line);
    fclose(f);
}

Guter Stil: Rückgabewerte von fopen, malloc und fgets auf NULL prüfen!

Hinweis: Dass man den Rückgabewert von fgets auf NULL prüfen sollte, haben wir in der Vorlesung bisher nicht behandelt. Wenn du das vergessen hast, kannst du trotzdem "Ja" ankreuzen.

Mögliche Fehler: fopen vergessen, falscher "mode", kein Buffer, fclose vergessen, argv[1] vergessen

Konntest du die Aufgabe in der Zeit lösen?

Reflexion 2: Zeitinvestition

Die Klausur ist in etwa 12 Wochen. Das ist noch Zeit – aber nur, wenn du heute ehrlich bist und dann etwas änderst.

Wie viele Stunden pro Woche investierst du durchschnittlich in diesen Kurs?

Wie viele Stunden wendest du in einer typischen Woche auf?

Std.: Besuch der Vorlesung und des Tutoriums

Std.: Short- und Section-Videos schauen

Std.: Notes der Vorlesung lesen bzw. durcharbeiten

Std.: Folien/Notes zusammenfassen

Std.: Lösen der Übungsaufgaben inkl. Recherche

Std.: Code aus Vorlesung/Videos nachprogrammieren

Wie viel deiner Lernzeit verbringst du mit Programmieren (selbst Code schreiben)?

Dauer einer typischen Lernsitzung am Stück?

Szenario: Dein Programm kompiliert, liefert aber ein falsches Ergebnis. Was ist dein erster Schritt?

Block 3: Pointer

Aufgabe 7/12: Pointer und Arrayzugriff

3:00

Aufgabe: Betrachte den folgenden Codeausschnitt:

int numbers[] = {1, 2, 3, 4, 5};
int *ptr = numbers;
printf("%d\n", *(ptr + 3)); // <--

Was wird ausgegeben und warum? Schreibe den äquivalenten Ausdruck mit Array-Syntax auf.

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

Ausgabe: 4 - weil ptr + 3 auf das vierte Element zeigt (Index 3)

Äquivalent: numbers[3] oder ptr[3]

Konntest du die Aufgabe in der Zeit lösen?

Aufgabe 8/12: Pointer als Parameter

5:00

Aufgabe: Schreibe eine Funktion void increment(int *value), die den Wert der übergebenen Ganzzahl um 1 erhöht. Schreibe auch den Aufruf in main(...), der eine Variable x, die anfangs den Wert 5 hat, mit increment inkrementiert und das Ergebnis ausgibt. Es ist nicht nötig, #include zu schreiben.

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

void increment(int *value) {
    (*value)++;
    // Alternativen für die Inkrementierung:
    // *value = *value + 1;
    // *value += 1;
}

int main(void) {
    int x = 5;
    increment(&x);
    printf("%d\n", x);  // 6
}

Häufiger Fehler: & beim Aufruf vergessen. Die Klammern bei (*value)++ sind wichtig - ohne sie würde der Pointer inkrementiert, nicht der Wert.

Konntest du die Aufgabe in der Zeit lösen?

Aufgabe 9/12: Pointer-Tracing

3:00

Aufgabe: Was wird ausgegeben?

int x = -3;
int y = 7;
int *p = &x;
int *q = &y;
*p = *q;
p = q;
*p = 10;
printf("x=%i, y=%i\n", x, y);

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

Ausgabe: x=7, y=10

Erklärung:

  • *p = *q kopiert Wert von y nach x → x=7
  • p = q biegt Pointer um, p zeigt jetzt auf y
  • *p = 10 ändert y → y=10

Häufiger Fehler: Verwechslung von *p = *q (Wert kopieren) und p = q (Pointer umbiegen)

Konntest du die Aufgabe in der Zeit lösen?

Aufgabe 10/12: Structs

4:00

Aufgabe: Definiere eine struct namens Person, die folgende Felder enthält: char name[50] und int number. Schreibe Code, der ein Array für drei Personen erstellt und den Namen der letzten Person auf "Michaela" setzt.

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

typedef struct {
    char name[50];
    int number;
} Person;

Person personen[3];
strcpy(personen[2].name, "Michaela");

// Ohne typedef (auch korrekt):
struct Person {
    char name[50];
    int number;
};
struct Person personen[3];
strcpy(personen[2].name, "Michaela");

// Alternative mit char* statt char[]:
typedef struct {
    char *name;
    int number;
} Person2;

Person2 personen2[3];
personen2[2].name = "Michaela";

Häufiger Fehler: personen[2].name = "Michaela" geht nicht bei char[] - man muss strcpy verwenden. Bei char* funktioniert die direkte Zuweisung.

Konntest du die Aufgabe in der Zeit lösen?

Reflexion 3: Arbeitsweise

Wie lange probierst du herum, bevor du Hilfe suchst?

Welche der folgenden Übungsaufgaben könntest du aktuell ohne Hilfe und ohne KI lösen?

Wie viele der 15 Aufgaben (Übung 1-5) hast du bearbeitet?

Denk an die 2-3 Übungsaufgaben, die du zuletzt bearbeitet hast. Was beschreibt dich am besten?

Block 4: Komposition

Aufgabe 11/12: Summe der Quadrate

7:00

Aufgabe: Schreibe ein Programm, das ein Array von fünf Ganzzahlen enthält. Es gibt eine Funktion quadratsumme, der das Array übergeben wird. Der Rückgabewert ist die Summe der Quadrate der Zahlen. Die main-Funktion gibt die Summe aus. Auf #include kannst du verzichten.

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

int quadratsumme(int arr[], int n) {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += arr[i] * arr[i];
    }
    return sum;
}

int main(void) {
    int zahlen[] = {1, 2, 3, 4, 5};
    printf("%d\n", quadratsumme(zahlen, 5));  // 55
}

// Alternative mit Pointer-Syntax:
int quadratsumme(int *arr, int n) {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += arr[i] * arr[i];  // oder: *(arr+i) * *(arr+i)
    }
    return sum;
}

Wichtig: Die Länge n muss als Parameter übergeben werden, weil Arrays in C zu Pointern "zerfallen" (decay) - die Funktion kennt die Größe nicht. int arr[] und int *arr sind im Funktionsparameter gleichwertig.

Konntest du die Aufgabe in der Zeit lösen?

Aufgabe 12/12: Fehler finden

3:00

Aufgabe: In folgendem Code sind mehrere Fehler enthalten. Die Syntax ist korrekt, aber das Programm verhält sich nicht wie erwartet. Identifiziere alle Fehler im Code. Erkläre, warum sie problematisch sind.

int main() {
    char buffer[5];
    strcpy(buffer, "Hello");

    char *copy = malloc(5);
    strcpy(copy, buffer);

    char *ptr = &copy[1];
    free(copy);

    printf("%c\n", *ptr);
    return 0;
}

Versuche diese Aufgabe in der verfügbaren Zeit auf Papier oder in VS Code zu lösen. Wenn du fertig bist oder die Zeit abgelaufen ist, kannst du deine Lösung überprüfen:

Lösung:

  1. Stack Buffer Overflow: buffer[5] ist zu klein für "Hello" - braucht 6 Bytes inkl. \0
  2. Heap Buffer Overflow: malloc(5) ist ebenfalls zu klein für 6 Bytes
  3. Use-After-Free: ptr zeigt auf copy[1], aber copy wurde mit free() freigegeben - Zugriff auf *ptr ist undefiniertes Verhalten (Dangling Pointer)

Hinweis: Das fehlende Testen des malloc-Rückgabewerts auf NULL ist prinzipiell auch ein Fehler (defensives Programmieren). Es ist hier aber nicht die Ursache dafür, dass sich das Programm nicht wie erwartet verhält - daher ist es egal, ob du diesen Fehler gefunden hast oder nicht.

Konntest du die Aufgabe in der Zeit lösen?

Reflexion 4: Herausforderungen

Kreuze alle Aussagen an, die auf dich aktuell zutreffen:

Was ist deine größte Herausforderung im Kurs, die oben noch nicht genannt wurde?

Was hilft dir aktuell am meisten? (max. 3 Kreuze)

Was würde dir für die Klausurvorbereitung am meisten helfen? (max. 3 Kreuze)

Welche Aussage beschreibt deine aktuelle Situation am besten?

Ich mache dieses Semester insgesamt ECTS.

Ich arbeite neben dem Studium ca. Std./Woche.

Hast du Anmerkungen, Wünsche oder Kritik zum Kurs?

Geschafft!

Du hast alle Fragen beantwortet.

Ergebnis: Du hast angegeben, dass du 0 von 12 Programmieraufgaben lösen konntest.
Bitte nicht absenden, wenn du in der Vorlesung bereits teilgenommen hast!

Datenschutzhinweise