8. Grundlagen von Funktionen C++ Programm Bestandteile eines C++ - Programms C++ Kern vordefinierte Datentypen, Operatoren, Befehle Standardbibliothek vordefinierte Funktionen und Klassen Anwender Selbsterstellte Funktionen, Klassen, Sonstiges externe Bibliotheken Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 2 Beispiele für Funktionen Formeln/mathematische Funktionen while (fabs (x*x-a) >=1.0e-10 ); flaeche=pow(durchmesser,2)*pi/4; x1=sqrt( b**2 - 4*a*c); y=cos(x*pi); s=log(y) ir=rand(); Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 3 Beispiele für Funktionen Andere Funktionen Sortieren der Elemente eines Vektors erforderlich: Vektorelemente + Anzahl Ergebnis: sortierter Vektor Suchen eines Elements in einem Vektor erforderlich: Vektorelemente + Anzahl + Suchelement Ergebnis: gefundener Index (Stelle) Ein-/Ausgabe eines Vektors erforderlich: Vektorelemente + Anzahl Ergebnis: eingelesener/angezeigter Vektor Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 4 8.1 Einfache selbstgeschriebene Funktionen Merkmale Eine Funktion hat einen Wert (Typ) Eine Funktion hat (mehrere) Parameter Die Parameter sind Variable, Konstante oder Ausdrücke ( wie hier x*x-a ) Prinzipieller Aufruf : funktionsname(parameter1,parameter2,.....,parameter_n) die Funktion erscheint rechts vom = Operator (R-Wert) also z.b. w=widerstand(laenge,durchmesser) ; cout<<widerstand(laenge,durchmesser) <<endl; Ausnahme Funktionen vom Typ void stehen nicht rechts vom = Operator. also z.b. swap(a,b);//vertauscht a und b Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 5 Prototyp Selbstgeschriebene Funktion/Beispiel // Funktion # include <iostream> #include <cmath> using namespace std; int main() { // Deklarationen double func_widerstand(double,double); double laenge, radius, widerstand; // Eingabe cout << "Laenge (m) angeben :"; cin >> laenge; cout << "Radius (mm) angeben :"; cin >> radius; // Plausibilitätsbetrachtung if ( radius <= 0 ) // unzulässig { cout << " Radius muss > 0 sein "; return 1; } else // Eingabedaten in Ordnung { widerstand= func_widerstand(laenge,2*radius); // Ausgabe cout << " Laenge \t" << laenge << " m" << endl; cout << " Radius \t" << radius <<" mm" << endl; cout << " Widerstand \t" <<widerstand <<" Ohm"<<endl; return 0; } } aktuelle Parameter Dr. Norbert Spangler / Grundlagen der Informatik double func_widerstand (double p_laenge,double p_durchmesser) { const double pi=3.14159, rho=0.0178; double flaeche; flaeche=pow(p_durchmesser,2)*pi/4; return rho*p_laenge/flaeche; } formale Parameter Definition Aufruf Variante 1: alles in einer Datei z.B. main.cpp Üblicherweise kommt main zuerst 10.11.2006 6 Selbstgeschriebene Funktion/Dateien Variante 2 Jede „Funktion“ in einer separaten Quellcodedatei main.cpp enthält „das Programm“ func.cpp enthält die Definition der Funktion Jede Datei wird dabei separat übersetzt und nach allen Übersetzungen wird durch den Linker die exe-Datei erzeugt. Hinweis: In diesem Fall muss in func.cpp #include <cmath> enthalten sein. Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 7 Signatur Die Signatur einer Funktion besteht aus der Anzahl und dem Typ der Parameter unter Berücksichtigung der Reifenfolge double func_widerstand(double,double); Dies ist wichtig, um Funktionen mit gleichem Namen unterscheiden zu können. Der Compiler vergleicht die Signaturen und ruft dann entsprechend passende auf. Es wird ein Link-Fehler angezeigt, wenn es keine passende Funktion gibt. Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 8 8.2 Prototyp (Deklaration) Im Programmteil, wo die Funktion aufgerufen wird, ist der Funktionsprototyp anzugeben. Erforderlich ist die Angabe von Typ und Name der Funktion, sowie der Typ der Parameter double func_widerstand(double,double); Namen für die Parameter sind erlaubt, aber nicht erforderlich double func_widerstand(double laenge,double durchmesser); Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 9 8.3 Definition Definition Angabe von Typ der Funktion entspricht dem Typ des return-Wertes Name der Funktion wie ein Variablenname Deklarationsliste Typ und Name der Parameter (genauer : formale Parameter) Funktionsblock {hier steht was die Funktion macht } im Funktionsblock wird der Wert der Funktion ermittelt und durch return wert; beendet und dem dem aufrufenden Programm das Ergebnis (wert) übergeben Ist die Funktion vom Typ void, so wird sie durch return; beendet. Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 10 Definition/Beispiel double func_widerstand (double p_laenge,double p_durchmesser) { const double pi=3.14159, rho=0.0178; double flaeche; flaeche=pow(p_durchmesser,2)*pi/4; return rho*p_laenge/flaeche; } Achtung: Alle hier vorkommenden Größen sind lokale Größen der Funktion p_laenge, p_durchmesser, pi, tho, flaeche Ist die Funktion vom Typ void darf mittels return kein Wert zurückgegeben werden (also nur return; ). Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 11 8.4 Funktionsaufruf Aufruf Im aufrufenden Programm (genauer: in der aufrufenden Funktion) werden anstelle der formalen Parameter die aktuellen Parameter eingesetzt: funktionsname(aktuellerparameter1,....,aktuellerparametern) Die aktuellen Parameter können Ausdrücke sein! Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 12 Ablauf des Aufrufs Beim Aufruf der Funktion erfolgt ein Sprung aus dem aufrufenden Programmteil zur Adresse der Funktion, die „Rücksprungadresse“ wird gemerkt und nach einem return dorthin „zurückgesprungen“. Alle für das Unterprogramm benötigten Objekte werden auf dem Stack gespeichert (formale Parameter, lokale Variable, Rücksprungadresse). -> hoher „organisatorischer“ Aufwand bei „kleinen“ Funktionen Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 13 Parameterübergabe Programm Aufruf, Rücksprungadresse merken widerstand(laenge,2*radius) Aktuelle Parameter auswerten und auf formale Parameter kopieren widerstand(p_laenge,p_durchmesser) Funktionsblock ausführen (lokale Objekte : p_laenge,p_durchmesser,flaeche,pi,rho) Rücksprungadresse holen, Wert mittels return übergeben Programm Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 14 Parameterübergabe Beim Aufruf werden die aktuellen Parameter ausgewertet (Ausdrücke) Speicher auf dem Stack für lokale Variable, formale Parameter Rücksprungadresse werden bereitgestellt Die Werte der aktuellen Parameter werden auf die formalen Parameter kopiert Technik der Parameterübergabe : Call by Value Konsequenz : Die aktuellen Parameter können in der Funktion nicht geändert werden (da nicht bekannt)! Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 15 Parameterübergabe Vorteil Ausdrücke werden nur ein mal ausgewertet, wenn der Parameter häufig in der Funktion verwendet wird. Parameter können nicht versehentlich geändert werden (Überschreiben von „Konstanten“) Nachteil Parameter mit hohem Speicherplatzbedarf werden dupliziert !!! Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 16 Beispiele/1 Summation Man erstelle eine Funktion, welche die Summe der natürlichen Zahlen von 1 bis n durch Summation bestimme. summe(n) = 1+ ...+n Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 17 Beispiel/1: Summation int summe (int n) { int h=0; for (int i=1;i<=n;i+=1) h+=i; return h; } Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 18 Beispiele 2/ Vertauschen Man erstelle eine Funktion, welche die Werte zweier ganzer Zahlen vertauscht. Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 19 Beispiele 2/Vertauschen // Funktionsaufruf/Variablentausch #include <iostream> using namespace std; void main() { int a=2,b=3; void swap (int,int); cout << " programm anfang a " << a << " b " << b << endl; swap(a,b); cout << " programm ende a " << a << " b " << b << endl; } void swap (int i1,int i2) { int h; cout << " swap anfang i1 " << i1 << " i2 " << i2 << endl; h=i1; i1=i2; i2=h; cout << " swap ende i1 " << i1 << " i2 " << i2 << endl; } Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 20 Vertauschen/Ergebnis Und nun? ->Lösung später Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 21 8.5 Rekursion Man erstelle eine Funktion, welche die Summe der natürlichen Zahlen von 1 bis n durch Summation bestimme. summe(n) = 1+ ...+n = 1+ ...+(n-1) + n (falls n>1) = summe(n-1) + n (falls n>1) Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 22 Rekursion Bei der Definition einer Funktion darf die Funktion selbst verwendet werden. 0 falls n <= 0 summe(n) = n + summe(n-1) falls n > 0 Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 23 Beispiel/Summation rekursiv int summe (int n) { if ( n<= 0 ) return 0; else return n + summe(n-1); } Rekursive Programme lassen sich in der Regel leichter formulieren Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 24 8.6 Eindimensionale Vektoren als Parameter // Vektoren als Parameter #include <iostream> using namespace std; void main() { double y[10]={2.1,4.2,6.3,8.4,10.5,12.6,14.7,16.8,18.9,20},ergebnis; double summe( double[],int); // Prototyp ergebnis=summe(y,5); // Aufruf cout<<" Ergebnis "<<ergebnis<<endl; } double summe ( double p_x[],int n) // Definition { double summe=0.0; for (int i=0;i<=n;i++) summe+=p_x[i]; return summe; } Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 25 Eindimensionale Vektoren als Parameter double summe( double[],int); // Prototyp -> im Prototyp ist nach dem Typ eine [] anzugeben bei Vektoren ergebnis=summe(y,5); // Aufruf -> im Aufruf ist nur der Name des Vektors anzugeben. Die Anzahl der verwendeten Komponenten steht in einen separaten Parameter vom Typ int. double summe ( double p_x[],int n) // Definition -> in der Definition ist ebenfalls [] anzugeben. Achtung: In diesem Fall wird keine lokale Kopie angelegt. Es wird mit den Originaldaten gearbeitet. -> genaue Technik später Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 26 8.7 Testen von Funktionen Funktionen sollten in der Regel ausserhalb der Einsatzumgebung separat getestet werden. Daher ist für den Test ein separates main zu erstellen, welches dies übernimmt: Treiber. Dieses Programm hat somit die Aufgabe, den für die Funktion erstellten Testplan durchführen zu können. Variante 1: Die erforderlichen Daten werden im Dialog/aus einer Datei gelesen Variante 2: alle Beispieldaten werden im main festgelegt. In diesem Fall können unterschiedliche Varianten eines Programmabbruchs nicht getestet werden. Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 27 Testen von Funktionen/Beispiel Variante 1 // Funktion # include <iostream> #include <cmath> using namespace std; int main() { // Deklarationen double func_widerstand(double,double); double laenge, radius, widerstand; // Eingabe cout << "Laenge (m) angeben :"; cin >> laenge; cout << "Radius (mm) angeben :"; cin >> radius; // Plausibilitätsbetrachtung if ( radius <= 0 ) // unzulässig { cout << " Radius muss > 0 sein "; return 1; } else // Eingabedaten in Ordnung { widerstand= func_widerstand(laenge,2*radius); // Ausgabe cout << " Laenge \t" << laenge << " m" << endl; cout << " Radius \t" << radius <<" mm" << endl; cout << " Widerstand \t" <<widerstand <<" Ohm"<<endl; return 0; } } Dr. Norbert Spangler / Grundlagen der Informatik Alternative: zusätzlicheSchleife, um mehrere Eingaben zu ermöglichen 10.11.2006 28 Testen von Funktionen/Beispiel Variante 2 // Funktion # include <iostream> #include <cmath> using namespace std; int main() { // Deklarationen double func_widerstand(double,double); // Abbruchfälle cout<< “Fall 1 Laenge -1 Durchmesser 1 Ergebnis “<< widerstand(-1,0)<<endl; cout<< “Fall 2 Laenge 0 Durchmesser 1 Ergebnis “<< widerstand(0,10)<<endl; cout<< “Fall 3 Laenge 1 Durchmesser -1 Ergebnis “<< widerstand(1,-1)<<endl; cout<< “Fall 4 Laenge 1 Durchmesser 0 Ergebnis “<< widerstand(1,0)<<endl; cout<< “Fall 5 Laenge a Durchmesser b Ergebnis “<< widerstand‘a‘,‘b‘)<<endl; //!!!!!!!!!!! //Normalfall cout<< “Fall 6 Laenge 5 Durchmesser 0.25 Ergebnis “<< widerstand(5,0.25)<<endl; // Grenzfaelle cout<< “Fall 7 Laenge 5 Durchmesser 0.0001 Ergebnis“<< widerstand(5,0.0001)<<endl; cout<< “Fall 8 Laenge 0,05 Durchmesser 0.25 Ergebnis “<< widerstand(0.05,0.25)<<endl; } Dr. Norbert Spangler / Grundlagen der Informatik 10.11.2006 29