12/18/12 // POST: values of a and b are interchanged void swap (int& a, int& b) { int c = a; a = b; b = c;

Ähnliche Dokumente
Binäre Suchbäume. Mengen, Funktionalität, Binäre Suchbäume, Heaps, Treaps

Mengen. Binäre Suchbäume. Mengen: Anwendungen (II) Mengen: Lösung mit Listen 12/3/12. Mengen, Funktionalität, Binäre Suchbäume, Heaps, Treaps

Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Rekursion vs. Iteration, Sortieren

Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Rekursion vs. Iteration, Sortieren

Dynamische Datentypen. Destruktor, Copy-Konstruktor, Zuweisungsoperator, Dynamischer Datentyp, Vektoren

Informatik - Übungsstunde

Datenkapselung: public / private

Mapra: C++ Teil 4. Felix Gruber. 6. Mai IGPM, RWTH Aachen. Felix Gruber (IGPM, RWTH Aachen) Mapra: C++ Teil 4 6.

Visuelle Kryptographie. Anwendung von Zufallszahlen

Dynamische Datentypen

Container für eine Folge gleichartiger Daten. Dynamische Datentypen. Probleme mit Feldern...aber nicht mit std::vector. ... und auch std::vector

16. Structs und Klassen I. Rationale Zahlen, Struct-Definition, Operator-Überladung, Datenkapselung, Klassen-Typen

4. Objektorientierte Programmierung mit C++

Übungsstunde: Informatik 1 D-MAVT

18. Vererbung und Polymorphie

Verschlüsseln eines Bildes. Visuelle Kryptographie. Verschlüsseln eines Bildes. Verschlüsseln eines Bildes

kurze Wiederholung class templates

Informatik - Übungsstunde

Repetitorium Programmieren I + II

C++ Kurs Teil 3. Standard Template Library (STL) Kommunikation mit der shell Hyper Text Markup Language (HTML)

Programmieren in C++ Templates

18. Vererbung und Polymorphie

C++ Teil 4. Sven Groß. 30. Apr IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Apr / 16

Die Anwesenheitspflicht beim Seminar gilt für diejenigen Teilnehmer, die einen Schein erwerben wollen. Für die Nachmittagsübungen gilt keine

Programmier-Befehle - Woche 08

Prüfung Informatik D-MATH/D-PHYS :00 17:00

19. Vererbung und Polymorphie

7. Vererbung und Polymorphie

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

Objektorientierte Programmierung mit C Datentypen (Strukturtypen)! p.name = "Willibald Wusel";

17. Klassen. Überladen von Funktionen. Funktionsüberladung. Operator-Überladung (Operator Overloading) operatorop

Prüfung Informatik D-MATH/D-PHYS :00 11:00

variadic templates Templates mit variabler Argumentanzahl?

19. Vererbung und Polymorphie

Repetitorium Programmieren I + II

C++ Teil 5. Sven Groß. 12. Nov IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 16

Lambda-Funktionen. Lambda-Funktionen. Lambda-Funktionen sollen

Programmieren in Java

Wo und wie lange leben Objekte? globale Objekte lokale Objekte dynamische Objekte

Datenkapselung: public / private

Mathematische Rekursion

Mapra: C++ Teil 4. Felix Gruber, Michael Rom. 24. Mai 2016 IGPM. Felix Gruber, Michael Rom (IGPM) Mapra: C++ Teil 4 24.

initializer lists (nicht für Referenzen... unklar warum...)

Einführung Sprachfeatures Hinweise, Tipps und Styleguide Informationen. Einführung in C. Patrick Schulz

Informatik 1 ( ) D-MAVT F2011. Klassen, Funktionen. Yves Brise Übungsstunde 9

Informatik II (D-ITET) Informatik II (D-ITET) Übungsstunde 1. Distributed Systems Group, ETH Zürich

Informatik 1 ( ) D-MAVT F2010. Klassen. Yves Brise Übungsstunde 9

Prüfung A Informatik D-MATH/D-PHYS :15 14:55

C++ Teil 12. Sven Groß. 18. Jan Sven Groß (IGPM, RWTH Aachen) C++ Teil Jan / 11

Pascal Schärli

Polymorphe for-anweisung 237

C++11. neu in C++11: range-based for. Objektorientierte Programmierung mit C++ Ersetzung durch: 1. Elementares C++ int array[] = { 1, 2, 3, 4, 5 };

9. Funktionen Teil II

Felder (Arrays) und Zeiger (Pointers) - Teil I

! "eine Zeichenkette\nmit Doppelapostroph \" und Backslash \\"

Datenkapselung: public / private class rational { r.d = 0 int n; int d; // INV: d!= Klassen rational r; r.n = 1; // error: n is private

Konstruktor/Destruktor

Polymorphismus 44. Function.hpp. #include <string>

Informatik I (D-ITET)

Programmieren in Java

Programmierkurs. Steffen Müthing. January 25, Interdisciplinary Center for Scientific Computing, Heidelberg University

Programmierkurs C/C++

17. Klassen. Datenkapselung, Klassen, Memberfunktionen, Konstruktoren

15. Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Aufrufstapel, Bau eines Taschenrechners, BNF, Parsen

Felder (Arrays) und Zeiger (Pointers) - Teil I

Informatik II (D-ITET) Übungsstunde 5

Lindenmayer-Systeme: Fraktale rekursiv zeichnen

Programmier-Befehle - Woche 10

Woche 6. Cedric Tompkin. April 11, Cedric Tompkin Woche 6 April 11, / 29

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Programmieren - C++ Templates

1 Einleitung Generizität Syntax... 2

Heap vs. Stack vs. statisch. 6 Speicherorganisation. Beispiel Statische Variablen. Statische Variablen

Repetitorium Programmieren I + II

Einführung in die Programmierung mit C++

Polymorphismus 179. Function.h. #include <string>

Felder (Arrays) und Zeiger (Pointers) - Teil I

1.2. Datentypen (Konstantentypen)

Objektorientierte Programmierung mit C++ SS 2007

Objektorientierte Programmierung II

! können default arguments haben: ein Endstück der Argumentliste einer Deklaration mit Wertevorgaben

6 Speicherorganisation

HSR Rapperswil 2001 Markus Rigling. Programmieren: Templates Auflage

Programmieren in Java

Wir erinnern uns... #include <iostream> #include <vector>

10.4 Konstante Objekte

Ein kleiner Blick auf die generische Programmierung

Binäre Suchbäume. Mengen, Funktionalität, Binäre Suchbäume, Heaps, Treaps

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 15/16. Kapitel 13. Bäume. Bäume 1

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 17/18. Kapitel 14. Bäume. Bäume 1

Einführung in die Informatik: Programmierung und Software-Entwicklung, WS 16/17. Kapitel 14. Bäume. Bäume 1

C++ Templates - eine kleine Einführung

Lindenmayer-Systeme: Fraktale rekursiv zeichnen. Definition. Definition. Definition. o Alphabet Σ ( Beispiel: {F, +, -} )

Structs, Referenztypen und Const-Typen

Tutoraufgabe 1 (Implementierung eines ADTs):

DAP2-Programmierpraktikum Einführung in C++ (Teil 2)

Transkript:

Generische Funktionalität Generisches Programmieren Template-Funktionen, Template- Klassen, generisches Sortieren, Fibonacci- und Ackermann-Zahlen zur Kompilierungszeit n Viele Funktionen braucht man für ganz verschiedene Typen void swap (int& a, int& b) int c = a; z.b. beim Sortieren ganzer Zahlen Generische Funktionalität n Viele Funktionen braucht man für ganz verschiedene Typen void swap (double& a, double& b) z.b. beim Sortieren reeller Zahlen Generische Funktionalität n Viele Funktionen braucht man für ganz verschiedene Typen n Ziel: Funktion nur einmal schreiben, und dann für alle passenden Typen aufrufen können. n So eine Funktion heisst generisch. n In C++: Template-Funktion Generisches Swap n Template = Vorlage, Formular n T ist Platzhalter für einen Typ und heisst Template-Parameter Generisches Swap - Aufruf int main() int n1 = 1; int n2 = 2; Instantiierung für int std::cout << n1 << ", " << n2 << std::endl; // 2, 1 double r1 = 1; double r2 = 2; Instantiierung für double std::cout << r1 << ", " << r2 << std::endl; // 2, 1 1

1. Compiler erkennt den Typ von n1, n2 (int) void swap (int& a, int& b) int c = a; 2. Der Compiler erzeugt aus der Vorlage Quelltext für den erkannten Typ, indem der Platzhalter T durch den erkannten Typ ersetzt wird. void swap (int& a, int& b) int c = a; 3. Der Compiler benutzt diesen Quelltext, um den Funktionsaufruf zu übersetzen. 1. Compiler erkennt den Typ von r1, r2 (double) void swap (double& a, double& b) 2. Der Compiler erzeugt aus der Vorlage Quelltext für den erkannten Typ, indem der Platzhalter T durch den erkannten Typ ersetzt wird. void swap (double& a, double& b) 3. Der Compiler benutzt diesen Quelltext, um den Funktionsaufruf zu übersetzen. 2

swap (n1, r2); //??? void swap (double& a, double& b) Fehlermeldung: keine passende Funktion gefunden, implizite Konversion greift bei Template-Funktionen nicht. swap.cpp: In function int main() : swap.cpp:22: error: no matching function for call to swap(int&, double&) Templates: Anforderungen n Eine Template-Funktion stellt implizit Anforderungen an den Typ T const int m1 = 1; const int m2 = 1; swap (m1, m2); //??? Hier: Werte vom Typ T müssen zuweisbar sein (Standard-Jargon: T is assignable ) swap.cpp: In function void swap(t&, T&) [with T = const int] : swap.cpp:26: instantiated from here swap.cpp:7: error: assignment of read-only reference a swap.cpp:8: error: assignment of read-only reference b Templates: Anforderungen n Eine Template-Funktion stellt implizit Anforderungen an den Typ T n Diese Anforderungen sollten dokumentiert sein: // PRE: T is assignable n Zur Erinnerung: minimum-sort void minimum_sort (int* first, int* last) for (int* p = first; p!= last; ++p) int* p_min = p; // pointer to current minimum int* q = p; Mit dieser Funktion können nur int s sortiert werden, die in einem Feld gespeichert sind. n Generisches minimum-sort: void minimum_sort (It first, It last) for (It p = first; p!= last; ++p) It p_min = p; // pointer to current minimum It q = p; It ist Platzhalter für einen Iteratortyp Anforderungen: Vergleichsoperatoren == und!= Dereferenzierungsoperator * Präinkrement-Operator ++ n Generisches minimum-sort: void minimum_sort (It first, It last) for (It p = first; p!= last; ++p) It p_min = p; // pointer to current minimum It q = p; It ist Platzhalter für einen Iteratortyp Anforderungen an den value type von It: assignable comparable Standard-Jargon: Forward Iterator 3

n Generisches minimum-sort: void minimum_sort (It first, It last) for (It p = first; p!= last; ++p) It p_min = p; // pointer to current minimum It q = p; It ist Platzhalter für einen Iteratortyp Erlaubt die Sortierung aller Container, die einen Forward Iterator anbieten zuweisbare und vergleichbare Daten enthalten Generische Ausgabe // POST: the elements of the range are written to std::cout void print(it first, It last) for (It j = first; j!= last; ++j) std::cout << *j << " "; std::cout << std::endl; It ist ein forward iterator (hier reicht sogar ein input iterator, der jedes Element nur einmal anschauen darf) Sortieren von ganzen Zahlen in Feldern Sortieren von Strings in Feldern // sort array of numbers int numbers[] = 2, 4, 0, -1, 5, 7, 0, -3, 10, 3; minimum_sort (numbers, numbers+10); print (numbers, numbers+10); -3-1 0 0 2 3 4 5 7 10 Instantiierung für T = int* // sort array of strings std::string months[] = "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ; minimum_sort (months, months+12); print (months, months+12); Instantiierung für T = std::string* Sortieren von Strings in Feldern Sortieren von ganzen Zahlen in Listen minimum_sort (months, months+12); print (months, months+12); April August December February January July June March May November October September operator< für Strings, der in minimum_sort beim Vergleich *q < *p_min benutzt wird, vergleicht lexikographisch wie im Wörterbuch. // sort list of numbers std::list<int> l; for (int i=0; i<10; ++i) Instantiierung für T = l.push_front(i); std::list<int>::iterator minimum_sort (l.begin(), l.end()); print (l.begin(), l.end()); 0 1 2 3 4 5 6 7 8 9 Zeiger auf das erste und hinter das letzte Element der Liste 4

Template-Klassen n Nicht nur viele Funktionen, sondern auch viele Klassen braucht man für ganz verschiedene Typen n Beispiel: Treaps mit Zahlen (Benutzer- Nummern), Treaps mit Strings (Wörterbuch) Generischer TreapNode: TreapNode<T> class TreapNode public: // constructor TreapNode(T key, int priority, TreapNode<T>* left = 0, TreapNode<T>* right = 0); // Getters const T& get_key() const; int get_priority() const; const TreapNode<T>* get_left() const; const TreapNode<T>* get_right() const; private: ; T key_; int priority_; TreapNode<T>* left_; TreapNode<T>* right_; friend class Treap<T>; Name des generischen Typs Sonst genau gleich wie der alte TreapNode für int, ausser hier: const T& anstatt T Grund: get_key() ist dann auch effizient für schwere Typen mit aufwändigem Copy-Konstruktor Generischer Treap class Treap public: // default constructor: // POST: *this is an empty tree Treap(); // copy constructor // POST *this is a copy of other Treap(const Treap<T>& other); private: TreapNode<T>* root_; Sortieren mit Treaps n Ausgabe der Schlüssel in in-order - Reihenfolge: n Schlüssel im linken Teilbaum, in-order n Wurzel n Schlüssel im rechten Teilbaum, in-order n Das gibt die Schlüssel in sortierter Reihenfolge aus! Sortieren mit Treaps void Treap<T>::print(std::ostream& o) const print(o, root_); Öffentliche Mitgliedfunktion für in-order -Ausgabe void Treap<T>::print(std::ostream& o, const TreapNode<T>* current) const if (current!= 0) print(o, current->get_left()); o << current->get_key() << " "; print(o, current->get_right()); Sortieren mit Treaps void Treap<T>::print(std::ostream& o) const print(o, root_); void Treap<T>::print(std::ostream& o, const TreapNode<T>* current) const if (current!= 0) print(o, current->get_left()); o << current->get_key() << " "; print(o, current->get_right()); Private Mitgliedfunktion für in-order -Ausgabe eines Teilbaums 5

Sortieren mit Treaps - Zahlen Sortieren mit Treaps - Strings // sort some numbers int numbers[] = 2, 4, 0, -1, 5, 7, 0, -3, 10, 3; Treap<int> tn; Instantiierung für T = int for (int i=0; i<10; ++i) tn.insert (numbers[i]); tn.print(std::cout); std::cout << std::endl; 0 1 2 3 4 5 6 7 8 9 // sort some strings std::string months[] = "January", "February", "March", Instantiierung für T = std::string "April", "May", "June", "July", "August", "September", "October", "November", "December ; Treap<std::string> ts; for (int i=0; i<12; ++i) ts.insert (months[i]); ts.print(std::cout); std::cout << std::endl; Sortieren mit Treaps - Strings Ganze Zahlen als Template- Parameter Treap<std::string> ts; for (int i=0; i<12; ++i) ts.insert (months[i]); ts.print(std::cout); std::cout << std::endl; April August December February January July June March May November October September #include<iostream> // POST: returns n % m template <int m> int mod (int n) return n % m; int main () std::cout << mod<7>(10) << std::endl; // 3 Nerd-Alarm: Fibonacci-Zahlen zur Kompilierungsszeit n Ziel: Definition einer Template-Klasse fib<n> mit einem konstanten Datenmitglied, dessen Wert die n-te Fibonacci-Zahl ist. struct A Daten-Mitglied, das der Klasse static const int value = 5; selbst gehört und nicht den ; Objekten der Klassse. int main () std::cout << A::value << std::endl; // 5 Nerd-Alarm: Fibonacci-Zahlen zur Kompilierungsszeit // general template template <int n> struct fib static const unsigned int value = fib<n-1>::value + fib<n-2>::value; ; // specialized templates, n = 0, 1 template <> struct fib<0> static const unsigned int value = 0; ; template <> struct fib<1> static const unsigned int value = 1; ; fib<n> ist eine andere Klasse als fib<n-1> und fib<n-2> Template- Spezialisierung: eigene Klassendefinitionen für die Fälle n=0 und n=1 6

Nerd-Alarm: Fibonacci-Zahlen zur Kompilierungsszeit int main() std::cout << fib<10>::value << std::endl; // 55 Fib<10> ist eine Klasse, die vom Compiler erstellt wurde; insbesondere hat er dabei das Datenmitglied value berechnet. Zur Laufzeit des Programms passiert gar nichts mehr! Nerd-Alarm: Ackermann- Zahlen zur Kompilierungsszeit n + 1, falls m = 0 A (m, n) = A (m-1, 1), falls m > 0, n = 0 A (m-1, A (m, n-1)), falls m > 0, n > 0 o o ist berechenbar, aber nicht primitiv rekursiv (man dachte Anfang des 20. Jahrhunderts, dass es diese Kombination gar nicht gibt) wächst extrem schnell Nerd-Alarm: Ackermann- Zahlen zur Kompilierungsszeit Nerd-Alarm: Ackermann- Zahlen zur Kompilierungsszeit m 0 1 2 3... n 0 1 2 3 4... n+1 1 2 3 4 5... n+2 2 3 5 7 9... 2n+3 3 5 13 29 61... 2 n+3-3 2 6553 4 13 65533 2 65536-3 6 2-3... Berechnung: Dieser Wert ging gerade noch... 2 2 2... -3 //general template template <int m, int n> struct ackermann ; static const unsigned int value = ackermann<m-1, ackermann<m,n-1>::value>::value; // specialized template, m = n = 0 template <> struct ackermann<0,0> ; static const unsigned int value = 1; // specialized templates, m = 0 template <int n> struct ackermann<0,n> ; static const unsigned int value = n+1; // specialized templates, n = 0 template <int m> struct ackermann<m,0> ; static const unsigned int value = ackermann<m-1,1>::value; int main() Versuchen wir den Wert, der gerade noch ging... std::cout << ackermann<4,1>::value << std::endl; Fazit: Compiler braucht ewig. 7