Programmieren in C

Arbeitsblatt 3
Zusammengesetzte Datentypen

Im Arbeitsblatt 1 haben Sie gelernt, Informationen in Variablen zu speichern und mit ihnen zu rechnen. Das Arbeitsblatt 2 brachte dann die Möglichkeit eines beliebigen Programmablaufs. So einfach diese Mittel auf dem ersten Blick wirken – mit ihnen ist es dennoch möglich, nahezu jede Softwarefunktionalität zu realisieren. Herzlichen Glückwunsch dazu!

Was nun noch hinzu kommt, sind vor allem Komfortfunktionen, die uns helfen, Code zu schreiben, der für Menschen leichter verstehbar ist. In diesem Arbeitsblatt soll es dabei um zusätzliche Möglichkeiten gehen, Daten im Speicher zu organisieren.

Lesen Sie für dieses Arbeitsblatt bitte das Kapitel 9 im Skript.

Aufgabe 301
Grundlagen zu Feldern (Arrays)

Nachfolgendes Programm berechnet die Summe zweier dreidimensionaler Vektoren.

23  #include <stdio.h>
24  
25  
26  int main()
27  {
28    int z;              /* Laufvariablen für den Zeilenindex */
29    double vektor1[3], vektor2[3];  /* Die beiden Summanden */
30    double vektorS[3];  /* Das Ergebnis der Vektoraddition */
31  
32  
33    /*
34     * Vektoren einlesen
35     */
36  
37    printf("Erster Vektor\n");
38    for (z=0; z<3; ++z) {
39      printf("Element %i: ", z+1);
40      scanf("%lf", &vektor1[z]);
41    }
42  
43    printf("\n");
44    printf("Zweiter Vektor\n");
45    for (z=0; z<3; ++z) {
46      printf("Element %i: ", z+1);
47      scanf("%lf", &vektor2[z]);
48    }
49  
50  
51    /*
52     * Summenvektor berechnen
53     */
54  
55    for (z=0; z<3; ++z) {
56      vektorS[z] = vektor1[z] + vektor2[z];
57    }
58  
59  
60    /*
61     * Summenvektor ausgeben
62     */
63  
64    printf("\n");
65    printf("Summenvektor\n");
66  
67    for (z=0; z<3; ++z) {
68      printf("  %.2lf\n", vektorS[z]);
69    }
70  }
  1. Versuchen Sie bitte als erstes, obigen Code zu verstehen. Gehen Sie ihn Schritt für Schritt durch. Compilieren Sie das Programm auch und testen Sie es mit verschiedenen Zahlen. Zur einfacheren Handhabung finden Sie den Code bereits in Brad als Angabe zu Aufgabe 301e.

    Das Programm zeigt eine typische Kombination aus Feldern mit for-Schleifen. Prägen Sie sich bitte deshalb seine Struktur ein.

  2. Multiple Choice-Frage Wie viele Elemente haben die Felder im obigen Beispiel jeweils?

    1
    2
    3
    9

  3. Multiple Choice-Frage In welchem Bereich liegen ihre Indizes?

    0 bis 2
    0 bis 3
    1 bis 3
    1 bis unendlich

  4. Multiple Choice-Frage

    Lückentext: Einen mathematischen Vektor im 3-dimensionalen Raum kann man in C also durch ein -dimensionales Feld mit insgesamt Elementen realisieren.

  5. Programmieraufgabe in Brad Verändern Sie das Programm nun so, dass es das Skalarprodukt (inneres Produkt) der beiden Vektoren berechnet anstatt der Summe. Geben Sie den Wert des Skalarprodukts mit folgendem Text in einer eigenen Zeile aus:

    "Das Skalarprodukt betraegt x.xx."

    Das Ergebnis sollen Sie an Stelle von x.xx mit exakt zwei Nachkommastellen ausgeben. Obiger Zeile soll eine Leerzeile vorausgehen. Beachten Sie dazu bitte die Ausgabe der Referenzlösung.

Icon für C-Quellcode-Datei

Aufgabe 302
Dubletten aus einer Liste entfernen

In dieser Aufgabe soll Ihr Programm doppelte Einträge aus einer Liste von Matrikelnummern herausfiltern. Manche Studenten hatten sich bei der Anmeldung zu einer Prüfung versehentlich mehrfach eingetragen.

  1. Multiple Choice-FrageWenn man in einer Variablen speichern will, ob eine gewissen Bedingung eingetreten ist, welchen Datentyp verwendet man hierzu üblicherweise in ANSI C89?

    char
    int
    double
    Boolean

  2. Multiple Choice-FrageWie können Sie eine for-Schleife vorzeitig abbrechen?

    exit
    continue
    break
    next

  3. Programmieraufgabe in BradSchreiben Sie nun das Programm. Lesen Sie dazu zuerst eine Reihe von Matrikelnummern (Ganzzahlen) ein, bis der Benutzer eine 0 eingibt. Diese Reihe (ohne die Null) ist dann die Liste der Studierenden; es sind maximal 700 Einträge. Fordern Sie den Benutzer jeweils mit dem Text

    "Matrikelnummer: "

    zur Eingabe auf.

    Geben Sie diese Liste dann wieder in derselben Reihenfolge aus, wobei Sie eine bereits ausgegebene Matrikelnummer kein zweites Mal ausgeben. Jede Matrikelnummer soll dabei alleine in einer eigenen Zeile stehen.

Icon für C-Quellcode-Datei

Aufgabe 303
Grundlagen zu Zeichenketten (strings)

Eine Zeichenkette (string) wird in C als char-Feld realisiert, also als eine Aneinanderreihung von einzelnen Zeichen im Speicher. Das folgende Programm zeigt eine einfache Verwendung einer Zeichenkette in C. Es legt zuerst das char-Feld an, liest dann in dieses Feld eine Zeichenkette vom Benutzer ein und gibt abschließend alle Feldelemente Zeichen für Zeichen aus.

17  #include <stdio.h>
18  
19  
20  int main()
21  {
22    char eingabe[21];
23    int i = 0;
24  
25  
26    printf("Bitte geben Sie einen Text ein: ");
27    scanf("%20s", eingabe);
28  
29    printf("# ");
30    for (i=0; i<21; ++i) {
31      printf(" %c ", eingabe[i]);
32    }
33    printf("\n");
34  }
  1. Versuchen Sie bitte als erstes, obigen Code zu verstehen. Gehen Sie ihn Schritt für Schritt durch. Compilieren Sie das Programm auch und probieren Sie es mit verschiedenen Eingaben aus. Zur einfacheren Handhabung finden Sie den Code bereits in Brad als Angabe zu Aufgabe 303e.

  2. Führen Sie nun das Programm ein weiteres Mal aus und geben Sie dabei "12345678" ein. Wie viele Zeichen gibt das Programm aus?

  3. Multiple Choice-Frage Woher kommen dabei die nicht eingegebenen Zeichen?

    Die Zeichen wurden eingegeben, sind aber nicht sichtbar gewesen
    Die Schleife gibt immer alle 21 Elemente des Arrays aus, egal wie viele Zeichen eingegeben wurden
    printf kann nicht wissen, wie viele Zeichen es ausgeben soll
    Manchmal hat der Compiler einen schlechten Tag

  4. Multiple Choice-Frage Welche Bedeutung hat im obigen Code die 20 im Formatstring von scanf?

    Gebe genau 20 Zeichen aus
    Lese genau 20 Zeichen vom Benutzer ein
    Warte bis zum nächsten Enter und lese dann ein Wort mit maximal 20 Zeichen ein
    Gebe 20 Mal s aus

  5. Programmieraufgabe in BradErgänzen Sie das Programm nun am Ende (also nach der letzten printf-Anweisung) um die folgenden beiden Funktionen: Berechnen Sie zuerst die Länge der eingegebenen Zeichenkette und geben Sie diese am Ende mit dem Formatstring

    "Laenge der Zeichenkette: %i.\n"

    aus. Benutzen Sie dazu nicht die Funktion strlen. Den gegebenen Code und eine Referenzlösung finden Sie in Brad.

  6. Multiple Choice-Frage Woran können Sie mit programmiertechnischen Mitteln erkennen, wie viele Zeichen der Benutzer eingegeben hat?

    Ich speichere die Länge des Feldes in einer Variablen
    Ich speichere die Länge des Feldes in einer Präprozessor-Konstanten
    Ich suche das erste Zeichen, welches nicht im ASCII-Bereich zwischen 30 und 127 ist
    Ich zähle alle Zeichen, bis das Zeichen '\0' kommt

  7. Programmieraufgabe in Brad Modifizieren Sie den ursprünglichen Code jetzt so, dass er nur die vom Benutzer eingegebenen Zeichen zeichenweise (mit der Formatzeichenkette " %c ") ausgibt. Lösen Sie auch diese Aufgabe ohne die Funktion strlen.

Icon für C-Quellcode-Datei Icon für C-Quellcode-Datei

Aufgabe 304
Römische Zahlen

In dieser Aufgabe üben Sie, Zeichenketten einzulesen und daraufhin zu verarbeiten. Eine interessante Zeichenkette ist hierfür eine römische Zahl. Im römischen Reich wurden Zahlen nämlich nicht mit den bei uns üblichen arabischen Ziffern notiert, sondern mit den Zeichen I, V, X, L, C, D und M. Mehr Informationen dazu finden Sie am Ende dieser Aufgabe. Ihr Programm soll also eine römische Zahl in eine arabische Zahl übersetzen.

Lesen Sie dazu eine Zeichenfolge mit einer maximalen Länge von 15 Zeichen ein. Benutzen Sie hierfür den Text

"Geben Sie bitte eine roemische Zahl ein: "

Berechnen Sie nun die Dezimaldarstellung, wobei Sie Groß- und Kleinschreibung gleichermaßen berücksichtigen. Geben Sie anschließend die Zahl in einer eigenen Zeile mit dem Text

"Die arabische Zahl lautet x."

aus. x ist eine einfache ganze Zahl. Sollten Sie auf ein ungültiges Zeichen stoßen, brechen Sie ihr Programm ohne Ausgabe ab. Ihr Programm muss aber nicht erkennen, ob die eingegebene Zahl allen syntaktischen Regeln für römische Zahlen entspricht. (Sie können also vereinfachend davon ausgehen, dass eine Zahl, die nur gültige Zeichen enthält, auch den syntaktischen Regeln genügt.)

  1. Multiple Choice-Frage Ihr Programm soll schrittweise alle eingegebenen Zeichen durchgehen und dabei den Wert der Zahl berechnen. Wie viele Zeichen müssen Sie maximal betrachten, um zu einem bestimmten Zeichen den zu summierenden Wert berechnen zu können? Beachten Sie dazu die Hinweise zu römischen Zahlen weiter unten.

    Maximal 1
    Maximal 2
    Maximal 4
    Maximal alle

    Sehen Sie entsprechende Variablen in Ihrem Programm vor.

  2. Die Zahl der zu betrachtenden Zeichen variiert je nach Situation. Welche Umstände müssen hier unterschieden werden? Wie viele Zeichen müssen Sie unter welchen Umständen betrachten?

    Sehen Sie entsprechende Variablen und Verzweigungen in Ihrem Programm vor.

  3. Das Programm ist relativ komplex. Schreiben Sie deshalb zuerst das Vorgehen in natürlicher Sprache auf einem Blatt Papier auf. Diese Niederschrift soll detailliert jeden kleinen Schritt beinhalten.

  4. Programmieraufgabe in Brad Implementieren Sie nun den Algorithmus in Brad. Beachten Sie dabei auch die von uns zur Verfügung gestellte Referenzlösung.

Hinweise zu römischen Zahlen:

Eine römische Zahl setzt sich aus Zeichen mit den folgenden Wertigkeiten zusammen:

I 1
V 5
X 10
L 50
C 100
D 500
M 1000

Die Buchstaben sind ihrer Wertigkeit nach von groß nach klein angeordnet und werden einfach addiert. MDCCCLXVII ist also 1000 + 500 + 100 + 100 + 100 + 50 + 10 + 5 + 1 + 1 = 1867. Findet sich ein I, X oder C vor einem ihrer beiden nächstgrößeren Zahlen, dann wird es von der größeren zuerst abgezogen und die Differenz anschließend zur Gesamtsumme hinzu addiert. IV ist also 4 (d.h. 5 - 1) und MCMXC 1990 (d.h. 1000 + (1000 - 100) + (100 - 10) oder auch 1000 - 100 + 1000 - 10 + 100). Bei einer echten römischen Zahl können maximal vier gleiche Zeichen aufeinander folgenden und maximal eine kleinere Ziffer vor einer größeren stehen. Deshalb genügt es immer, maximal zwei Zeichen gleichzeitig zu betrachten. Wer mehr Interesse an römischen Zahlen hat, kann sich den Wikipedia-Artikel dazu anschauen.

Icon für C-Quellcode-Datei

Aufgabe 305
Aufzählungsdatentypen

  1. Multiple Choice-Frage Für welche Art von Information gibt es Aufzählungstypen (in C und anderen Sprachen)?

    Zeichenketten
    Informationen, die Geldbeträge repräsentieren
    Informationen, die nur zwei Werte annehmen können
    Informationen, die nur bestimmte Werte in begrenzter Anzahl annehmen können

  2. Multiple Choice-Frage Wie wird eine Variable eines Aufzählungstyps intern repräsentiert?

    Als int
    Als Zeichenkette (string)
    Als char-Feld
    Als char

  3. Multiple Choice-Frage Mit welchem Zeichen werden Komponenten in der Definition eines Aufzählungstyps getrennt?

    ,
    ;
    .
    :

  4. Multiple Choice-Frage Wie verarbeitet der Prozessor unterschiedliche enum-Typen?

    Der Prozessor wandelt enum-Werte mit einer Tabelle ähnlich wie der ASCII-Tabelle zur Laufzeit in Zahlen um
    Der Compiler wandelt alle enum-Typen in Zahlen um, so dass der Prozessor nur noch Zahlen verarbeitet
    Der Prozessor verarbeitet die Zeichenketten des enum-Typs wie C-Strings
    Der Prozessor hat eine eigene enum-Rechenheit ähnlich der Gleitkomma- und der Ganzzahl-Recheneinheiten

Icon für C-Quellcode-Datei

Aufgabe 306
Grundlagen zu Strukturen (struct)

In dieser Aufgabe lernen Sie den Umgang mit Strukturen. Das sind Datentypen, die Sie selbst erstellen (komponieren) können; sie setzen sich aus den bereits bekannten Grunddatentypen zusammen und werden durch das Schlüsselwort struct gekennzeichnet.

Die Verwendung von Strukturen zeigt diese Aufgabe am Beispiel der Anmeldung zur Tutorübung in „Programmieren in C“. Dabei mussten Sie als Student Ihren Vornamen, Ihren Nachnamen, Ihre Emailadresse und Ihren Wunschtermin in ein Formular eintragen. Nachdem Sie Ihre Daten abgeschickt hatten, sendete Ihnen das Programm eine Email zu, die die Anmeldung bestätigte und den Wunschtermin enthielt.

Unten sehen Sie ein Programm, das bereits den Nachnamen und die Terminnummer (eine Nummer zwischen 1 und 8) einliest und verarbeitet. Sie können darin beispielhaft sehen, wie Sie in C mit Strukturen umgehen können.

 52  #include <stdio.h>
 53
 54
 55  int main()
 56  {
 57    /* Datentyp für alle Daten zu einem Studenten (Datensatz) */
 58    struct Student {
 59      char nachname[21];
 60      int termin;          /* Nummer der Tutorübung (1-8) */
 61    };
 62    /* Variable, die die Daten zu einem Studenten (Datensatz) speichert.
 63       (Vom Datentyp struct Student) */
 64    struct Student stud;
 65
 66
 67    /* Daten des Studenten einlesen und überprüfen */
 68    printf("Nachname: ");
 69    scanf("%20s", stud.nachname);
 70
 71    printf("Terminnummer der Tutorübung: ");
 72    scanf("%i", &stud.termin);
 73    if (stud.termin < 1 || stud.termin > 8) {
 74      printf("Bitte wählen Sie eine Terminnummer zwischen 1 und 8.\n");
 75      return 1;
 76    }
 77
 78
 79    /* Email an den Studenten zur Bestätigung senden */
 80    printf("\n\nEmail: \n");
 81    printf("------\n\n");
 82    printf("Hallo %s,\n"
 83           "\n"
 84           "vielen Dank fuer Ihre Anmeldung zur Tutorenstunde "
 85           "von Programmieren in C.\n"
 86           "\n"
 87           "Sie wurden fuer den Termin %i eingetragen. Bei Fragen "
 88           "wenden Sie sich bitte an pic@ldv.ei.tum.de oder "
 89           "die Uebungsbetreuer.\n"
 90           "\n"
 91           "Das LDV GIP Team.\n",
 92           stud.nachname, stud.termin);
 93  }
  1. Versuchen Sie bitte als erstes, obigen Code zu verstehen. Gehen Sie ihn Schritt für Schritt durch. Compilieren Sie das Programm auch und führen Sie es aus. Zur einfacheren Handhabung finden Sie den Code bereits in Brad als Angabe zu Aufgabe 306e.

    Das Programm zeigt eine typische Verwendung von Strukturen (Schlüsselwort struct). Prägen Sie sich bitte deshalb seinen Aufbau ein.

  2. Multiple Choice-Frage Zu welchem Zweck gibt es Strukturen in C?

    Damit der Compiler die Ablaufstruktur besser optimieren kann
    Um mehrere Variablen sinnvoll zusammenfassen zu können
    Um den strikten Modus des Compilers abschalten zu können
    Das Schlüsselwort struct war noch übrig

  3. Multiple Choice-Frage Welches Zeichen trennt die Komponenten in der Definition einer Struktur?

    ,
    ;
    .
    :

  4. Multiple Choice-Frage Welches Zeichen schließt eine struct-Anweisung (also die Definition einer Struktur) ab?

    ,
    ;
    .
    :

  5. Programmieraufgabe in BradErgänzen Sie das Programm um die Verarbeitung für die Emailadresse und die Studienrichtung, indem Sie die folgenden Änderungen durchführen:

    1. Fügen Sie in struct Student eine Variable vorname, die eine Zeichenkette mit maximal 20 Zeichen aufnehmen kann, und eine Variable email ein, die eine Zeichenkette mit maximal 50 Zeichen aufnehmen kann (die Emailadresse des Studenten).

    2. Fragen Sie vor dem Nachnamen den Vornamen mit dem Text

      "Vorname: "

      ab und speichern Sie die Eingabe in die Komponente vorname der Variablen stud. Stellen Sie dabei sicher, dass Ihr Programm maximal 20 Zeichen vom Benutzer einliest.

    3. Fragen Sie nach dem Nachnamen die Emailadresse mit dem Text

      "Email: "

      ab und speichern Sie die Eingabe in die Komponente email der Variablen stud. Stellen Sie dabei sicher, dass Ihr Programm maximal 50 Zeichen vom Benutzer einliest.

    4. Ändern Sie die Ausgabe der Email zuletzt so ab, dass sie die Formatzeichenkette

      "An: %s\n"
      "\n"
      "Hallo %s %s,\n"
      "\n"
      "vielen Dank fuer Ihre Anmeldung zur Tutorenstunde "
      "von Programmieren in C.\n"
      "\n"
      "Sie wurden fuer den Termin %i eingetragen. Bei Fragen "
      "wenden Sie sich bitte an pic@ldv.ei.tum.de oder "
      "die Uebungsbetreuer.\n"
      "\n"
      "Das LDV GIP Team.\n"
      

      verwendet, wobei die Variablen in der Reihenfolge email, vorname, nachname und termin eingefügt werden müssen.

    Das Programm, das tatsächlich Ihre Anmeldung zur Tutorübung per WWW bearbeitet hat, ist übrigens in PHP geschrieben. Es zeigt dennoch sehr große Ähnlichkeiten mit Ihrem Code auf, weil sich C und PHP zu einem großen Teil gleichen. Sie würden es sicherlich verstehen.

  6. Programmieraufgabe in Brad Für diese Teilaufgabe ist folgender etwas veränderter Code gegeben. Er fragt in einer Schleife fortlaufend Studenten ab, bis der Benutzer abbricht. Jedoch speichert der Code nur den zuletzt eingegebenen Datensatz. Sie sollen den Code nun so ergänzen, dass er eine Liste von Studenten speichert und diese Liste abschließend ausgibt.

    29  #include <stdio.h>
    30
    31
    32  int main()
    33  {
    34    /* Datentyp für alle Daten zu einem Studenten (Datensatz) */
    35    struct Student {
    36      char nachname[21];
    37      int termin;      /* Nummer der Tutorübung (1-8) */
    38    };
    39    /* Variable, die die Daten zu einem Studenten (Datensatz) speichert.
    40       (Vom Datentyp struct Student) */
    41    struct Student stud;
    42
    43    char antwort = 0;  /* Zum Speichern einer j/n- (Ja/Nein-) Antwort */
    44
    45
    46    do {
    47      /* Daten des Studenten einlesen und überprüfen */
    48      printf("Nachname: ");
    49      scanf("%20s", &stud.nachname);
    50
    51      printf("Terminnummer der Tutorübung: ");
    52      scanf("%i", &stud.termin);
    53      if (stud.termin < 1 || stud.termin > 8) {
    54        printf("Bitte wählen Sie eine Terminnummer zwischen 1 und 8.\n");
    55        return 1;
    56      }
    57
    58      printf("Wollen Sie einen weiteren Studenten eingeben (j/n): ");
    59      scanf(" %c", &antwort);
    60    } while (antwort != 'n' && antwort != 'N');
    61
    62
    63    printf("\n\nListe:\n");
    64    printf("------\n\n");
    65
    66    printf("%-20s  |  %i\n", stud.nachname, stud.termin);
    67  }
    

    Um nun viele Studenten in einer Liste speichern zu können, verändern Sie bitte den Code wie folgt:

    1. Legen Sie ein Feld an, das 700 Elemente vom Typ struct Student aufnehmen kann.

    2. Speichern Sie alle vom Benutzer eingegebenen Datensätze (Daten eines Studenten) fortlaufend in diesem Feld.

    3. Erweitern Sie die letzte printf-Anweisung um Code, der in einer Schleife alle eingegebenen Studenten wieder tabellarisch ausgibt. Die Formatzeichenkette dieser printf-Anweisung soll dabei unverändert bleiben.

Icon für C-Quellcode-Datei Icon für C-Quellcode-Datei

Aufgabe 307
Wochentagsberechnung

Schreiben Sie ein Programm, um den Wochentag an einem bestimmten Datum zu bestimmen. Berücksichtigen Sie folgende Regeln für das Schaltjahr. Sie haben diese Bedingungen programmiertechnisch bereits in Aufgabe 204 umgesetzt.

Zusätzlich soll das (fiktive) Jahr 0 kein Schaltjahr und der 1. Januar 00 ein Sonntag gewesen sein.

Fragen Sie zu Beginn das Datum mit

"Jahr: "
"Monat: "
"Tag: "

ab. Überprüfen Sie dessen Korrektheit (Tag und Monat im gültigen Bereich; Jahr ≥ 0) und brechen Sie bei einer fehlerhaften Eingabe sofort mit der Meldung

"Falsche Eingabe."

ab. War das eingegebene Datum in Ordnung, geben Sie den Wochentag mit

"Der xx.xx.xxxx ist ein yyyyyyy."

aus. Dabei ist xx.xx.xxxx das eingegebene Datum, beispielsweise in der Form 13.01.736, und yyyyyyy der Wochentag, beispielsweise Donnerstag.

Hinweise zur Lösung:

  1. Berechnen Sie auf einem Blatt Papier für die folgenden Datumsangaben die Anzahl der Tage, die seit dem 1. Januar 00 vergangen sind. Leiten Sie dann daraus den Wochentag des jeweiligen Datums ab. Vergleichen Sie Ihre Berechnungen mit dem Lösungsprogramm (307c_loesung).

    • 1.1.00
    • 1.2.00
    • 1.3.00
    • 1.1.01
    • 1.4.01
    • 1.1.04
    • 1.4.04
    • 1.1.05
    • 1.1.06
    • 1.1.100
    • 1.1.101
    • 1.1.400
    • 1.1.401
  2. Formulieren Sie nun in natürlicher Sprache Ihr Vorgehen bei den obigen Berechnungen auf einem Blatt Papier. Erwähnen Sie dabei jeden auch noch so kleinen Schritt.

  3. Programmieraufgabe in Brad Implementieren Sie dieses Vorgehen als Programm in Brad. Geben Sie dabei zum Testen die berechnete Anzahl der seit dem 1.1.00 vergangenen Tage aus und vergleichen Sie diese mit Ihren eigenen Berechnungen. Um Fehler in Ihrem Programm aufzuspüren, empfehle ich Ihnen, schrittweise die in Teilaufgabe a genannten Daten der Reihe nach auszuprobieren.

Icon für C-Quellcode-Datei


XHTML 1.0 Strict und CSS 2