In diesem Abschnitt werden die public-Elementfunktionen von streambuf beschrieben. Es sollten keine reinen Objekte vom Typ streambuf in einem Programm verwendet werden, sondern nur von streambuf abgeleitete Objekte (z.B. filebuf, strstreambuf, stdio- buf)! #include <iostream.h> typedef long streamoff, streampos; class ios enum bin, tabexp}; // und viele andere Klassen, siehe ios. }; class streambuf { public:
virtual int sync(); }; | |||||||||||
Die Klasse streambuf unterstützt Puffer, in die Zeichen eingefügt (put) oder aus denen Zeichen entnommen (get) werden können. Ein solcher Puffer ist eine Folge von Zeichen mit einem oder zwei Zeigern (einem get- und/oder einem put-Zeiger), die die Position beschreiben, an der Zeichen eingefügt oder entnommen werden. Man sollte sich vorstellen, dass die Zeiger zwischen die Zeichen und nicht auf die Zeichen zeigen. Das vereinfacht das Verständnis der Grenzbedingungen (Zeiger vor dem ersten oder hinter dem letzten Zeichen). Einige Auswirkungen des Entnehmens und Einfügens von Zeichen werden durch diese Klasse definiert, die meisten Details bleiben aber den spezialisierten -aus streambuf abgeleiteten -Klassen vorbehalten, siehe filebuf, sstreambuf und stdiobuf. Die aus streambuf abgeleiteten Klassen variieren in der Behandlung der Zeiger get und put. Im einfachsten Fall erlauben die Puffer entweder nur das Einfügen oder nur das Entnehmen von Zeichen. Solche Klassen dienen als reine Quellen (Erzeuger) oder Ziele(Verbraucher) von Zeichen. Warteschlangen-ähnliche Puffer (siehe strstream und sstreambuf) besitzen einen put- und einen get-Zeiger, die unabhängig voneinander verschoben werden können. In solchen Puffern werden gespeicherte Zeichen abgelegt, bis sie zu einem späteren Zeitpunkt wieder entnommen werden. Dateiähnliche Puffer (beispielsweise filebuf; siehe filebuf) erlauben sowohl Einfügungen als auch Entnahmen, weisen aber nur einen Zeiger auf. (In anderen Worten: Die Zeiger get und put sind hierbei zu einem Zeiger kombiniert. Wird ein Zeiger verschoben, so führt dies auch zu einer Verschiebung des anderen Zeigers.) Die meisten Elementfunktionen von streambuf sind in zwei Phasen unterteilt. Soweit als möglich werden die Operationen auf das Speichern in oder Entnehmen aus Feldern (den Bereichen get und put, die gemeinsam den Reservierungsbereich oder Puffer bilden) beschränkt. Von Zeit zu Zeit werden virtuelle Funktionen zur Bearbeitung einer Reihe von Zeichen in den Bereichen get und put aufgerufen. Die virtuellen Funktionen holen weitere Zeichen von einem "Zeichenlieferanten" oder übergeben eine Zeichenfolge an einen "Endverbraucher" von Zeichen. Im allgemeinen benötigt der Benutzer von streambuf hierfür kein Detailwissen, einige der public-Elemente geben aber Informationen zum Status der Bereiche zurück. Weitere Informationen zu diesen Bereichen finden Sie im Abschnitt zu sbufprot, wo die geschützte Schnittstelle beschrieben wird. Die public-Elementfunktionen der Klasse streambuf werden im folgenden beschrieben. Dabei wird angenommen, dass
public-Elementfunktionenint i=sb→in_avail() Die Anzahl der Zeichen, die im Bereich get sofort zur Entnahme bereitstehen, wird geliefert. Es können garantiert i Zeichen entnommen werden, ohne daß ein Fehler auftritt. int i=sb→out_waiting() Die Anzahl der Zeichen im Bereich put, die noch nicht (durch einen Endverbraucher)aufgebraucht wurde, wird geliefert. int c=sb→sbumpc() Der Zeiger get wird um ein Zeichen vorwärts verschoben; das auf diese Weise übersprungene Zeichen wird geliefert. Wenn sich der Zeiger am Ende der Zeichenfolge befindet, wird der Wert EOF geliefert. int c=sb→sgetc() Das Zeichen hinter dem Zeiger get wird geliefert. Der Zeiger get wird hierbei nicht verschoben! Wenn kein Zeichen verfügbar ist, wird EOF geliefert. streambuf* sb1=sb->setbuf(char * ptr, int len, int i) Es werden len Bytes, beginnend bei ptr, als Reservierungsbereich angeboten. Falls ptr NULL oder len kleiner oder gleich 0 ist, wird der Status ohne Pufferung angefordert. Ob der angebotene Bereich eingesetzt oder einer Anforderung des ungepufferten Status nachgegeben wird, hängt von den Details in der abgeleiteten Klasse ab. setbuf() liefert üblicherweise sb; falls das Angebot aber nicht angenommen oder die Anforderung abgelehnt wird, wird der Wert 0 geliefert. int i=sb->sgetn(char * ptr, int n) Es werden n Zeichen hinter dem Zeiger get entnommen und in den Bereich kopiert,der bei ptr beginnt. Wenn weniger als n Zeichen vor dem Ende der Zeichenfolge verbleiben, entnimmt sgetn() alle verbleibenden Zeichen. Die Funktion sgetn() repositioniert den Zeiger get hinter die entnommenen Zeichen und liefert die Anzahl der entnommenen Zeichen. int c=sb→snextc() Der Zeiger get wird um ein Zeichen vorwärts verschoben; das auf die neue Position folgende Zeichen wird geliefert. Wenn sich der Zeiger - vor oder nach der Verschiebung - am Ende der Zeichenfolge befindet, wird EOF geliefert. int i=sb->sputbackc(int c) Der Zeiger get wird um ein Zeichen zurückgesetzt. c muss das aktuelle Zeichen sein,das sich direkt vor dem Zeiger befindet. Der zugrunde liegende Mechanismus kann einfach den Zeiger get zurücksetzen oder die internen Datenstrukturen so verändern, dass c gespeichert wird. Die Auswirkung der Funktion sputbackc() ist folglich nicht definiert, wenn c nicht das vor dem Zeiger get befindliche Zeichen ist. Die Funktion sputbackc() liefert bei erfolgloser Ausführung EOF. Die Bedingungen, unter denen ein Aufruf erfolglos ist, hängen von Details der abgeleiteten Klasse ab. int i=sb->sputc(int c) c wird hinter dem Zeiger put gespeichert und der Zeiger hinter das gespeicherte Zeichen verschoben. Üblicherweise führt dies zu einer Verlängerung der Zeichenfolge.Im Fehlerfall wird EOF geliefert. Die Bedingungen, unter denen Fehler auftreten, sind von der abgeleiteten Klasse abhängig. int i=sb->sputn(const char * ptr, int n) Hinter dem Zeiger put werden die n Zeichen, die bei ptr beginnend abgelegt sind,gespeichert; der Zeiger put wird hinter die Zeichenfolge positioniert. Die Funktion sputn() liefert i, die Anzahl der erfolgreich gespeicherten Zeichen. Im Normalfall ist i mit n identisch; i kann beim Auftreten eines Fehlers aber auch niedriger als n sein. void sb →stossc() Der Zeiger get wird um ein Zeichen nach vorn verschoben. Falls sich der Zeiger beim Funktionsaufruf am Ende der Zeichenfolge befindet, hat der Funktionsaufruf keine Auswirkung. streampos pos=sb->seekoff(streamoff off, ios::seek_dir dir, int mode) Die Zeiger get und/oder put (die abstrakten get- und put-Zeiger und nicht pptr() und gptr()) werden neu positioniert. mode gibt dabei an, ob der Zeiger put (das Bit ios::out ist gesetzt) oder get (das Bit ios::in ist gesetzt) modifiziert werden soll. Eskönnen beide Bits gesetzt sein; in diesem Fall sollten auch beide Zeiger angesprochen werden. off wird als Byte-Offset interpretiert (beachten Sie, dass es sich hierbei um einen vorzeichenbehafteten Wert handelt). Die Bedeutung der Werte, die dir annehmen kann,sind ios::beg Der Beginn des Datenstroms. ios::cur Die aktuelle Position. ios::end Das Ende des Datenstroms (Ende der Datei). Nicht alle aus streambuf abgeleiteten Klassen unterstützen die Repositionierung. Die Funktion seekoff() liefert den Wert EOF, falls das Repositionieren von der Klasse nicht unterstützt wird. Unterstützt die Klasse das Repositionieren, liefert seekoff() die neue Position oder - im Fehlerfall - EOF. streampos pos=sb->seekpos(streampos pos, int mode) Die streambuf-Zeiger get und/oder put werden auf pos gesetzt. mode spezifiziert, welche Zeiger - wie bei seekoff() - verändert werden. Es wird pos (das Argument) oder - wenn die Klasse keine Repositionierung unterstützt oder ein Fehler auftritt - EOF geliefert. Auf eine Variable des Typs streampos sollte im allgemeinen keine arithmetische Operation angewendet werden. Zwei Werte besitzen aber eine besondere Bedeutung: streampos(0) Stellt den Beginn der Datei dar. streampos(EOF) Wird als Hinweis auf einen Fehler genutzt. int i=sb→sync() Die internen Datenstrukturen werden mit der externen Quelle oder dem externen Ziel synchronisiert. Die Details dieser Funktion hängen von der abgeleiteten Klasse ab.Die Funktion sync() wird aufgerufen, damit die abgeleitete Klasse die Statusangaben der Bereiche einsehen und diese mit der externen Repräsentation synchronisieren kann. Üblicherweise sollte sync() alle im Bereich put gespeicherten Zeichen verbrauchen und - wenn möglich - die Zeichen im Bereich get, die noch nicht entnommen wurden, an die Quelle zurückgeben. Nach der Rückkehr von sync() sollten keine weiteren, nicht verbrauchten Zeichen vorliegen, und der Bereich get sollte leer sein. sync() sollte den Wert EOF liefern, wenn ein Fehler aufgetreten ist. sync() "leert" also alle gespeicherten Zeichen, die noch nicht verbraucht wurden, und es werden alle Zeichen zurückgegeben, die zwar erzeugt, aber noch nicht entnommen wurden. | |||||||||||
BEISPIEL | Im folgenden Programm wird eine Variable vom Typ filebuf definiert, die mit cin verknüpft ist. Aus diesem filebuf-Objekt werden Zeichen blockweise eingelesen, bis das Dateiende erreicht ist. Daraufhin wird die Anzahl der tatsächlich eingelesenen Zeichen ermittelt, wobei jedes Zeilenende-Zeichen ’\n’ ein Zeichen darstellt: #include <iostream.h> #include <fstream.h> int main() { filebuf in_file(0); /* in_file ist mit cin verknüpft */ const int N = 10; int k; char text_b[N+1]; /* Textpuffer */ cout << "Bitte " << N << " Zeichen eingeben :\n"; cout.flush(); k = in_file.sgetn(&text_b[0],N); cout << "Es wurden " << (k+in_file.in_avail()) ; cout << " Zeichen eingegeben.\n"; /* jedes \n ist auch ein Zeichen. */ return 0; } Das Ergebnis der Programmausführung ist: Bitte 10 Zeichen eingeben : 0123456789 Es wurden 11 Zeichen eingegeben. % CCM0998 Verbrauchte CPU-Zeit: 0.0040 Sekunden Der Benutzer kann die Puffergröße durch den Aufruf der Elementfunktion setbuf() ändern. Durch einen Aufruf von setbuf() kann jede Puffergröße gesetzt werden. | ||||||||||
BESONDERHEITEN | |||||||||||
setbuf gehört nicht im eigentlichen Sinne zur öffentlichen Schnittstelle und wurde nur aus Kompatibilitätsgründen im stream-Paket aufgenommen. | |||||||||||
SIEHE AUCH | |||||||||||