Fun as in Function

Mein Vater sagte zu mir immer: „Funktionier doch mal!“

Das hat mir im Leben nie weitergeholfen, aber ich verstehe jetzt, dass er darauf hinweisen wollte, dass in C viele Funktionen bereits in der Bibliothek vorliegen, aber es gleichzeitig auch die Möglichkeit gibt, selber Funktionen zu schreiben.
Das hatten wir damals auch bei Assembler schon angewandt. Mit „call“ konnte eine Funktion, die irgendwo im Code stand, aufgerufen werden.

Wenn eine Funktion geschrieben wird, ist sie genauso aufgebaut wie die „main“-Funktion. Also: Name, Klammern mit Platz für die Parameter, Anweisungsblock in geschweiften Klammern inkl. Deklaration der Variablen. Ein Beispiel:

 #include <stdio.h>

raeum_dein_zimmer_auf () 
{
       int deadline;
       for (deadline=1; deadline<=13; deadline=deadline+1)
              printf("\nIch hab dir jetzt tausendmal gesagt, du sollst
                        dein Zimmer aufräumen!\n");
}

main () 
{ 
....

Und so weiter, und so fort.
Die Variable „deadline“ kann ich auch in den anderen Funktionen verwenden, was ich nicht tun würde. Aber für solche häufig verwendeten Variablen wie „x“ oder „y“ ist das durchaus hilfreich. Der Name der Funktion darf aus Buchstaben, Zahlen und Unterstrichen bestehen und maximal 31 Zeichen lang sein. Der Lesbarkeit und Einheitlichkeit halber sollten Wörter durch Unterstrich getrennt sein, nicht mit einem Unterstrich beginnen und möglichst keine Großbuchstaben beinhalten.

Die Funktion oben ist womöglich gut geeignet, wenn ein gestörtes Kommunikationsverhältnis vorliegt und wenn die Prämisse gilt, dass das Zimmer bis 13 Uhr aufgeräumt sein soll. Aber eigentlich sollten Funktionen flexibler gestaltet werden für andere Anwendungen. Dafür gibt es die Funktionsparameter. Ein Beispiel:

linie(int zeichen, int laenge)
{
        int i;
        for(i=1; i<laenge; i++)                           /*(1)/
                printf("%c", zeichen);
}

main ()
{
        int zeichen, wieoft;
        printf("\nIch schreibe jetzt 10 Fragezeichen.\n");
        linie('?', 10);
        printf("\nWelches Zeichen: ");
        zeichen=getchar();                                
        printf("Wie oft schreiben: ");
        scanf("%i", &wieoft);                             /*(2)/
        printf("\n");
        linie(zeichen, wieoft);                           /*(3)/
        printf("\n");
}

Neu ist zunächst der Ausdruck i++ in der for-Schleife (1). Der bedeutet aber dasselbe wie i+1. Das haben wir bisher verwendet, um dem Programm zu sagen, dass es die Variable um 1 inkrementieren, also erhöhen soll. Sieht anscheinend geiler as in professioneller aus und spart mehr oder weniger wertvolle Lebenszeit.

/*Nachtrag: Falsch, i++ ist nicht dasselbe wie i+1, sondern wie i=i+1,
danke erlehmann! Geht übrigens auch mit i– (dekrementieren)/

Die Parameter in der ersten Zeile sind als int definiert. Die Werte für die Variablen werden in der main-Funktion durch die Eingabe der User bestimmt (2). Bei (3) werden sie als int-Werte an die Funktion übergeben (obwohl eine Zeichenkonstante (char) eingelesen wurde, diese kann aber von C auch als Code des zugehörigen Zeichens interpretiert werden, also für „?“ eine „63“).

Ein drittes Beispiel soll die eigentlich wichtigste Funktionen-Funktion darstellen: Die Rückgabe von Werten. Wäre ja schade drum, wenn das Programm für mich 1+1 ausrechnet, ich aber nicht an das Ergebnis komme.

#include <stdio.h>

int max(int a, int b)
{
        if (a > b)
                return a;                     /*(1)/
        else 
                return b;
}

main ()
{
        int zahl1, zahl2, ja1, ja2;
        printf("\nBitte geben Sie eine Zahl ein: ");
        scanf("%i", &zahl1);
         printf("\nBitte geben Sie eine Zahl ein: ");
        scanf("%i", &zahl2);
        printf("\nTrommelwirbel!\n");
        printf("\nBitte irgendeine irrelevante Zahl eingeben: ");
        scanf("%i", &ja1);
        printf("\nWarte... warte... schon aufgeregt?\n");
        printf("\nBitte noch irgendeine Zahl eingeben: ");
        scanf("%i", &ja2);
        printf("\nDie Zahl %i ist groesser!\n",          
                max(zahl1,zahl2));                         /*(2)/
}

Die max-Funktion gibt den größeren von zwei int-Werten aus. Das tut sie aufgrund der return-Anweisung (1). Diese beendet zum Einen die Schleife, zum Anderen sorgt sie dafür, dass der Wert, der ausgegeben wurde an die aufrufende Stelle (2) geliefert wird.
Das passiert in der letzten Zeile dieses Programms, das sich mit schlecht.s um den vorletzten Platz auf dem Sinnvolle-Programme-Ranking streitet. Dem Platzhalter %i wird also der Wert zugewiesen, den return von max aus bekommen hat.

Bleibt zu bemerken, dass man aufpassen sollte, dass die Rückgabetypen der Funktionen rechtzeitig definiert werden. Standardgemäß geht der Compiler davon aus, dass der Rückgabewert vom Typ int ist. Blöd, wenn er nicht int ist, sondern bspw. double. Wenn die Funktion also aufgerufen wird und erst später die nicht-int-Typen definiert werden, ist das Programm im Arsch.  Am Leichtesten lässt sich das natürlich bewerkstelligen, indem die Funktion auf jeden Fall vor dem ersten Aufrufen definiert wird. Das geht ganz einfach, indem man bspw. am Anfang des Programms, noch vor der main-Funktion schreibt:

double func (double, double);

Was irgendwie nach einem generischen Gabba-Song-Titel aussieht, ist ein Funktionsprototyp. In den Klammern müssen keine Variablen-Bezeichnungen stehen, sondern nur die Typen. Außerdem wird die Klammer mit einem Semikolon beendet. Semikolonsemikolonsemikolon. Nicht vergessen!

Hier, nochmal, zum Üben: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

In meinem Chat, den ich hier aus Gründen nochmal ausschreibe:

##fionalerntprogrammieren auf freenode
(join!)

gab es dann heute morgen auch nochmal eine schöne Diskussion darüber, wie sinnvoll die Längenbregrenzung für Funktionsnamen ist.
Eingangs wusste ich einfach nicht, woher die Begrenzung auf 31 Zeichen kommt. Scheint mir „historische Gründe“ zu haben. Darauf wurde aber nicht wirklich geantwortet, stattdessen wurde sich darüber gestritten, dass unsinnige Bezeichnungen auch mit weniger als 31 Zeichen möglich sind, Beispiele: ffhvfdhfddchfdvzffbfdf() oder penis2() .
Einige waren der Meinung, dass eindeutige Bezeichnungen auch mal so richtig schön lang sein können und sollten, andere, darunter ich, finden es einfach nur hässlich und unhandlich, wenn Funktionsnamen zu lang sind.

Aber vielleicht hat die Eine oder der Andere noch etwas weltbewegendes dazu zu sagen, dann können wir den Streit in den Kommentaren fortsetzen. Und wer darauf besteht, dass penis(2) eine sinnvolle Bezeichnung ist, wird gelöscht.

%d Bloggern gefällt das: