FB Informatik Prof. Dr. R.Nitsch Prozeduren und Funktionen Reiner Nitsch ℡ 8417 [email protected] www.fbi.h_da.de/~r.nitsch Wozu Prozeduren/Funktionen? FB Informatik Prof. Dr. R.Nitsch • Verbergen von Implementierungsdetails bzw. Komplexität – Abstraktion dient dazu, Komplexität zu verstecken – Prozeduren/Funktionen sind ein Mittel der Abstraktion (man interessiert sich nicht mehr für bestimmte Details, vereinfacht die Realität). Hier spielt es für den Benutzer/Aufrufer keine Rolle, • wie die Prozedur/Funktion ihre Aufgabe löst, sondern nur Prozedurale Abstraktion • was sie genau macht. Input ? Output Prozedur/Funktion als Black-Box-Abstraktion • Strukturierung von Code – Programme können beliebig lang sein (Spaghetti-Code, schwer zu verstehen, schlecht wiederverwendbar) – Oft braucht man im gleichen Programm an verschiedenen Stellen ein gleiches Stück Programmcode (Bsp: Menüs anzeigen, Grafikobjekte zeichnen, Textdateien einlesen, … ). – Um die Lesbarkeit & Änderbarkeit& Übersichtlichkeit des Programms zu verbessern, sollte dieser Programmcode nur einmal aufgeschrieben werden. – Das ist mit Prozeduren/Funktionen möglich: • Man kann einem Stück Programmcode einen Namen geben, und es dann an verschiedenen Stellen im Programm aufrufen (ausführen lassen). 30.03.2009 2 Wozu Prozeduren/Funktionen? FB Informatik Prof. Dr. R.Nitsch • Delegation von Teilaufgaben – Zerlegen einer komplexen Aufgabe in mehrere, einfacher lösbare Teilaufgaben (Teile und Herrsche) und Delegation dieser Teilaufgaben an Prozeduren/Funktionen (Programming by delegation) • Wiederverwendung von Code – Mehrere solcher Prozeduren bzw. Funktionen mit gleichem Focus werden oft zu Klassen, Modulen, Bibliotheken zusammengefaßt (z.B. Grafikbibliothek, Mathematische Bibliothek, C++ Standardbibliothek, … ) • Vorteile solcher Bibliotheken: Die Wiederverwendung bereits getesteter Funktionen – spart Zeit und Geld – verkürzt die time-to-market und – verbessert die Zuverlässigkeit neuer Software. 30.03.2009 3 Anforderungen an Prozeduren und Funktionen FB Informatik Prof. Dr. R.Nitsch • Sollten nur für eine genau definierte Aufgabe zuständig sein. • müssen bei Bedarf einen oder mehrere Eingabewerte (Eingabeparameter) übernehmen können – Sie dienen der Übermittlung von Werten aus dem aufrufenden Programm an die Proz./Fkt. • Sollten nicht mehr als die unbedingt nötigen Eingabeparameter erwarten. • Sollten Ergebnisse bei Bedarf zurückgeben können. – Funktionen haben genau einen Rückgabewert. • Er dient der Übermittlung eines Wertes (Ergebnis) aus der Funktion an das aufrufende Programm • Funktionen können daher in Ausdrücken dort eingesetzt werden, wo ein Wert erwartet wird. – Prozeduren haben keinen Ausgabewert und können daher nicht in Ausdrücken für einen Wert stehen. Sie werden stets in einer einzelnen Anweisung aufgerufen. • Sollten gut dokumentiert sein (Aufgabe, Vorbedingungen, Nachbedingungen) • Minimale Abhängigkeit vom Rest des Programms durch – möglichst kleine/einfache Schnittstelle zum Rest des Programms. • In Prozeduren/Funktionen kann man auch selbst wieder Prozeduren/Funktionen aufrufen. 30.03.2009 4 Bestandteile eines C++ Programms FB Informatik Prof. Dr. R.Nitsch Bestandteile eines C++ Programms Kern von C++ Standardtypen Operatoren Kontrollstrukturen Klassen und Prozeduren/Funktionen der Standardbibliothek Selbsterstellte Klassen und Prozeduren/Funktionen und weitere Bibliotheken C++ kennt keine keine spezielle Syntax für Prozeduren. In C++ sind Prozeduren einfach Funktionen ohne Ausgabewert. 30.03.2009 5 Globale benutzerdefinierte Funktion ohne Parameter #include <iostream> using namespace std; void main () { // show menu cout << "[1] Eingabe\n"; cout << "[2] Ausgabe\n"; cout << "[9] Fertig\n"; // … } Wird mehrmals im Programm verwendet. cut&paste Nachteile? void steht für "kein Rückgabewert" #include <iostream> namespace std; void showMenu(); void main() { showMenu(); // … } Funktionsname besser mit Funktionsaufruf Funktionsdeklaration oder Funktionsprototyp Funktionsaufruf Funktionskopf void showMenu() { cout << "[1] Eingabe\n"; cout << "[2] Ausgabe\n "; cout << "[9] Fertig\n"; return; } 30.03.2009 Funktionsdefinition Funktionsrumpf FB Informatik Prof. Dr. R.Nitsch • Die Funktiondeklaration (Fkt-Prototyp) beschreibt das Funktionsinterface. Sie enthält für den Compiler alle erforderlichen Angaben (Typ, Reihenfolge und Menge der Ein- und Ausgabewerte), um den Funktionsaufruf übersetzen zu können. Merke: • Eine Funktion muss vor der ersten Benutzung deklariert aber nicht definiert sein. • Eine Funktion kann überall und beliebig oft deklariert werden. • Die Definition kann dann hinter main am Ende der Datei oder in einer ganz anderen Datei (z.B. Library) stehen. • Die Funktionsdefinition (Implementierung) sagt dem Compiler, wie die Funktion ihre Aufgabe erledigen soll. • In C++ können Funktionen nicht innerhalb anderer Funktionen definiert werden. • Die einmal übersetzte Funktionsdefinition wird nach jedem Aufruf ausgeführt. 6 Globale Funktion mit Parametern und mit/ohne Rückgabewert FB Informatik Prof. Dr. R.Nitsch Um die Funktionsdeklarationen nicht in jeder Anwendung neu eintippen zu müssen, werden Sie in Header-Dateien (*.h) zusammengefaßt und diese Header-Dateien von der Anwendung inkludiert. #include <iostream> using namespace std; Typ des Rückgabewerts Typ des Parameters double getCircleArea( double radius Formalparameter; hier nur 1 Parameter ); Variablenspeicher Parametername (optional; zur Dokumentation) int main() lokale Variable der Funktion main { Stapelspeicher r 2.0 double r = 2.0; (Stack) cout << getCircleArea(r) << endl; area 12.56 Kopie return 0; radius 2.0 } Aktualparameter 12.56 Rückgabewert Funktionswert … Formalparameter Name hier zwingend! (Eingangstür zur Fkt.) double getCircleArea(double radius ) { double area; area = 3.14 * radius * radius; return area; } Lokale Variable (Name optional) der Funktion getCircleArea (lokale Variable, d.h. im Hauptprogramm main nicht bekannt und nicht zugreifbar) Kopie Ausgangstür der Funktion. Nicht die lok. Variable area wird hier zurückgegeben, sondern die Kopie ihres Wertes im Stack 30.03.2009 7 Ablauf eines Funktionsaufrufs FB Informatik Prof. Dr. R.Nitsch … weitere lokale Parameter Beim Rücksprung "poppen" letzter Parameter … 1. Parameter Beim Aufruf "pushen" Stack (Stapelspeicher) oder LIFO (Last In First Out) Funktionswert Rücksprungadresse • Reservierung von Speicherplatz auf dem Stapelspeicher (stack) für die FormalParameter. Initialisierung der Formal-Parameter mit den Aktual-Parametern (Argumenten). • Speichern der Rücksprungadresse (= Stelle des Funktionsaufrufes im Programm) auf dem Stack und Fortsetzung des Programms am Anfang der aufgerufenen Funktion. • Nach Ausführung der Funktion, Fortsetzung des Programms in der aufrufenden Funktion mit Hilfe der gesicherten Rücksprungadresse. Freigabe des belegten Stacks. 30.03.2009 8 Benutzung von Bibliotheksfunktionen FB Informatik Prof. Dr. R.Nitsch // Calculation of powers xy with function pow( double x, double y ) #include <iostream> #include <cmath> // Hinzufügen aller Funktionsdeklarationen der math-Library using namespace std; int main() double x y = pow( y = pow( y = pow( { = 1.5, y; x, 3.0 ); x, 3 ); x, 2+1 ); y = pow( "x", 3); y = pow( x + 3 ); cout << y << endl; return 0; } // ok! return-Wert an y zuweisen // auch ok! Typkonversion int → double durch Compiler // Auch ok! Als Parameterwert darf auch ein beliebiger Ausdruck übergeben werden // Aber Anzahl und Typ der Parameter müssen passen! // Fehler: Typkonflikt // Fehler: nur 1 Parameter // Ausgabe: 3.375 = 1.53 Woher weiß der Compiler Anzahl und Typ der erwarteten Parameter ? // cmath enthält die Deklaration double pow( double x, double y ); 30.03.2009 9 Struktur eines C++ Programms FB Informatik Prof. Dr. R.Nitsch Programmkopf Präprozessor-Direktiven (z.B. #include) Deklaration von globalen Objekten Funktionsdeklarationen (i.A. in Header-Dateien) Klassendeklarationen (i.A. in Header-Dateien) Implementierung int main() { // Variablendefinitionen … // Ausführbare Anweisungen … return 0; } Klassenimplementierung Funktionsimplementierung 30.03.2009 10 HS-Übung 1 FB Informatik Prof. Dr. R.Nitsch • Finden Sie die Fehler in den folgenden Programmfragmenten und erklären Sie, wie der Fehler behoben werden kann. a) int g(void) { cout << "in Funktion g\n"; int h(void){ cout << "in Funktion h\n"; } } c) void f(double a){ float a; cout << a << endl; } 30.03.2009 b) int sum( int x, int y){ int result ; result = x+y; } d) void product (void){ int a, b, c, ergebnis; cout << "Gib 3 Ganzzahlen ein: "; cin >> a >> b >> c; result = a * b * c; cout << "Ergebnis: << result << endl; return result; } 11 HS-Übung 2 FB Informatik Prof. Dr. R.Nitsch • Definieren Sie eine Funktion, welche die Seitenlängen eines Quaders übergeben bekommt und das Volumen des Quaders zurück gibt. Integrieren Sie den Funktionsaufruf in die nachfolgende Anwendung. Geben Sie das Ergebnis auf dem Bildschirm aus. //Zweck: Berechnung des Quadervolumens #include <iostream> using namespace std; int main (void){ double a, b, c; cout << "Gib die Seitenlaengen eines Quaders: "; } 30.03.2009 13 Zusammenfassung: Prozeduren / Funktionen FB Informatik Prof. Dr. R.Nitsch • • • • • • • • lösen eine abgeschlossene Teilaufgabe, erbringen Leistungen, die mehrmals im Programm anfallen (können), müssen vor erstmaligem Aufruf deklariert (oder implementiert) werden, verursachen einen geringen Laufzeitverlust beim Aufruf, können (in C++) nicht innerhalb anderer Funktionen definiert werden, verbergen Implementationsdetails vor dem Anwender, erleichtern die Wiederverwendung von Code, sollten genau umrissene Einzelaufgaben lösen, die sich in der Namensgebung wiederspiegeln. Kleine Funktionen unterstützen die Wiederverwendbarkeit. • sind die Bausteine, aus denen C-Programme bestehen, • müssen in C++ innerhalb von Klassen ( -> Memberfunktionen) oder global definiert sein, d.h. Funktionsdefinitionen dürfen nicht verschachtelt sein. 30.03.2009 14