Übungsaufgaben
Zehn Übungen zum Klicken, Zuordnen, Nachverfolgen und Knobeln — von AFB I bis AFB III. Jede Übung gibt dir sofort Rückmeldung; wenn du nicht weiterkommst, helfen dir die gestuften Tipps.
Die Mensa-Kasse berechnet Preise mit Rabatt.
double rabatt(double preis, int prozent) { return preis * (100 - prozent) / 100; }
Ordne jedem Teil den passenden Fachbegriff zu.
; — er kündigt die Funktion nur an. Der Aufruf enthält keine Typen, sondern konkrete Werte. Übrigens: rabatt(12.0, 25) liefert 9.00.Fünf Behauptungen über Funktionen und Header. Nenne jeweils, ob sie stimmt.
return zurück und weist ihn beim Aufruf zu.return wirkt wie ein Notausgang aus der Funktion.Die Wetterstation wird auf drei Dateien verteilt: main.c, temperatur.h und temperatur.c. Ordne jede Zeile der Datei ein, in die sie gehört.
;) und den Include-Guard, die .c-Datei die Definitionen mit Rumpf. Typischer Fehler: Funktionsdefinitionen in den Header schreiben. Wird er dann von zwei .c-Dateien eingebunden, meldet der Linker die Funktion doppelt.; oder hat sie einen Rumpf in { }?#ifndef / #define gehört zum Include-Guard des Headers.int stufe(int x) { x = x * 2; return x + 1; } int main(void) { int a = 5; int b = stufe(a); int c = stufe(b) - a; printf("%d %d %d\n", a, b, c); return 0; }
Wende die Regeln für Funktionsaufrufe an und gib die Werte Schritt für Schritt an.
-
Wert von
b -
Wert von
anach dem ersten Aufruf -
Rückgabewert von
stufe(b) -
Wert von
c
stufe wird x verdoppelt — aber x ist nur eine Kopie von a. a bleibt 5. Deshalb ist c = 23 − 5 = 18 und nicht 23 − 10.stufe(5) Zeile für Zeile: x = 10, Rückgabe 11.a in main und der Parameter x sind zwei verschiedene Speicherplätze.*** ******
Ergänze das Programm so, dass genau diese Ausgabe entsteht.
sterne(int n) { for (int i = 0; i < n; i++) { printf("*"); } printf("\n"); } ist_teiler(int t, int z) { z % t == 0; } int main(void) { for (int z = 1; z <= 6; z++) { if (ist_teiler(, z)) { sterne(); } } return 0; }
sterne gibt nur aus und liefert nichts — also void. ist_teiler muss dagegen einen Wert (0 oder 1) für das if zurückgeben. Typischer Fehler bei Lücke 5: t wählen. t ist ein Parameter von ist_teiler und in main unbekannt — gcc bricht ab. Mit sterne(3) kämen zweimal drei Sterne.z im zweiten Treffer.Im Projekt „Geometrie“ steckt die Funktion kreisflaeche in eigenen Dateien. Stelle den Aufbau des Projekts vollständig dar, indem du die Lücken füllst — zwei Bausteine bleiben übrig.
Die Datei enthält nur den Prototyp double kreisflaeche(double r);. Die Definition mit Rumpf steht in . main.c bindet den Header mit ein. Übersetzt wird das Projekt mit . Der Include-Guard besteht aus #ifndef GEOMETRIE_H, #define GEOMETRIE_H und am Schluss .
<geometrie.h> sucht der Präprozessor nur in den Systemordnern und meldet No such file. Und gcc main.c -o geo übersetzt geometrie.c gar nicht mit — der Linker meldet undefined reference to `kreisflaeche'. Der Header selbst steht nie im gcc-Befehl..h), Quelldatei = Umsetzung (.c)..c-Dateien, die übersetzt werden sollen.int plus_eins(int x) { return x + 1; } int doppelt(int x) { return 2 * x; } // in main: printf("%d\n", doppelt(plus_eins(doppelt(3))) - plus_eins(4));
Berechne, welche Zahl ausgegeben wird.
doppelt(3) = 6, plus_eins(6) = 7, doppelt(7) = 14. Dann 14 − plus_eins(4) = 14 − 5 = 9. Typischer Fehler: von außen nach innen rechnen und doppelt zuerst auf 3 und dann erst plus_eins anwenden — oder die Klammern falsch zuordnen.doppelt(3) ist 6. Welcher Aufruf umschließt ihn direkt?Das Projekt soll 2 min 30 s in Sekunden umrechnen und 150 ausgeben. Übersetzt wird mit gcc -Wall main.c zeit.c -o zeit. Von main.c siehst du nur die Zeilen um den Aufruf. Überprüfe die drei Dateien — drei Zeilen sind fehlerhaft.
-Wall die Warnung control reaches end of non-void function aus. Ohne -Wall übersetzt alles still, und das Programm gibt eine zufällige Zahl aus. Zeile 10 dagegen ist korrekt: Bei der Definition steht kein Semikolon hinter der Klammer.#include-Klammern, den Unterschied Prototyp/Definition, und ob die Funktion ihr Ergebnis zurückgibt.Mit Schleife und Verzweigung aus 2.1.3 wird eine Funktion anzahl_teiler gebaut, die zählt, wie viele Teiler eine Zahl hat (für 12: 1, 2, 3, 4, 6, 12 → 6). Eine zweite Funktion nutzt sie: Eine Primzahl hat genau zwei Teiler.
Implementiere beide Funktionen, indem du die Zeilen ordnest.
return anzahl; in die Schleife: Dann endet die Funktion schon beim ersten Durchlauf und liefert immer 1. Auch int anzahl = 0; muss vor der Schleife stehen, sonst wird der Zähler in jedem Durchlauf zurückgesetzt. ist_primzahl(1) liefert übrigens korrekt 0: 1 hat nur einen Teiler.void erhoehe(int x) { x = x + 5; } int erhoehe2(int x) { x = x + 5; return x; }
Jede Zeile unten steht allein in main. Lege für jede Zeile fest, ob sie 10 ausgibt — markiere alle, bei denen das zutrifft.
return bringt einen Wert aus der Funktion heraus — und nur, wenn der Aufrufer ihn auch verwendet. erhoehe(a) und ein nicht zugewiesenes erhoehe2(a) ändern a nicht: Ausgabe 5. Die Falle: Dass der Parameter genauso heißt wie die Variable in main (x), ändert nichts — es bleiben zwei verschiedene Variablen. Zeile 4 gibt trotzdem 10 aus, weil erst bei der Ausgabe 5 addiert wird; erhoehe2(erhoehe2(a)) - a ist 15 − 5.main und im Parameter bedeuten nicht dieselbe Variable.