W
Hier ist es meines Erachtens sinnvoll, das Problem in zwei Teile zu zerlegen.
1.) es muss eine Möglichkeit geschaffen werden, über alle Elemente des Puffers zu laufen
2.) der eigentliche Algorithmus reverse zum Vertauchen der Reihenfolge der Elemente im Puffer
Zu 1.) eignet sich ein Iterator - etwa so was:
struct PufferIterator
{
Puffer* m_puffer;
int m_idx;
};
Ein Objekt dieser Struktur zeigt auf genau ein Element in einem Puffer - also in diesem Fall auf m_puffer->D[m_idx].
Zum Traversieren muss man diesen Iterator hoch- und runterzählen können. Ich mache jetzt mal in dem Stil weiter, wie Du den Puffer aufgebaut hast. Dann ergeben sich zwei Funktionen zum inkrementieren (inc: hochzählen) und Dekrementieren (dec: runterzählen).
PufferIterator& inc( PufferIterator& pi )
{
if( ++pi.m_idx >= MAX )
pi.m_idx = 0;
return pi;
}
PufferIterator& dec( PufferIterator& pi )
{
if( pi.m_idx-- == 0 )
pi.m_idx = MAX-1;
return pi;
}
Für den Zugriff auf das aktuelle Element und für den Vergleich zweier Iteratoren - wird im Algorithmus benötigt - braucht man noch einen !=-Operator und das Dereferenzieren (deref) - also den Zugriff auf das aktuelle Element.
bool operator!=( const PufferIterator& a, const PufferIterator& b )
{
return a.m_idx != b.m_idx || a.m_puffer != b.m_puffer;
}
char& deref( const PufferIterator& pi )
{
return pi.m_puffer->D[ pi.m_idx ];
}
Das hat bisher zunächst gar nichts mit dem gesuchten Algorithmus zu tun; erleichtert aber dessen Erstellung ganz enorm.
Wegen der besseren Übersichtlichkeit im Code verpasst man dem Iterator noch einen Konstruktor. Dann ändert sich die struct PufferIterator zu:
struct PufferIterator
{
PufferIterator( Puffer& P, int idx )
: m_puffer( &P )
, m_idx( idx )
{}
Puffer* m_puffer;
int m_idx;
};
Bevor ich jetzt zu reverse komme, zunächst ein Beispiel, wie der Iterator angewendet wird:
#include <iostream>
// Puffer & PufferIterator (s.o.)
int main()
{
using namespace std;
Puffer buf;
leere( buf ); // notwendig, da Default-Konstruktor fehlt
// -- ein wenig Puffer-Aktion
for( char c = 'a'; c != 'e'; ++c )
lege( buf, c );
while( !istLeer( buf ) )
entnimm( buf );
for( char c = '1'; c != '9'; ++c )
lege( buf, c );
// -- Puffer ausgeben
for( PufferIterator i( buf, buf.Anfang ); i != PufferIterator( buf, buf.Ende ); inc( i ) )
cout << deref( i );
cout << endl;
return 0;
}
Man sieht jetzt, dass in der Schleife keine Rücksicht mehr darauf genommen werden muss, dass der interne Index 'm_idx' beim Inkrementieren am Ende des Arrays D[] wieder auf 0 gesetzt werden muss. Dies ist in den Funktionen inc bzw. dec versteckt.
Der Iterator ist zwar nicht Standard-konform , aber trotzdem ein echter Iterator.
Zu 2.): Der Algorithmus reverse beginnt von beiden Seiten - also Anfang und Ende - und tauscht einfach die Elemente aus, bis die beiden Iteratoren sich in der Mitte treffen.
void reverse( PufferIterator von, PufferIterator bis )
{
for( ; von != bis && von != dec( bis ); inc( von ) )
{
// swap( *von, *bis );
char tmp = deref( von );
deref( von ) = deref( bis );
deref( bis ) = tmp;
}
}
Der Aufruf ist Dank des Konstruktors von PufferIterator ganz einfach (vor Zeile 18 im main() einfügen):
// -- Reihenfolge im Puffer 'buf' umdrehen
reverse( PufferIterator( buf, buf.Anfang ), PufferIterator( buf, buf.Ende ) );
Das, was Du programmierst hast, ist übrigens keine Liste sondern eine Queue bzw. Pipe. Das leere heißt clear(), istLeer ist empty(), lege heißt push() bzw. push_back() und entnimm heißt pop() bzw. pop_front() bzw. der Zugriff auf das erste Element heißt top() bzw. front().
Noch ein Tipp: mache die Konstante MAX zu einer statischen Variablen in der Klasse Puffer.
Gruß
Werner