C++ LCD stream Klasse

Gast #4107913
Lesenswert?
• ▲
▼
Hallo,

ich habe mir eine Klasse für ein Display geschrieben:
1
class Lcdbasestream: public streambuf, public ostream
2
{
3
  private:
4
    int overflow(int = EOF);
5
                int linelength;
6
  public:
7
     Lcdbasestream(int boardversion);
8
      ~Lcdbasestream(void);
9
      void Clear();
10
      virtual void Gotoxy(int x, int y) = 0;
11
    void setLight(bool state);
12
};
13

14
extern Lcdbasestream lcd;

So kann ich ganz bequem mit lcd << "Test" etwas auf mein Display 
schreiben. Drei Fragen:

1. Wie kann muss ich den Code erweitern, so dass ich die Clear Methode 
in der Art "cout << clr << i" aufrufen kann?
2. Gleiches wie oben für die Goto Methode, also mit Parametern, so dass 
ich etwa "lcd << goto(10, 2) << i" verwenden kann?
3. Wie kann ich mir einen Manipulator schreiben, der mir die nächste 
Ausgabe zentriert, also z.B. lcd << center << "Test"? Die Zeilenlänge 
liegt als Attribut in der LCD Klasse vor.

Grüße
Stefan
(Firma: Torrox.de) #4107956
Lesenswert?
• ▲
▼
Hallo Stefan,

0) Deine Klasse sollte nicht public von stream und buffer erben. Da 
das Verhalten von streams in der Regel über ihre buffer implementiert 
werden, würde ich einen buffer implementieren und dann für convenience 
einen stream, der einen buffer enthält und diesen als c'tor argument an 
den stream weiter reicht.

für 1-3) müsstest Du dann erkennen, ob der stream buffer eines streams 
deinem buffer typen entspricht. Hier würde ich dynamic_cast verwenden 
(wenn bei Dir verfügbar) (ansonsten wären xalloc()/iword und static_cast 
Dein Freund).

1) Manipulatoren, die keine zusätzlichen Argumente nehmen (z.B. endl) 
sind Funktionen, die einen ostream als argument nehmen und einen ostream 
zurück geben:
1
std::ostream& clr( std::ostream& out ) {
2
    lcd_buffer* const buf = dynamic_cast< lcd_buffer* >( out.rdbuf() );
3

4
    if ( buf )
5
        buf->Clear();
6

7
    return out;
8
}

2) Manipulatoren, die Argumente nehmen lassen sich gut als Typen mit 
Konstruktoren implementieren:
1
struct goto
2
{
3
    goto( int ax, int ay )
4
        : x( ax )
5
        , y( ay )
6
    {}
7

8
    int x, y;
9
};
10

11
std::ostream& operator<<( std::ostream& out, const goto& target )
12
{
13
    lcd_buffer* const buf = dynamic_cast< lcd_buffer* >( out.rdbuf() );
14

15
    if ( buf )
16
        buf->goto_xy( target.x, target.y );
17

18
    return out;    
19
}

3) Da müsstest Du dir merken, dass die nächste Zeile zentriert werden 
soll (siehe 1) und dann jedes Zeichen, dass im stream buffer vorbei 
kommt zwischen speichern und darauf untersuchen, ob es ein Zeilenumbruch 
ist. Das kann man aber auch optimieren, wenn man eine ganze Kette an 
Zeichen bekommt, kann man natürlich diese komplett untersuchen.

HTH
Torsten
Gast #4108142
Lesenswert?
• ▲
▼
>Da kommt gleich der dicke Fisch mit "ASM ist besser" um die Ecke.
Yo Danke für den Hinweis, habe schon gesehen dass dieses Thema hier im 
Forum etwas "nötiger als nötig" diskutiert wird, deswegen werde ich hier 
nicht schreiben für welche Plattform das ganze ist :-)

Danke Torsten, auch für den Tip 0. Einen dynamic_cast habe ich nicht, 
aber ich habe es mit einem static_cast gemacht. Gibt letzterer auch 0 
zurück wenn ein casten nicht möglich ist?

Stefan
(Firma: Torrox.de) #4108155
Lesenswert?
• ▲
▼
Stefan schrieb:

> Danke Torsten, auch für den Tip 0. Einen dynamic_cast habe ich nicht,
> aber ich habe es mit einem static_cast gemacht. Gibt letzterer auch 0
> zurück wenn ein casten nicht möglich ist?

Nein, der liefert dann nur "undefined behaviour", das wird nicht 
funktionieren, es sei den Du kannst sicherstellen, dass jeder Stream 
(inkl. string streams etc.) nur lcd_buffer enthält. Ansonsten brauchst 
zwingend eine Möglichkeit, zur Laufzeit zu unterscheiden, ob es ein 
lcd_buffer ist. Dazu fallen mir zwei Möglichkeiten ein:

1) Jeder stream enthält ein array. Mit std::ios_base::xalloc() kannst Du 
Dir einen slot/index in jedes array aller streams reservieren ...

2) zweite Möglichkeit wäre, in den Konstruktoren und Destruktor des 
lcd_buffer eine intrinsisch, verkettet Liste (jeder lcd_buffer enthält 
noch mal zusätzlich einen Zeiger auf den nächsten) zu führen, über die 
Du nachschlagen kannst, ob es ein stream buffer ein lcd_buffer ist oder 
nicht.

oder
3) Du verzichtest auf die std-streams, orientierst Dich an deren Syntax 
und baust das ganze parallel selbst auf.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.