Programmieren mit C++

Code-Beispiele & Lösungen

Klassen für allgemeine Aufgaben

Ringpuffer

Ein Ringpuffer stellt eine endlose Liste von Einträgen dar, wobei am oberen Ende neue Einträge hinzugefügt und am unteren Ende Einträge entfernt werden. Zeitlich gesehen ist der erste Eintrag im Puffer der jüngste, der letzte der älteste.

Diese Art von Ringpuffer wird auch als FIFO (First in – First out) bezeichnet, weil immer garantiert ist, daß die Elemente in der Reihenfolge ausgelesen werden, in der sie zuvor eingetragen wurde.

Ein Ringpuffer kann nie überlaufen. Wenn mehr Elemente eingetragen als ausgelesen werden, gehen die ältesten Einträge verloren.

Typische Anwendungen sind das Zwischenpuffern von Daten, die mit unterschiedlichen Geschwindigkeiten ein- und ausgelesen werden.

In Multiprozeßanwendungen werden Ringpuffer zur Übergabe von Daten zwischen den einzelnen Prozessen eingesetzt.

Beim gepufferten Schreiben in Files kann der Ringpuffer zum Zwischenspeichern von Schreib- oder Leseanforderungen eingesetzt werden.

Die Klasse RingBuffer ist als Template definiert, so daß sie jede Art von Datenstrukturen oder Klassen aufnehmen kann. Die Template-Definition hält sich an die Standarddefinition, so daß sie von allen C++Compilern übersetzt werden kann.

Anwendung

Eine Instanz eines Ringpuffers kann wie folgt erzeugt werden:

RingBuffer  IntBuffer (500);

Beim Einsatz von Klassen sollte der Zuweisungsoperator definiert werden.

Beispiel

class Auftrag {
private:
  int AuftragsNummer;
  Daten *AuftragsDaten;
public:
  Auftrag ();
  ~Auftrag ();
  operator= (const Auftrag &daten);
};
RingBuffer  AuftragBuffer (100);

Beim Erzeugen dieses Ringpuffers werden für alle 100 Einträge jeweils die Konstruktoren aufgerufen.

Bei Eintrag neuer Elemente wird der klasseneigene Zuweisungsoperator benutzt.

Die maximale Puffergröße hängt vom jeweils eingesetzten Speichermodell und von der Größe der Datenstruktur ab.

Zuweisungs-operator

Bei Datentypen, die Pointer enthalten, muß beachtet werden, daß der Standard-Zuweisungsoperator nur den Speicherbereich kopiert, d. h. bei einem Pointer wird nur dessen Inhalt kopiert, nicht aber der Inhalt, auf den er zeigt. Um dies zu umgehen, sollten diese Klassen einen eigenen Zuweisungsoperator definieren, der alle Elemente ordnungsgemäß zuweist.

Standard-Zuwei-sungsoperator

Die Klasse besitzt neben den Pufferindizes für das Ein- und Auslesen einen weiteren Index, der innerhalb des Puffers frei positioniert werden kann. Damit kann der Puffer nach bestimmten Einträgen abgesucht werden, ohne die Reihenfolge der Einträge zu verändern.

Leseindex

RingBuffer  (const int Size = 0);

Mit diesem Konstruktor wird eine neue Instanz erzeugt und initialisiert.

Der Speicherraum für den Puffer wird mit new auf dem Heap angelegt. Wenn der Datentyp einen eigenen new-Operator definiert hat, wird dieser für das Anlegen des Speichers eingesetzt.

Der Parameter Size legt die maximale Anzahl der Elemente im Puffer fest. Beim Anlegen des Puffers wird für jedes Element dessen Defaultkonstruktor aufgerufen

Wenn der Konstruktor ohne Parameter aufgerufen wird, erhält der Puffer die Größe 0. In diesem Fall wird kein Speicher auf dem Heap angelegt.

Durch eine spätere Zuweisung kann die Puffergröße nachträglich verändert werden.

Default-Konstruktor

RingBuffer  (const RingBuffer &origbuf);

Der Kopierkonstruktor erzeugt eine neue Instanz und übernimmt alle Elemente des übergebenen Puffers.

Das Kopieren der Elemente erfolgt mit dem Zuweisungsoperator des Datentyps. Je nach Größe des Puffers und der Datenstruktur kann dies erhebliche Laufzeit verursachen.

Kopier-Konstruktor

~RingBuffer ();

Der angelegte Speicher auf dem Heap wird mit delete freigegeben. Wenn der Datentyp einen eigenen delete-Operator definiert hat, wird dieser auch benutzt. Dabei werden auch alle Destruktoren der Elemente aufgerufen.

Destruktor

void Reset ();

Reset erledigt das Initialisieren des Puffers. Dabei werden der Puffer geleert und alle Indizes zurückgesetzt.

Memberfunktion Reset

Type &Insert (const Type &Element);

Über Insert erfolgt das Einfügen eines neuen Elements.

Die Daten werden in die erste freie Position kopiert und die Anzahl der gültigen Einträge erhöht.

Die Funktion liefert die Referenz auf den neuen Eintrag zurück. Wenn der Puffer voll war, wird der älteste Eintrag überschrieben.

Memberfunktion Insert

Type &Getout ();

Getout wird verwendet, um den ältesten Eintrag aus dem Puffer auszulesen.

Falls der Puffer mindestens einen gültigen Eintrag enthielt, wird die Anzahl der gültigen Elemente um eins verkleinert, ansonsten ist der Rückgabewert undefiniert.

Die Anzahl der gültigen Einträge kann mit der Funktion GetCount ermittelt werden. Nach dem Auslesen wird der Index auf den letzten Eintrag um eins weiterbewegt.

Memberfunktion Getout

int  GetCount ();

GetCount ermittelt die Anzahl der gültigen Pufferelemente. Wenn der Puffer leer ist, wird 0 zurückgegeben.

Memberfunktion GetCount

Type &GetFirst ();

Das Auslesen des ersten gültigen Eintrags im Puffer erfolgt über GetFirst. Gleichzeitig wird dabei der interne Leseindex auf dieses Element gesetzt.

Mit den Funktionen GetNext und GetPrev kann man sich nun innerhalb des Puffer vorwärts und rückwärts bewegen.

Memberfunktion GetFirst

Type &GetLast ();

GetLast liefert eine Referenz auf den letzten gültigen Puffereintrag. Der interne Leseindex wird gleichzeitig auf das älteste Element gesetzt.

Über die zurückgegebene Referenz kann der Eintrag verändert werden. Die Position des Eintrags innerhalb des Puffers wird aber nicht verändert.

Memberfunktion GetLast

Type &GetNext ();

Der interne Leseindex wird um eins erhöht und eine Referenz auf das Element zurückgegeben, auf das er dann zeigt.

Durch Setzen des Leseindex mit GetLast kann man so den ganzen Puffer von Anfang bis Ende durchsuchen, ohne daß sich die Ein- und Auslesereihenfolge verändert.

Memberfunktion GetNext

Type &GetPrev ();

Der interne Leseindex wird auf den vorhergehenden Eintrag gesetzt und eine Referenz darauf zurückgegeben.

Memberfunktion GetPrev





Sachgebiet


© 2009-2012 by Alojado Publishing. Alle Rechte vorbehalten. Ausgewiesene Marken gehören ihren jeweiligen Eigentümern.
Mit der Benutzung dieser Seite erkennen Sie die Nutzungsbedingungen und die Datenschutzerklärung an. Der Betreiber übernimmt keine Haftung für den Inhalt verlinkter externer Internetseiten.
Seite erzeugt 2012-05-20 03:05:18 von textarchiv.alojado.de