Startseite

Funktionen

Code modular gestalten

Eigene Funktionen schreiben und verwenden

Grundlagen der Programmierung

Lernziele

Nach dieser Vorlesung konnen Sie:

  • Verstehen, was Funktionen sind und warum sie wichtig sind
  • Eigene Funktionen definieren und aufrufen
  • Funktionen mit Parametern erstellen
  • Ruckgabewerte verwenden
  • Funktionsprototypen richtig einsetzen
  • Programme modular und ubersichtlich strukturieren

Was ist eine Funktion?

Eine Funktion ist ein benannter Codeblock, der eine bestimmte Aufgabe erfullt.

Funktionen, die wir schon kennen:

printf("Hallo Welt!\n"); // Ausgabe auf dem Bildschirm scanf("%d", &zahl); // Eingabe von der Tastatur strlen(text); // Lange eines Strings strcmp(s1, s2); // Vergleich zweier Strings

Diese Funktionen wurden von anderen Programmierern geschrieben.
Jetzt lernen wir, eigene Funktionen zu schreiben!

Warum eigene Funktionen?

1. Code-Wiederverwendung

Einmal schreiben, mehrmals verwenden - kein Copy-Paste!

2. Bessere Organisation

Komplexe Programme in kleinere, verstandliche Teile aufteilen

3. Lesbarkeit

Code wird ubersichtlicher und leichter zu verstehen

4. Wartbarkeit

Fehler finden und beheben wird einfacher

Anatomie einer Funktion

Ruckgabetyp Funktionsname(Parameter) { // Funktionskorper (Body) // Hier steht der Code return wert; // optional }
Bestandteil Beschreibung Beispiel
Ruckgabetyp Welchen Datentyp gibt die Funktion zuruck? int, double, void
Funktionsname Wie heißt die Funktion? berechneFlaeche
Parameter Welche Eingaben benotigt die Funktion? int breite, int hoehe
Funktionskorper Was macht die Funktion? Alle Anweisungen zwischen { }

Erste einfache Funktion

void = Funktion gibt nichts zuruck
Keine Parameter = Funktion benotigt keine Eingaben

#include <stdio.h> // Funktion definieren void gruesse() { printf("Hallo!\n"); printf("Willkommen zur Programmierung!\n"); printf("Schon, dass du da bist!\n"); } int main() { // Funktion aufrufen gruesse(); return 0; }
Hallo! Willkommen zur Programmierung! Schon, dass du da bist!

Funktion mehrmals aufrufen

Eine Funktion kann beliebig oft aufgerufen werden!

void sternlinie() { printf("********************\n"); } int main() { sternlinie(); // Aufruf 1 printf(" Willkommen!\n"); sternlinie(); // Aufruf 2 printf(" Grundlagen\n"); sternlinie(); // Aufruf 3 return 0; }
******************** Willkommen! ******************** Grundlagen ********************

Wie funktioniert ein Funktionsaufruf?

void sagHallo() { printf("Hallo aus der Funktion!\n"); } int main() { printf("Start von main()\n"); sagHallo(); // <-- Sprung zur Funktion printf("Zuruck in main()\n"); return 0; }

Ablauf:

1. Programm startet in main()
2. Bei sagHallo() springt das Programm zur Funktion
3. Funktion wird ausgefuhrt
4. Programm kehrt zuruck zu main()
5. Nachste Zeile nach dem Aufruf wird ausgefuhrt

Funktionen mit Parametern

Parameter ermoglichen es, Daten an eine Funktion zu ubergeben!

void gruesseBenutzer(char name[]) { printf("Hallo %s!\n", name); printf("Schon, dich zu sehen!\n"); } int main() { gruesseBenutzer("Anna"); gruesseBenutzer("Max"); gruesseBenutzer("Lisa"); return 0; }
Hallo Anna! Schon, dich zu sehen! Hallo Max! Schon, dich zu sehen! Hallo Lisa! Schon, dich zu sehen!

Mehrere Parameter

Parameter werden durch Komma getrennt!

void zeigeInfo(char name[], int alter, double groesse) { printf("Name: %s\n", name); printf("Alter: %d Jahre\n", alter); printf("Grosse: %.2f m\n", groesse); printf("\n"); } int main() { zeigeInfo("Anna", 20, 1.65); zeigeInfo("Max", 22, 1.80); return 0; }
Name: Anna Alter: 20 Jahre Grosse: 1.65 m Name: Max Alter: 22 Jahre Grosse: 1.80 m

Funktionen mit Ruckgabewert

Ruckgabewert: Eine Funktion kann ein Ergebnis zuruckgeben!

Bisher: void (kein Ruckgabewert)

void sagHallo() { printf("Hallo!\n"); // Gibt nichts zuruck }

Neu: Funktion mit Ruckgabewert

int gibZahl() { return 42; // Gibt eine Zahl zuruck! }

Ruckgabetyp festlegen

Der Ruckgabetyp gibt an, welchen Datentyp die Funktion zuruckgibt:

Ruckgabetyp Bedeutung Beispiel
void Kein Ruckgabewert void zeigeText() {...}
int Gibt eine Ganzzahl zuruck int berechneAlter() {...}
double Gibt eine Kommazahl zuruck double berechneFlaeche() {...}
char Gibt ein Zeichen zuruck char gibBuchstabe() {...}

Wichtig: Der Ruckgabetyp muss zum return-Wert passen!

Einfaches Beispiel: Quadrat berechnen

#include <stdio.h> // Funktion: Berechnet das Quadrat einer Zahl int quadrat(int x) { int ergebnis = x * x; return ergebnis; // Ergebnis zuruckgeben } int main() { int zahl = 5; int resultat; resultat = quadrat(zahl); // Ruckgabewert speichern printf("Das Quadrat von %d ist %d\n", zahl, resultat); return 0; }
Das Quadrat von 5 ist 25

Die Funktion quadrat(5) gibt 25 zuruck!

Ruckgabewert direkt verwenden

Den Ruckgabewert muss man nicht immer in einer Variablen speichern!

int quadrat(int x) { return x * x; } int main() { // Direkt in printf verwenden printf("5^2 = %d\n", quadrat(5)); printf("10^2 = %d\n", quadrat(10)); // In Berechnungen verwenden int summe = quadrat(3) + quadrat(4); printf("3^2 + 4^2 = %d\n", summe); return 0; }
5^2 = 25 10^2 = 100 3^2 + 4^2 = 25

Weitere Beispiele mit Ruckgabewerten

// Maximum von zwei Zahlen int maximum(int a, int b) { if (a > b) { return a; } else { return b; } } // Durchschnitt von drei Zahlen double durchschnitt(int a, int b, int c) { double summe = a + b + c; return summe / 3.0; } int main() { printf("Maximum von 7 und 12: %d\n", maximum(7, 12)); printf("Durchschnitt: %.2f\n", durchschnitt(10, 20, 30)); return 0; }
Maximum von 7 und 12: 12 Durchschnitt: 20.00

void vs. Ruckgabetyp

void (kein Ruckgabewert)

void druckeFlaeche(int b, int h) { int flaeche = b * h; printf("Flache: %d\n", flaeche); // Kein return! } int main() { druckeFlaeche(5, 3); return 0; }

Funktion gibt nur aus, gibt aber nichts zuruck

Mit Ruckgabewert

int berechneFlaeche(int b, int h) { int flaeche = b * h; return flaeche; } int main() { int ergebnis = berechneFlaeche(5, 3); printf("Flache: %d\n", ergebnis); return 0; }

Funktion gibt Wert zuruck, kann weiterverwendet werden

Ubung: Rechteckflache berechnen

Aufgabe:

Schreiben Sie eine Funktion rechteckFlaeche, die:

  • Zwei Parameter nimmt: breite und hoehe (beide int)
  • Die Flache berechnet (breite × hoehe)
  • Das Ergebnis als int zuruckgibt

Losung:

int rechteckFlaeche(int breite, int hoehe) { return breite * hoehe; } int main() { int flaeche = rechteckFlaeche(8, 5); printf("Die Flache ist: %d\n", flaeche); return 0; }

Mehrere return-Anweisungen

Eine Funktion kann mehrere return-Anweisungen haben!
Bei der ersten return-Anweisung wird die Funktion beendet.

// Pruft, ob eine Zahl positiv ist int istPositiv(int zahl) { if (zahl > 0) { return 1; // Wahr (true) } else { return 0; // Falsch (false) } } int main() { if (istPositiv(10)) { printf("10 ist positiv!\n"); } if (!istPositiv(-5)) { printf("-5 ist nicht positiv!\n"); } return 0; }

Haufige Fehler mit return

Fehler 1: return vergessen

int addiere(int a, int b) { int summe = a + b; // Fehler: kein return! } // ⚠️ Compiler-Warnung!

Fehler 2: Falscher Ruckgabetyp

int addiere(int a, int b) { return "Hallo"; // ⚠️ Fehler: String statt int! }

Fehler 3: return bei void

void sagHallo() { printf("Hallo!\n"); return 5; // ⚠️ Fehler: void gibt nichts zuruck! }

Ubung: Funktionen mit Ruckgabewerten

Aufgaben:

  1. Schreiben Sie eine Funktion istGerade(int zahl), die pruft, ob eine Zahl gerade ist (return 1 fur ja, 0 fur nein)
  2. Schreiben Sie eine Funktion minimum(int a, int b), die das Minimum von zwei Zahlen zuruckgibt
  3. Schreiben Sie eine Funktion kreisFlaeche(double radius), die die Flache eines Kreises berechnet (π × r²)

Tipp: π (Pi) konnen Sie als 3.14159 approximieren!

Losung: Funktionen mit Ruckgabewerten

// Aufgabe 1: Pruft, ob eine Zahl gerade ist int istGerade(int zahl) { if (zahl % 2 == 0) { return 1; // Gerade } else { return 0; // Ungerade } } // Aufgabe 2: Gibt das Minimum von zwei Zahlen zuruck int minimum(int a, int b) { if (a < b) { return a; } else { return b; } } // Aufgabe 3: Berechnet die Flache eines Kreises double kreisFlaeche(double radius) { double pi = 3.14159; return pi * radius * radius; }

Funktionsprototypen

Problem:

int main() { int summe = addiere(5, 3); // ⚠️ Fehler: addiere() noch nicht bekannt! return 0; } int addiere(int a, int b) { return a + b; }

Der Compiler kennt addiere() noch nicht, wenn er main() ubersetzt!

Losung: Funktionsprototyp (Vorwartsdeklaration)

Ein Prototyp sagt dem Compiler: "Diese Funktion existiert, Details kommen spater!"

Warum brauchen wir Prototypen?

Funktionsprototyp = "Versprechen" an den Compiler

Ein Prototyp sagt dem Compiler:

  • Welchen Namen die Funktion hat
  • Welche Parameter sie nimmt
  • Was sie zuruckgibt
  • Die Details (der Funktionskorper) kommen spater
// Syntax eines Prototyps: Ruckgabetyp Funktionsname(Parameterliste); // <-- Semikolon! // Beispiele: int addiere(int a, int b); double berechneFlaeche(double radius); void druckeText(char text[]);

Wo platziere ich Funktionen?

Moglichkeit 1: Vor main()

#include <stdio.h> // Funktion vor main() int addiere(int a, int b) { return a + b; } int main() { int summe = addiere(5, 3); printf("%d\n", summe); return 0; }

Kein Prototyp notig!

Moglichkeit 2: Nach main() mit Prototyp

#include <stdio.h> // Prototyp am Anfang int addiere(int a, int b); int main() { int summe = addiere(5, 3); printf("%d\n", summe); return 0; } // Funktion nach main() int addiere(int a, int b) { return a + b; }

Ubersichtlicher bei vielen Funktionen!

Vollstandiges Beispiel mit Prototyp

#include <stdio.h> // ===== PROTOTYPEN ===== int quadrat(int x); void druckeLinie(); // ===== HAUPTPROGRAMM ===== int main() { druckeLinie(); printf("5 zum Quadrat: %d\n", quadrat(5)); printf("8 zum Quadrat: %d\n", quadrat(8)); druckeLinie(); return 0; } // ===== FUNKTIONSDEFINITIONEN ===== int quadrat(int x) { return x * x; } void druckeLinie() { printf("====================\n"); }
==================== 5 zum Quadrat: 25 8 zum Quadrat: 64 ====================

Typische Programmstruktur

#include <stdio.h> #include <string.h> // ========================================== // FUNKTIONSPROTOTYPEN // ========================================== void zeigeMenue(); int leseZahl(); int berechneErgebnis(int a, int b, char operation); // ========================================== // HAUPTPROGRAMM // ========================================== int main() { zeigeMenue(); // ... Rest des Codes return 0; } // ========================================== // FUNKTIONSDEFINITIONEN // ========================================== void zeigeMenue() { // ... } int leseZahl() { // ... } int berechneErgebnis(int a, int b, char operation) { // ... }

Funktionen arbeiten zusammen

Funktionen konnen andere Funktionen aufrufen!

#include <stdio.h> int quadrat(int x) { return x * x; } int summeQuadrate(int a, int b) { int quadrat_a = quadrat(a); // Ruft quadrat() auf int quadrat_b = quadrat(b); // Ruft quadrat() auf return quadrat_a + quadrat_b; } int main() { int ergebnis = summeQuadrate(3, 4); // 3² + 4² = 9 + 16 = 25 printf("Ergebnis: %d\n", ergebnis); return 0; }
Ergebnis: 25

Best Practices: Funktionsnamen

Gute Funktionsnamen:

  • Beschreibend: Name sagt, was die Funktion macht
  • Verben verwenden: berechneFlaeche(), zeigeText()
  • CamelCase: istGerade(), leseZahl()
  • Nicht zu lang, nicht zu kurz: Finde die Balance!
Schlecht Gut Warum?
f1() berechneFlaeche() Beschreibend
zahl() leseZahl() Verb verwenden
BerechneDieFlaeche() berechneFlaeche() Nicht zu lang

Wann sollte ich eine neue Funktion erstellen?

Code-Wiederholung

Wenn Sie denselben Code mehrmals schreiben → Funktion!

Logische Einheit

Wenn Code eine klare, eigenstandige Aufgabe erfullt → Funktion!

Ubersichtlichkeit

Wenn main() zu lang wird (>50 Zeilen) → Funktionen!

Komplexitat reduzieren

Wenn Code schwer zu verstehen ist → In Funktionen aufteilen!

Faustregel: Eine Funktion sollte eine Aufgabe erfullen und diese gut!

Praxis-Beispiel: Taschenrechner

#include <stdio.h> // Prototypen int addiere(int a, int b); int subtrahiere(int a, int b); int multipliziere(int a, int b); double dividiere(int a, int b); int main() { printf("10 + 5 = %d\n", addiere(10, 5)); printf("10 - 5 = %d\n", subtrahiere(10, 5)); printf("10 * 5 = %d\n", multipliziere(10, 5)); printf("10 / 5 = %.2f\n", dividiere(10, 5)); return 0; } int addiere(int a, int b) { return a + b; } int subtrahiere(int a, int b) { return a - b; } int multipliziere(int a, int b) { return a * b; } double dividiere(int a, int b) { return (double)a / b; }

Beispiel: Temperatur-Umrechnung

#include <stdio.h> // Celsius zu Fahrenheit double celsiusZuFahrenheit(double celsius) { return (celsius * 9.0 / 5.0) + 32.0; } // Fahrenheit zu Celsius double fahrenheitZuCelsius(double fahrenheit) { return (fahrenheit - 32.0) * 5.0 / 9.0; } int main() { double temp_c = 25.0; double temp_f = celsiusZuFahrenheit(temp_c); printf("%.1f°C = %.1f°F\n", temp_c, temp_f); printf("%.1f°F = %.1f°C\n", temp_f, fahrenheitZuCelsius(temp_f)); return 0; }
25.0°C = 77.0°F 77.0°F = 25.0°C

Beispiel: Eingabe-Validierung

#include <stdio.h> // Pruft, ob Zahl positiv ist int istPositiv(int zahl) { return zahl > 0; } // Pruft, ob Zahl im Bereich liegt int istImBereich(int zahl, int min, int max) { return zahl >= min && zahl <= max; } int main() { int alter = 20; if (istPositiv(alter)) { printf("Alter ist gültig!\n"); } if (istImBereich(alter, 18, 65)) { printf("Alter liegt zwischen 18 und 65!\n"); } return 0; }

Beispiel: Array-Funktionen

#include <stdio.h> // Array ausgeben void druckeArray(int arr[], int groesse) { for (int i = 0; i < groesse; i++) { printf("%d ", arr[i]); } printf("\n"); } // Maximum finden int findeMax(int arr[], int groesse) { int max = arr[0]; for (int i = 1; i < groesse; i++) { if (arr[i] > max) { max = arr[i]; } } return max; } int main() { int zahlen[] = {5, 12, 3, 8, 15}; int groesse = 5; druckeArray(zahlen, groesse); printf("Maximum: %d\n", findeMax(zahlen, groesse)); return 0; }

Beispiel: String-Funktionen

#include <stdio.h> // String ausgeben mit Dekoration void druckeText(char text[]) { printf("*** %s ***\n", text); } // Lange eines Strings manuell berechnen int gibLaenge(char text[]) { int laenge = 0; while (text[laenge] != '\0') { laenge++; } return laenge; } int main() { char name[] = "Grundlagen"; druckeText(name); printf("Lange: %d Zeichen\n", gibLaenge(name)); return 0; }
*** Grundlagen *** Lange: 10 Zeichen

Beispiel: Menu-System

#include <stdio.h> void zeigeMenue() { printf("\n=== HAUPTMENU ===\n"); printf("1. Option A\n"); printf("2. Option B\n"); printf("3. Beenden\n"); printf("Wahl: "); } int leseAuswahl() { int wahl; scanf("%d", &wahl); return wahl; } void fuehreAktionAus(int wahl) { if (wahl == 1) { printf("Option A ausgewahlt!\n"); } else if (wahl == 2) { printf("Option B ausgewahlt!\n"); } } int main() { int wahl; do { zeigeMenue(); wahl = leseAuswahl(); fuehreAktionAus(wahl); } while (wahl != 3); return 0; }

Vollstandiges Beispiel: Taschenrechner

#include <stdio.h> void zeigeMenue(); double berechne(double a, double b, char op); int main() { double zahl1, zahl2, ergebnis; char operation; zeigeMenue(); printf("Erste Zahl: "); scanf("%lf", &zahl1); printf("Operation (+, -, *, /): "); scanf(" %c", &operation); printf("Zweite Zahl: "); scanf("%lf", &zahl2); ergebnis = berechne(zahl1, zahl2, operation); printf("\nErgebnis: %.2f\n", ergebnis); return 0; } void zeigeMenue() { printf("=== TASCHENRECHNER ===\n"); } double berechne(double a, double b, char op) { if (op == '+') return a + b; if (op == '-') return a - b; if (op == '*') return a * b; if (op == '/') return a / b; return 0; }

Haufige Fehler und Debugging

1. Funktionsaufruf ohne Klammern

int ergebnis = quadrat; // ⚠️ Falsch! int ergebnis = quadrat(5); // ✓ Richtig!

2. Falsche Anzahl Parameter

int addiere(int a, int b) { ... } int summe = addiere(5); // ⚠️ Fehler: zu wenig Parameter! int summe = addiere(5, 3); // ✓ Richtig!

3. Prototyp vergessen

// ⚠️ Kein Prototyp! int main() { quadrat(5); // Fehler: quadrat() nicht bekannt! } int quadrat(int x) { ... }

Zusammenfassung

Funktionen sind Code-Blocke mit:

  • Ruckgabetyp: Was gibt die Funktion zuruck? (void, int, double, ...)
  • Name: Wie heißt die Funktion?
  • Parameter: Welche Eingaben braucht sie?
  • Funktionskorper: Was macht sie?

Vorteile von Funktionen:

  • Code-Wiederverwendung
  • Bessere Organisation
  • Leichter zu lesen und zu warten
  • Fehler einfacher finden

Funktionsprototypen ermoglichen es, Funktionen nach main() zu definieren!

Vielen Dank!

Viel Erfolg beim Programmieren mit Funktionen!