Aufgabenblock — AFB I
Zehn Standardaufgaben zum Reproduzieren: Ausgaben ablesen, Werte bestimmen, Begriffe zuordnen. Das sind die sicheren Punkte in jeder Arbeit zu C und C++ — zu jeder Aufgabe gibt es eine Erinnerung und die Lösung zum Aufklappen.
Beim Übersetzen mit gcc prog.c -o prog läuft der Quelltext durch drei Stationen: 1 Präprozessor, 2 Compiler, 3 Linker. Jedes der drei Programme enthält genau einen Fehler.
#include <stdio.h> #include "werte.h" int main(void) { printf("Start\n"); return 0; }
#include <stdio.h> int main(void) { printf("Start\n"); retrun 0; }
#include <stdio.h> int mian(void) { printf("Start\n"); return 0; }
Ordne jedem Programm die Nummer der Station zu, die den Fehler meldet.
#-Zeilen, der Compiler prüft die Anweisungen (Syntax, Namen), der Linker setzt am Ende alle Teile zusammen und sucht dabei auch main.Lösung anzeigen
a) Die Datei werte.h gibt es nicht — schon der Präprozessor bricht ab: fatal error: werte.h: No such file or directory → Station 1
b) retrun ist ein Tippfehler; der Compiler kennt den Namen nicht: error: 'retrun' undeclared → Station 2
c) Syntaktisch ist alles korrekt — es gibt nur keine Funktion main. Das merkt erst der Linker: undefined reference to `main' → Station 3
int a = 17, b = 5; printf("%d\n", a / b); printf("%d\n", a % b); printf("[%8.2f]\n", (double) a / b);
Gib die drei Ausgabezeilen an. Trage bei der dritten Zeile ein, wie viele Leerzeichen zwischen [ und der ersten Ziffer stehen.
int, schneidet / die Nachkommastellen ab; % liefert den Rest. %8.2f heißt: mindestens 8 Zeichen breit, 2 Nachkommastellen, rechtsbündig.Lösung anzeigen
17 = 3 · 5 + 2, also 17 / 5 = 3 und 17 % 5 = 2.
Der Cast macht a zur Kommazahl: 17,0 / 5 = 3,4. Mit zwei Nachkommastellen ist 3.40 4 Zeichen lang; bis zur Breite 8 fehlen 4 Leerzeichen.
3 2 [ 3.40]
int s = 0; for (int i = 2; i <= 10; i += 2) { s += i; } printf("%d\n", s);
Stelle den Ablauf in einer Tabelle mit den Spalten i und s dar. Wie oft läuft der Schleifenrumpf, und welcher Wert wird ausgegeben?
for (Start; Bedingung; Schritt): Erst wird die Bedingung geprüft, dann der Rumpf ausgeführt, danach der Schritt i += 2.Lösung anzeigen
| Durchlauf | i | s danach |
|---|---|---|
| 1 | 2 | 2 |
| 2 | 4 | 6 |
| 3 | 6 | 12 |
| 4 | 8 | 20 |
| 5 | 10 | 30 |
Danach ist i = 12, die Bedingung 12 <= 10 ist falsch. → 5 Durchläufe, Ausgabe 30
int verdopple(int x) { x = 2 * x; return x; } int main(void) { int a = 6; int b = verdopple(a); printf("%d %d\n", a, b); return 0; }
Nenne die Werte, die für a und b ausgegeben werden.
a in den Parameter x kopiert. Änderungen an x betreffen nur die Kopie; zurück kommt nur der return-Wert.Lösung anzeigen
x startet mit 6 und wird in der Funktion zu 12. Dieser Wert wird zurückgegeben und in b gespeichert. a selbst bleibt unverändert.
6 12
char c; int n; double d[2];
Nimm die typischen Größen an: char 1 Byte, int 4 Byte, double 8 Byte. Berechne den Speicherbedarf der drei Variablen zusammen, also sizeof(c) + sizeof(n) + sizeof(d).
sizeof liefert die Größe in Byte. Ein Array belegt Anzahl · Größe eines Elements.Lösung anzeigen
1 Byte + 4 Byte + 2 · 8 Byte = 21 Byte
Die Größen sind „typisch“ — auf einem Arduino ist ein int zum Beispiel nur 2 Byte groß. Deshalb misst man mit sizeof nach, statt Zahlen fest einzutippen.
int x = 4; int *p = &x; *p = *p + 3; printf("%d %d\n", x, *p * 2);
Beschreibe für jede Zeile, was mit x geschieht. Welche zwei Zahlen gibt das Programm aus?
&x ist die Adresse von x. int *p = &x; speichert sie in p. *p bedeutet „der Wert an dieser Adresse“ — also x selbst.Lösung anzeigen
| Zeile | Wirkung | x |
|---|---|---|
int x = 4; | x anlegen | 4 |
int *p = &x; | p zeigt auf x | 4 |
*p = *p + 3; | x über p um 3 erhöhen | 7 |
*p * 2 ist 7 · 2. → Ausgabe 7 14
char wort[] = "Informatik"; printf("%zu %zu\n", strlen(wort), sizeof(wort));
Bestimme die beiden ausgegebenen Werte.
'\0'. strlen zählt die Zeichen ohne das Endezeichen, sizeof misst das ganze Array.Lösung anzeigen
„Informatik“ hat 10 Buchstaben → strlen = 10. Das Array ist ohne Größenangabe genau so groß angelegt, dass auch '\0' hineinpasst → sizeof = 11.
void loop() { digitalWrite(13, HIGH); delay(200); digitalWrite(13, LOW); delay(300); }
Die LED an Pin 13 blinkt. Entnimm dem Sketch die Periodendauer T und bestimme daraus die Frequenz f.
Lösung anzeigen
T = 200 ms + 300 ms = 500 ms = 0,5 s
f = 1 / 0,5 s = 2 Hz — die LED blinkt zweimal pro Sekunde, weil loop() endlos wiederholt wird.
string ort = "Mensa"; ort = ort + "-Kasse"; int a = 3; int &r = a; r += 4; cout << ort.length() << " " << a << endl;
Wende die Regeln für string und Referenzen an: Welche zwei Zahlen gibt das Programm aus?
+ hängt zwei strings aneinander, .length() liefert die Anzahl der Zeichen. Eine Referenz int &r = a; ist ein zweiter Name für dieselbe Variable.Lösung anzeigen
"Mensa-Kasse" hat 5 + 1 + 5 = 11 Zeichen.
r ist nur ein anderer Name für a: r += 4 erhöht a von 3 auf 7.
11 7
srand(time(0)); int z = 10 + rand() % 21;
Erstelle eine kleine Tabelle mit den möglichen Werten von rand() % 21 und den zugehörigen Werten von z. Welchen kleinsten und welchen größten Wert kann z annehmen?
rand() % n liefert einen Rest bei der Division durch n, also eine Zahl von 0 bis n − 1.Lösung anzeigen
rand() % 21 | 0 | 1 | … | 20 |
|---|---|---|---|---|
z | 10 | 11 | … | 30 |
z liegt zwischen 10 und 30 — das sind 21 mögliche Werte. Allgemein liefert a + rand() % (b - a + 1) Zahlen von a bis b.
