c++ kurs teil 3 - uni-freiburg.de€¦ · o. ronneberger: c++ kurs teil 3 seite 5 c-style-strings...
TRANSCRIPT
O. Ronneberger: C++ Kurs Teil 3 Seite 1
C++ Kurs Teil 3
● Standard Template Library (STL)
– Übersicht
– vector<>
– algorithm: sort, for_each
– map<>
● Exceptions
● Kommunikation mit der shell
O. Ronneberger: C++ Kurs Teil 3 Seite 2
Standard Template Library (STL)
● Containers (vector, list, map, ...)
● General Utilities (date, time, ...)
● Algorithms (sort, for_each, ...)
● Strings (string, wide-character stuff, ...)
● Input/Output (streams, manipulators...)
● Language Support (numeric limits, dynamic memory, ...)
● Numerics (sqrt, sin, cos, complex, ...)
O. Ronneberger: C++ Kurs Teil 3 Seite 3
Übersicht über die Standard Container
● vector<T>eindimen-sionales Array
● list<T>doppelt verketteteListe
O. Ronneberger: C++ Kurs Teil 3 Seite 4
Übersicht über die Standard Container
● map<Key,T> assoziatives Array (Binärbaum)
● string: Zeichenkette
O. Ronneberger: C++ Kurs Teil 3 Seite 5
c-style-strings und std::string
/* ein c-style string ist nur ein Pointer! das Ende des strings ist durch '\0' gekennzeichnet */const char* name = "Olaf";
/* std::string ist eine Klasse. Umwandlung von c-style in std::string z.B. durch Zuweisung */std::string name2 = name;
// std::strings können verkettet werdenname2 += ".txt";
/* Umwandlung zurück mit c_str(), z.B. als File Name für einen ifstream */std::ifstream file( name.c_str());
name: 0xdbca0
'O' 'l' 'a' 'f' '\0'0xdbca0:
O. Ronneberger: C++ Kurs Teil 3 Seite 6
Übersicht über die Standard Container
● stack<T>"last in first out" Container
● queue<T>"first in first out" Container (fifo)
● priority_queue<T>teilsortierte Queue (top() liefert immer das größte Element)
● komplette Übersicht in Stroustrup Kapitel 17
O. Ronneberger: C++ Kurs Teil 3 Seite 7
STL vector(eindimensionales Array)
#include <string>#include <vector>
int main( int argc, char** argv){ std::vector<std::string> people; people.push_back( "Chris"); people.push_back( "Bert"); people.push_back( "Detlef"); people.push_back( "Alfons"); people.push_back( "Gerhard"); std::cout << "Der 5. heißt: " << people[4] <<std::endl; people.resize( 7); people[5] = "Fred"; people[6] = "Ernie"; return 0;}
Leeres Array aus strings
Einige strings anfügen (Array wächst automatisch)
Zugriff auf das 5. Element
Vergrößern
O. Ronneberger: C++ Kurs Teil 3 Seite 8
Elemente ausgeben und sortieren
#include <vector>#include <string>#include <algorithm> ....
// Alle Elemente ausgeben std::vector<std::string>::const_iterator p; for( p = people.begin(); p != people.end(); ++p) { std::cout << *p << std::endl; }
// Sortieren std::sort( people.begin(), people.end()); Element, auf
das der Iterator zeigt
Iterator (verhält sich wie ein Pointer)
Quicksort aus 'algorithm'
O. Ronneberger: C++ Kurs Teil 3 Seite 9
Sortieren mit eigener Vergleichs-Funktion
// rückwärts sortieren std::sort( people.begin(), people.end(), myGreaterThan);
bool myGreaterThan( const string &a, const string &b){ return (a > b);}
Die Vergleichsfunktion muß extra definiert werden:
O. Ronneberger: C++ Kurs Teil 3 Seite 10
Andere Methode zur Ausgabe aller Elemente (for_each)
// Alle Elemente ausgeben std::for_each( people.begin(), people.end(), print_entry);
void print_entry( const std::string& name){ std::cout << name << std::endl;}
Für jedes Element zwischen begin() und end() die Funktion print_entry() aufrufen
print_entry() muß extra definiert werden und bekommt eine Referenz auf das jeweilige Element übergeben
O. Ronneberger: C++ Kurs Teil 3 Seite 11
STL map(assoziatives Array)
std::map<std::string, int> histogram;
std::ifstream documentFile( "GPL_V2");
std::string word; while( documentFile >> word) { histogram[word] += 1; } for( std::map<std::string, int>::const_iterator p = histogram.begin(); p != histogram.end(); ++p) { std::cout << p->first << ": " << p->second << std::endl; }
„Array“ vom Typ int mit string als index (wird intern als balancierter Baum gespeichert)
Datei „GPL_V2“ zum Lesen öfnen
Element-Zugriff: Wenn noch kein Eintrag existiert, wird automatisch ein neuer erzeugt
Ausgabe aller Histogramm-Einträge (automatisch alphabetisch sortiert)
O. Ronneberger: C++ Kurs Teil 3 Seite 12
Übersicht über die Standard Container
insert() push_front() push_back()Beispiele:
O. Ronneberger: C++ Kurs Teil 3 Seite 13
Exceptions
● Im traditionellen C (und vielen anderen Sprachen) ist es nicht möglich, die Fehlerbehandlung sauber vom eigentlichen Code zu trennen.
● Fehlerbehandlung wird dort typischerweise über verschiedene Rückgabewerte realisiert.
O. Ronneberger: C++ Kurs Teil 3 Seite 14
Traditionelle Fehlerbehandlung
handle = dc1394_create_handle(0);if (handle==NULL){ exit( 1);}status = dc1394_setup_capture(handle,..., &camera);if( status != DC1394_SUCCESS){ raw1394_destroy_handle(handle); exit(1);}status = dc1394_start_iso_transmission(handle,camera.node);if( status != DC1394_SUCCESS){ dc1394_release_camera(handle,&camera); raw1394_destroy_handle(handle); exit(1);}status = dc1394_single_capture(handle,&camera);if( status != DC1394_SUCCESS){ ...
● Das eigentliche Programm besteht nur aus 4 Zeilen
● Durch die Fehlerbehandlung ist die Struktur des Programmes kaum noch zu erkennen
● Schließen der Firewire-Verbindung erfolgt an etlichen verschiedenen Stellen
O. Ronneberger: C++ Kurs Teil 3 Seite 15
Traditionelle Fehlerbehandlungmeistgenutze Alternative: Fehler ignorieren...
handle = dc1394_create_handle(0);dc1394_setup_capture(handle,..., &camera);dc1394_start_iso_transmission(handle,camera.node);dc1394_single_capture(handle,&camera);
● Da die trad. Fehlerbehandlung zu umständlich ist, wird vielfach der Rückgabewert gar nicht abgefragt. Daraus resultieren dann unerklärliche Abstürze des Programms durch Nutzung von kaputten Datenstrukturen.
O. Ronneberger: C++ Kurs Teil 3 Seite 16
Exceptions
● Exceptions erlauben es, das eigentliche Programm und die Fehlerbehandlung sauber zu trennen.
● Wenn in einer Funktion eine exception "geworfen" wird, wird nicht von der Funktion zurückgesprungen, sondern stattdessen ein passendes catch() gesucht.
try{ handle = dc1394_create_handle(0); dc1394_setup_capture(handle,..., &camera); dc1394_start_iso_transmission(handle,camera.node); dc1394_single_capture(handle,&camera);}catch( int errorNumber){ ....}
O. Ronneberger: C++ Kurs Teil 3 Seite 17
throw, try und catch
● Um eine Exception zu werfen wird der 'throw' Befehl genutzt. Hier wird einfach ein 'int' geworfen
● Die geworfene Exception hangelt sich solange nach oben, bis es ein passendes 'catch' findet. Wenn es keines gibt, wird das Programm abgebrochen.
void irgendeineFunktion(){ ... if (a != b) throw 42; if (x == y) throw 137;}
O. Ronneberger: C++ Kurs Teil 3 Seite 18
Fehlerklassen
● throw( xyz) kann als Aufruf der Methode catch() mit dem Parameter xyz aufgefaßt werden, wobei nach Beendigung des catch-Block natürlich nicht zum Punkt des throws zurückgekehrt wird.
● Einen 'int' als Exception zu werfen, ist nur bedingt brauchbar. Besser ist es, die Standard-Fehlerklassen zu benutzen, oder eine eine eigene FehlerKlasse dafür zu erzeugen, die dann auch noch weitere Information vom throw zum catch transportieren kann
O. Ronneberger: C++ Kurs Teil 3 Seite 19
FehlerklassenEinem try-Block dürfen mehrere catch-Blöcke folgen
void myFunction(){ ...
if( file == 0) { FileOpenError err( fileName); throw err; } ...
if( format == -1) { throw WrongFormatError(); } ...}
try{ ... myFunction(); ...}catch( FileOpenError& err){ std::cerr << "Can't open file " << err.fileName() << std::endl;}catch( WrongFormatError& err){ std::cerr << "File has wrong format\n";}catch( ...) // hier stehen wirklich drei Punkte!{ std::cerr << "Unknown error occured\n";}
O. Ronneberger: C++ Kurs Teil 3 Seite 20
Klassenhierarchien für exceptions
● catch( SppError& err) fängt alle Fehlerklassen (also auch die abgeleiteten)
● catch( SppInternalError& err) fängt alle "internen" Fehler.
● catch( SppErrorDeviceBusy& err) fängt nur den "device busy error"
● Bei Fehlerklassen-Hierarchien Immer "catch by reference", nie "catch bei value"!(siehe Thinking in C++ Vol 2: Programming with exceptions)
// normal errorsclass SppError { .... };class SppErrorDeviceBusy : public SppError {....};...// internal errorsclass SppInternalError : public SppError {....};class SppErrorSaneNotInitialized : public SppInternalError{....};...
O. Ronneberger: C++ Kurs Teil 3 Seite 21
"Resource allocation is initialization"
● Damit geöffnete Resourcen automatisch wieder geschlossen werden, wenn eine exception auftritt, kann man die Methode "Resource allocation is initialization" anwenden:
try{ handle = dc1394_create_handle(0); dc1394_setup_capture(handle,..., &camera); dc1394_start_iso_transmission(handle,camera.node); dc1394_single_capture(handle,&camera);}catch( int errorNumber){ /* Wir wissen nicht, ob raw1394_destroy_handle(handle); aufgerufen werden muß */}
O. Ronneberger: C++ Kurs Teil 3 Seite 22
"Resource allocation is initialization"
try{ ... std::ifstream hurz( "abcdeg.txt"); ...} // hier wird das File hurz durch den Destructor automatisch geschlossencatch( int errorNumber){ /* An dieser Stelle befinden sich die Resourcen wieder in einem "sauberen" Zustand */}
O. Ronneberger: C++ Kurs Teil 3 Seite 23
Kommunikation mit der shell
#include <iostream>
int main( int argc, char** argv){ std::cout << "Der Programmname ist: " << argv[0] << std::endl; std::cout << "Es wurden " << argc-1 << " Argumente übergeben\n"; std::cout << "Das 1. Argument ist: " << argv[1] << std::endl; std::cout << "Das 2. Argument ist: " << argv[2] << std::endl; std::cout << "Das 3. Argument ist: " << argv[3] << std::endl; return 0;}
> sample_code hallo du daDer Programmname ist: sample_codeEs wurden 3 Argumente übergebenDas 1. Argument ist: halloDas 2. Argument ist: duDas 3. Argument ist: da
O. Ronneberger: C++ Kurs Teil 3 Seite 24
Neue Aufgabe: Erweiterung der GrayImage-Klasse, Region-Properties
● Ziel: Koordinaten der Lampen im Bild finden, und Kreuze dort einzeichnen