1 Seite 1 Einführung in die Programmierung mit C++ Teil IV - Weiterführende Themen 13. Klassenbibliotheken Klassenbibliotheken Seite 2 Sammlung von Algorithmen und Klassen in Klassenbibliotheken: Konzept: Wiederverwendbarkeit von Code Voraussetzung Schnittstellen sind allgemein gehalten Informationsschutzprinzip wurde angewandt Schnittstellen sind gut dokumentiert Beispiel: C++ Standard Klassenbibliothek
2 C++ Standard Klassenbibliothek Seite 3 Zeichenketten (Strings) Ein- und Ausgabe (Streams) generische Container-Klassen einschliesslich Iteratoren und Algorithmen Alle Klassen und Namen im Namensraum std entweder am Anfang using namespace std; oder allen Klassen und Namen std:: voranstellen String Klasse I Seite 4 Header #include <string> Konstruktoren std::string( const char * ) std::string( std::string ) Kopie von normalem C String Kopierkonstruktor Operatoren =, +, += Kopieren, Zusammenführen und Anhängen [..] Zugriff auf einzelne Zeichen Methoden find(), rfind(), substr() insert(), erase(), replace() length(), size() c_str() Suchen und extrahieren von Substrings Operationen auf Substrings Länge bzw. Größe abfragen zu C String umwandeln
3 String Klasse II Seite 5 Beispiel (benötigt iostream und string Header) std::string a( "Hallo" ); std::tring b( a ); // (eigenständige) Kopie von a std::string c; // zunächst leer c = a + b; cout << c << endl; a += ", Welt"; cout << a << endl; cout << b << endl; c.erase( 5, 5 ); c.insert( 4, "ihall" ); cout << c << endl; // "HalloHallo" // "Hallo, Welt" // "Hallo" // "Hallihallo" string::size_type pos = c.find( "hallo", 0 ); cout << pos << endl; // 5 Ein- und Ausgabe I Seite 6 Header #include <iostream> allgemein Ein-/Ausgabe Objekte cin, cout, cerr, clog endl Standardeingabe, -ausgabe, -fehlerausgaben New Line Operatoren <<, >> Ausgabe an bzw. Eingabe von Stream
4 Ein- und Ausgabe II Seite 7 Header #include <fstream> Ein-/Ausgabe in Dateien Klassen ifstream, ofstream fstream Dateiabstraktion für Lese- bzw. Schreibzugriff Dateiabstraktion für wahlfreien Zugriff Methoden open(), close() read(), write() tellg(), seekg(), tellp(), seekp() öffnen und schließen Zugriff auf Binärdateien Abfragen/Setzen des Lese-/Schreibzeigers Ein- und Ausgabe III Seite 8 Beispiel (benötigt iostream, fstream und string Header) std::string name; std::cin >> name; std::cout << "Hallo, " << name << std::endl; std::ofstream( "name.dat" ) ofile; ofile << name; std::ifstream( "name.dat" ) ifile; ifile >> name; std::cout << "Hallo, " << name << std::end; char buffer[100]; std::fstream file1( "file.dat", std::ios::in ); std::fstream file2( "file.dat", std::ios::out ); file1.read( buffer, 100 ); for ( int i = 0; i < 50; ++i ) { char temp = buffer[i]; buffer[i] = buffer[99-i]; buffer[99-i] = temp; file2.write( buffer, 100 ); file1.close(); file2.close();
5 Container Klassen I Seite 9 Container-Objekte enthalten andere Objekte sehr oft gebraucht, mit verschiedenen Inhaltstypen daher als Klassenschablonen implementiert Klassen für verschiedene Zugriffsmuster vector wahlfreier Zugriff, schnelles Anfügen am Ende, langsames Einfügen am Anfang, Integer als Indizes list schnelles Einfügen überall, nur serieller Zugriff deque (double-ended queue) wahlfreier Zugriff, schnelles Einfügen am Anfang und Ende, Integer als Indizes stack einfügen/entnehmen nur am Ende map wahlfreier Zugriff, beliebige Typen als Indizes (Schlüssel) oft auch Dictionary genannt Container Klassen II Seite 10 Methoden insert() erase() clear() size() capacity() empty() push_back() pop_back() push_front() pop_front() Einfügen eines Elements Löschen eines Elements Löschen aller Elemente Anzahl der gespeicherten Elemente abfragen Anzahl der Elemente, die gespeichert werden können bevor neuer Speicher allokiert werden muss Prüft ob Container leer ist Anhängen ans Ende Entfernen vom Ende Einfügen am Anfang (außer vector) Entfernen vom Anfang (außer vector) Operatoren [..] wahlfreier Zugriff (vector, deque)
6 Iteratoren I Seite 11 Iteratoren zeigen auf Elemente innerhalb eines Containers jeder Container hat eigene Iteratortypen mit spezifischen Eigenschaften Vorwärts- und Rückwärtsiteratoren alle Iteratoren können zum nächsten (Vorwärtsiterator) bzw. vorherigen (Rückwärtsiterator) Element springen Inkrement Operator ++ sowohl bei Vorwärts- als auch bei Rückwärtsiteratoren Iteratoren von wahlfreien Containern (vector, deque) erlauben auch Sprünge um beliebig viele Elemente Sprünge entgegen der eigentlichen Richtung Dekrement Operator -- Iteratoren II Seite 12 Container Methoden zum Erzeugen eines Iterators begin(), rbegin() Vor-/Rückwärts-Iterator auf erstes/letztes Element end(), redn() Vor-/Rückwärts-Iterator hinter letztes/vor erstes Element wenn begin() und end() identisch dann Container leer Iterator Operatoren ++ nächstes Element *, -> Elementzugriff == Vergleich (wahr wenn zwei Iteratoren auf selbes Element verweisen) Iterator operatoren für wahlfreie Container -- vorheriges Element +, -, mathematische Operationen auf Zugriffsindex +=, -=
7 Container Klassen und Iteratoren I Seite 13 Beispiel zu vector (benötigt iostream und vector Header) std::vector<int> container; container.push_back( 4 ); container.insert( container.begin(), 3 ); container.insert( container.begin(), 1 ); container.insert( container.begin(), 0 ); std::vector<int>::iterator while ( iter!= container.end() ) std::cout << * iter++ << std::endl; if ( * iter == 3 ) break; container.insert( iter, 2 ); Container Klassen und Iteratoren II Seite 14 Fortsetzung if ( * iter == 2 ) break; container.erase( iter ); container[2] = 2; container[3] = 3; iter = container.begin() + 2; std::cout << * iter << std::endl; std::vector<int>::reverse_iterator riter = container.rbegin(); while ( riter!= container.rend() ) std::cout << * riter++ << std::endl; std::cout << container.size() << std::endl;
8 Container Klassen und Iteratoren III Seite 15 Beispiel zu list (benötigt iostream und list Header) std::list<int> container; container.push_back( 4 ); container.insert( container.begin(), 3 ); container.insert( container.begin(), 1 ); container.insert( container.begin(), 0 ); std::list<int>::iterator while ( iter!= container.end() ) std::cout << * iter++ << std::endl; if ( * iter == 3 ) break; container.insert( iter, 2 ); Container Klassen und Iteratoren IV Seite 16 Fortsetzung if ( * iter == 2 ) break; container.erase( iter ); if ( * iter == 3 ) * iter = 2; if ( *iter == 4 ) * iter = 3; std::list<int>::reverse_iterator riter = container.rbegin(); while ( riter!= container.rend() ) std::cout << * riter++ << std::endl; std::cout << container.size() << std::endl;
9 Container Klassen und Iteratoren V Seite 17 Beispiel zu vector (benötigt iostream und vector Header) class test { public: void print() { std::cout << "Buh!" << std::endl ; ; vector<test> container; test t; container.push_back( t ); container.begin()->print(); container[0].print(); Eigene Datentypen in Container Klassen Seite 18 Container Klassen verwenden Kopier-Konstruktoren und Zuweisungs-Operatoren der enthaltenen Datentypen Diese müssen daher bei Verwendung von nicht-eingebauten Datentypen sinnvoll definiert sein Wichtig insbes. bei interner Allokierung von Speicher in Objekten Kopier-Konstruktor/Zuweisungs-Operator müssen in kopiertem Objekt neuen Speicher allokieren und den Inhalt des allokierten Speichers im ursprünglichen Objekt kopieren Nicht lediglich Zeiger auf allokierten Speicher kopieren Speicher kann doppelt freigegeben werden