benutzerdefinierte Daten Iostream
-
20-09-2019 - |
Frage
Ich habe eine Datenstruktur definiert als
struct myDataStruct
{
int32_t header;
int16_t data[8];
}
und ich mag einen Zeichenstrom nehmen und es in einen myData Strom verwandeln. Was Stream-Klasse soll ich verlängern? Ich möchte eine benutzerdefinierte Stream-Klasse erstellen, so dass ich die Dinge tun kann wie
myDataStruct myData;
myDataStruct myDataArray[10];
myDataStream(ifstream("mydatafile.dat"));
myDataStream.get(myData);
myDataStream.read(myDataArray, 10);
Lösung
Statt myDataStream.get(myData)
, was Sie tun, ist Überlastung operator>>
für Ihren Datentyp:
std::istream& operator>>(std::istream& is, myDataStruct& obj)
{
// read from is into obj
return is;
}
Wenn Sie in ein Array lesen möchten, schreiben Sie einfach eine Schleife:
for( std::size_t idx=0; idx<10; ++idx )
{
myDataStruct tmp;
if( is >> tmp )
myDataArray[idx] = tmp;
else
throw "input stream broken!";
}
eine Funktionsvorlage verwenden, sollten Sie auch in der Lage den Operator für Arrays auf der rechten Seite zu überlasten (aber das habe ich noch nie versucht):
template< std::size_t N >
std::istream& operator>>(std::istream& is, myDataStruct (&myDataArray)[N])
{
// use loop as above, using N instead of the 10
}
Aber ich kann nicht entscheiden, ob dieses wunderschöne oder verabscheuungswürdig ist.
Andere Tipps
Wenn Sie mit unformatierter Eingabe arbeiten, sollen Sie wahrscheinlich direkt in binärer Form lesen. Normalerweise würden Sie einige Compiler spezielle Richtlinie verwenden, um Datenstrukturen ohne Polsterung zu erstellen und dann nur lesen / schreiben aus einer Datei.
// Gcc
#pragma pack(1) // option 1: pragmas
struct frame {
std::uint32_t header;
std::uint16_t data[8];
} __attribute((packed)); // option 2: packed attribute
#pragma pack(0)
bool operator==( data const & lhs, data const & rhs )
{
bool result = lhs.header == rhs.header;
for ( int i = 0; i < 8; ++i )
{
result &= lhs.data[i] == rhs.data[i];
}
return result;
}
int main()
{
frame data = { 10, 1, 2, 3, 4, 5, 6, 7, 8 };
std::ofstream out( "data.bin", ofstream::binary );
out.write( reinterpret_cast<char*>(&data), sizeof(data) );
out.close();
std::ifstream in( "data.bin", ifstream::binary );
frame readed;
in.read( reinterpret_cast<char*>(&readed), sizeof(readed) );
in.close();
std::cout << (readed == data) << std::endl; // 1
}
Die Compiler-Direktive zu deaktivieren Polsterung für VS anders sein könnte (ich glaube, die Pragma-Direktive funktioniert sowohl in gcc und VS, aber ich habe immer das Attribut verwendet wird).