[Home]
für Einsteiger!
Seite:  [1] - Drucken

Inhalt:


Funktionen - Teil 2

Obwohl wir uns schon mit Funktionen beschäftigt haben, kann man noch viel mehr lernen. Dieser zweite Teil beinhaltet immernoch nicht alle Dinge, die man mit Funktionen machen kann, soll aber eine gute Übersicht geben und ein paar Programmiertechniken einbringen!
 
Funktionen sind nicht zu unterschätzen. Sie helfen Übersicht in ein Programm zu bringen und ersparen Tipparbeit: Man ruft eine Funktion eben mehfach auf anstatt jedesmal alles zu schreiben!
 
Funktionen haben einen Rückgabetyp: Dies kann ein "normaler" Datentyp sein, oder "void". Void bedeutet, dass die Funktion nichts zurückliefert!
Man kann den Rückgabewert auch als Fehlerindikator benutzen (d.h.: Zurückgeben, dass alles OK/Nicht OK war...). (In C++ kann man allerdings besser mit "exceptions" arbeiten, später mehr!)
 

Prototypen

Benutzt du in einer Funktion eine andere, muss diese darüber bereits [b/g]eschrieben sein. Es reicht allerdings aus, einen Prototypen zu schreiben, wie wir es bereits getan haben. Durch das konsequente Benutzen werden Fehlerquellen minimiert. Es reicht aus, Rückgabetyp, Name, Parameterzahl und Typ zu kennen. Die Namen der Parameter können, müssen aber nicht angegeben werden!
 
Ein anderes Anwendungsgebiet liegt bei (eigenen) Bibliotheken. Wenn du eine Sammlung von Funktionen geschreiben hast, und diese einem anderen Programmierer zur Verfügung stellen willst, muss dieser die Prototypen in sein Programm einfügen.
(z.B. mit einem header den du dann via "#include" einbeziehst...
 
(Außerdem entweder die "*.cpp"-Datei mitkompilieren oder die (von dir) mitgegebene Bibliotheken-Object-Datei dazulinken!)
Siehe dazu auch: Andere Bibliotheken benutzen. Wenn wir andere Bibliotheken nutzen / eigene Bibliotheken schreiben, werde ich allerdings sowieso darauf zurückkommen!

Ein Prototyp steht in deinem Programm über der main()-Funktion!
Quelltext
  1. int quadrat(int); //Prototyp
  2.  
  3. //Noch ein Prototyp:
  4. int quadrat(int i); //Name des Parameters
  5. //kann angegeben werden, muss aber nicht...
  6.  

 

Die main()-Funktion (Teil 1)

Die main Funktion gibt einen integer zurück! Sie kann entweder gar keinen Parameter haben ("main(){...}") oder einen ("main(int argc){...}"; ungewöhnlich). Dann gibt es die Variante mit zweien ("main(int argc, char *argv[]){...}"):
Quelltext
  1. int main();
  2. int main(int argc); //Selten, aber möglich
  3. int main(int argc, char *argv[]);
  4. int main(int argc, char *argv[], char *env[]);
  5. //Sehr selten, nur auf einigen Systemen sinnvoll
  6.  
  7. /*
  8. argc ist die Anzahl der Parameter.
  9. argv[0] ist das, was der Nutzer getippt hat,
  10.   um das Programm zu starten.
  11. argv[1 bis argc-1] speichert die Parameter.
  12. env[] speichert die Environment-Variablen.
  13. */
  14.  

 
Tippt der nutzer nun z.B. "demo.exe --test --help", so bietet sich das folgende Bild:
argc=3
argv[0]="demo.exe"
argv[1]="--test"
argv[2]="--help"

 
Was sollen die Parameter denn? Ganz einfach: Vielleicht kennst du das Kommando "DEL" (DOS) oder "rm" (Linux)?! Da rufst du das Programm mit einem Parameter auf: Die zu löschende(n) Datei(en). Stell dir vor, du müsstest eine Abfrage mit "cin" schreiben... Willst du nun dein Programm so schreiben, das du Hilfe bekommen kannst, schreibst du z.B. eine "if()"-Abfrage ein, die prüft, ob ein Parameter namens "--help" übergeben wurde...
Um die Parameter (mit Ausnahme von "argc" zu benutzen, musst du wissen, wie man in C(++) mit Buchstaben, Wörtern und Sätzen umgeht... Das ist allerdings erst das Thema des Dritten großen Teils! (s. linke Spalte - Kommt ja bald!!! ;) ). Ich werde dann nocheinmal darauf zurückkommen, wie man mit diesen Parametern arbeiten kann...

Ein Paar andere Dinge zu Funktionen

  • Funktionen müssen immer außerhalb einer anderen, wie der main() Funktion definiert werden!
  • Sie sollten, wie auch Variablen, einen sinnvollen Namen bekommen
  • Man kann mehrere Funktionen mit dem gleichen Namen schreiben, solange ihre Parameter sich voneinander durch Anzahl oder Typ unterscheiden. Dies nennt man "Überladen", oder "Polymorphie" ("Vielgestaltigkeit"). Der Rückgabewert ist beim Überladen übrigens egal! Nur sich unterscheidende Rückgabetypen können nicht zur Unterscheidung genutzt werden!
    Quelltext
    1. bool saghallo()
    2. void saghallo(int i)
    3. int saghallo(float f)
    4.  
    5. //aber nicht:
    6. int test()
    7. void test()
    8. float test()
    9.  
  • Rekursion: Rekursive Funktionen sind Funktionen, die sich immer wieder mit veränderten Parametern aufrufen. Gleich mehr... (nächster Abschnitt!)
  • Default-Parameter: Wenn du einem Parameter innerhalb des Prototypen/des Funktionskopfes einen Wert zuweist, kann dieser beim Funktionsaufruf weggelassen werden. Geschieht dies, so wird der Standardwert genommen, den du festgelegt hast. Wichtig: Solche default-Parameter dürfen nur am Ende stehen, normale Parameter dürfen dann nicht mehr folgen, damit die Reihenfolge nicht durcheinander gebracht wird. Weitere default-Parameter dürfen folgen, allerdings kann nicht der vorletzte Parameter weggelassen werden, der letzte aber nicht...!
    Quelltext
    1. int test1 (int i=0); //Geht
    2. int test2 (int i=0, int k); //Geht nicht
    3. int test3 (int i, int k=5); //Geht
    4. int test4 (int i=0, int k=9); //Geht
    5.  
    6. // [...]
    7.  
    8. test1(); //Geht: i=0
    9. test1(3); //Geht: i=3
    10.  
    11. test3(2); //Geht: i=2, k=5
    12. test3(2,-19); //Geht: i=2, k=-19
    13.  
    14. test4(); //Geht: i=0, k=9
    15. test4(1); //Geht: i=1, k=9
    16. test4(-19,8); //Geht: i=-19, k=8
    17.  
    18. test4(/*nur k angeben woll*/); //Geht nicht
    19.  
  • static: Lokale Variablen, die ihren Wert nach Verlassen einer Funktion bis zum nächsten Aufruf behalten, nennt man "static": "static int beispiel;"
  • Es gibt auch "inline"-Funktionen: Inline Funktionen werden automatisch an alle Stellen kopiert, wo sie vorkommen. Dadurch wird Speicher (RAM) gespart (Der Computer muss sich nicht merken, von wo er die Funktion aufgerufen hat!) und die binäre, ausführbare Datei größer. Daher nutzt man sie meist bei kleinen, kurzen Funktionen, da sie "inline" schneller sind, aber die Übersichtlichkeit von Funktionen bleibt! Inlinefunktionen werden mit dem Wort "inline" gekennzeichnet, aber ganz normal aufgerufen:
    Quelltext
    1. inline int saghallo() {/*...*/};
    2.  
Aber jetzt zu Praxis!
 

Rekursion & Iteration

Rekursive Funktionen sind Funktionen, die sich immer wieder mit veränderter Parameteranzahl aufrufen.

Als Beispiel soll die Berechnung der Fakultät dienen...
 
Die Fakultät einer natürlichen Zahl ist das Produkt aller vorangegangenen Zahlen von 1 an: (mathematisch: x!)
fak(3) = 3! = 1*2*3
fak(7) = 7! = 1*2*3*4*5*6*7
...

Um diese Funktion zu schreiben, gibt es zwei Möglichkeiten: Die rekursive und die iterative:
Rekursiv Iterativ
Quelltext
  1. int fak_rek(int zahl)
  2. {
  3. if (zahl<=1) //Abbruchbedingung,
  4. // welche nur einen
  5. // Wert zurückgibt,
  6. { // aber die nicht mehr
  7. return 1; // sich selbst (Funktion)
  8. } //aufruft...
  9.  
  10. return (fak_rek(zahl-1)*zahl);
  11. //Aufruf mit ver&auml;nderten Parametern
  12. }
  13.  
Quelltext
  1. int fak_iter(int zahl)
  2. {
  3. int fakult=1;
  4. int faktor=2;
  5. while (faktor<=zahl) //Schleife
  6. {
  7. fakult*=faktor;
  8. faktor++;
  9. }
  10. return fakult;
  11. }
  12.  
Die rekursive Funktion läuft (kaum merklich) langsamer, da der Computer sich den Punkt merkt, von dem er eine Funktion aufruft, um dorthin zurückzukehren. Daher kommt es hier bei SEHR großen Anwendungen zu Abstürzen (kein Arbeitsspeicher etc.):
rekursiv iterativ

Wie geht's weiter?

So, jetzt hast du ein solides Basiswissen! Wenn du noch dabei bist, kannst du dich jetzt auf ein paar leichtere Teile freuen! Jetzt kommt noch eine Zusammenfassung zum Ausdrucken sowie einige Beispiele und Anregungen für eigene Programme! Durchatmen!!
Seite:  [1] - Drucken