Generischer Ansatz für ostream& operator<<(...) m

Alles rund um die Programmierung mit Qt
Antworten
nasahl
Beiträge: 33
Registriert: 24. Juli 2008 12:30

Generischer Ansatz für ostream& operator<<(...) m

Beitrag von nasahl »

Hallo,

ich möchte einen generischen Ausgabeoperator auf ostream für all QT-Klassen implementieren, die intern ein "QDataStream & operator<< ( QDataStream & stream, ... )" haben.

Das würde ungefähr so aussehen:

Code: Alles auswählen

template<class QTCLASS>
ostream& operator<<(ostream& oss, const QTCLASS& obj)
{
    QDataStream str;
    str << obj;
    std::string s = convert2StringButIDontKnowHow( str );
    oss << s;
    return oss;
}
Hat jemand eine Idee wie das gehen könnte? Ich kenn mich mit QT nicht so gut aus.


Danke schon mal, Christof
scn
Beiträge: 4
Registriert: 14. September 2004 10:26
Wohnort: Isernhagen (Region Hannover)

Beitrag von scn »

Hallo Christof,

QDataStream serialisiert binäre Daten auf ein Device. Anstelle einer Datei verwendest du ein QByteArray. Die Daten kannst du dann mit constData() als const char * auslesen.

Also, um dein Beispiel aufzugreifen, könnte es dann so aussehen:

Code: Alles auswählen

template<class QTCLASS>
ostream& operator<<(ostream& oss, const QTCLASS& obj)
{
    QByteArray data;
    QDataStream str(&data, QIODevice::ReadWrite);
    str << obj;
    oss << data.constData();
    return oss;
}
Gruß Thomas
nasahl
Beiträge: 33
Registriert: 24. Juli 2008 12:30

Beitrag von nasahl »

Vielen Dank für die konkrete Antwort.

Was ich aber nicht verstehe, ist, dass der folgende Code:

Code: Alles auswählen

template<class QTCLASS>
std::string convert2String( const QTCLASS& obj )
{
    QByteArray data;
    QDataStream str(&data, QIODevice::ReadWrite);
    str << obj;
    return std::string( data.constData() );
} 
...
    QRect r(1, 2, 3, 4);
    std::cout << "r: " << convert2String(r) << std::endl;

eine leere Ausgabe für r produziert.

Was ist daran falsch ?

Christof
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

nasahl hat geschrieben: Was ist daran falsch ?
scn hat geschrieben: QDataStream serialisiert binäre Daten auf ein Device
Genau das.
Wie kommst Du darauf das die Binärdaten als string irgend etwas vernünftiges anzeigen?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
nasahl
Beiträge: 33
Registriert: 24. Juli 2008 12:30

Beitrag von nasahl »

Mein Beitrag 2 ist nur eine Umsetzung der Idee von Beitrag 1. Vielleicht kann man das Problem so nicht lösen. Wie macht man es aber dann?

Christof
scn
Beiträge: 4
Registriert: 14. September 2004 10:26
Wohnort: Isernhagen (Region Hannover)

Beitrag von scn »

OK. Vielleicht war ich mit constData() auch zu schnell. Binäre Daten können natürlich auch NULL-Bytes enthalten. Werden diese Daten als const char * interpretiert und in einen std::string umgewandelt ist natürlich beim ersten '\0' die Zeichenkette zu Ende.
Deshalb wahrscheinlich die leere Ausgabe.
Bei der Wandlung des QByteArray in einen QString bleiben NULL-Bytes erhalten. Also versuch mal

Code: Alles auswählen

template<class QTCLASS>
std::string convert2String( const QTCLASS& obj )
{ 
    QByteArray data;
    QDataStream str(&data, QIODevice::ReadWrite);
    str << obj;
    return QString(data).toStdString();
}
Gruß Thomas
RHBaum
Beiträge: 1436
Registriert: 17. Juni 2005 09:58

Beitrag von RHBaum »

Aehm, nur kurz ne Frage ...

warum ein QByteArray übern den umweg via (Q)string serialisieren ???
und warum der Umweg ueber QDataStream?
A data stream is a binary stream of encoded information which is 100% independent of the host computer's operating system, CPU or byte order. For example, a data stream that is written by a PC under Windows can be read by a Sun SPARC running Solaris.
Ist deine Order im QByteArry denn eigentlich genau spezifiziert ?
Ist auch genau spezifiziert, wie die Ausrichtung deiner Nutzdaten im "bytefeld" eigentlich ist ?
Normal ist das bei Motorola und Intel nicht gleich.
Ein Feld von Ints z.b. was nen mac geschrieben hat, musst "ziemlich aufwendig" nach intel konvertieren (sawtooth methode).

Wenn das ned beruecksichtigs, kriegst sowieso probleme beim serialisieren ....

wenn Motorola / intel keine bedeutung fuer dich hat, brauchst den Umweg ueber QDataStream ned ....

wenn es doch fest definiert ist, ist dein bytearray selber schon plattformunabhaengig, und Du brauchst QDataStream ned dazu ...

Das ist wohl auch der grund, warum es keinen fertigen operator fuer QDatastream und QByteArry scho gibt.

Also pump deine daten lieber per write() direkt ins QIODevice rein.

Felder von ints, oder andere dinge soltest du nicht ueber QByteArray direkt serialisieren, wenn Prozesseurunabhaengigkeit eine rolle spielt, sondern du solltest die Daten nach ihren folgen vorher aufloesen, also wenn 25 ints speichern willst, dann 25 in den datastream, und dann alle 25 werte hinterher. nur das garantiert dir die unabhaengigkeit.
Speicherbereiche aus unterschiedlichen daten (Structs, Arrays) sind nicht prozessorunabhaengig !!!

Ciao ....
AuE
Beiträge: 918
Registriert: 5. August 2008 10:58

Beitrag von AuE »

Bei Lade- und Speichervorgängen in Registern und Speichern gibt es zwei Anordnungssysteme in dem die Bytes eingelesen werden: Das Little-Endian-Format und das Big-Endian-Format.



Big- und Little-Endian-Formate



Im Gegensatz zu Big Endian ist Little Endian ein Format für die Übertragung oder Speicherung binärer Daten, in denen das Least Significant Byte (LSB) an erster Stelle kommt und auf der niedrigsten Speicheradresse gespeichert wird. So wird das Byte E3 von der hexadezimalen Zahl 6FE3 im Little-Endian-Format auf dem Speicherplatz mit der niedrigsten Adresse gespeichert.

Nach diesem Prinzip arbeiten u. a. Intel, die VAX von DEC, DEC-Alpha und MIPS-Chips.
Antworten