Pregunta

I tienen una estructura de datos definida como

struct myDataStruct
{
   int32_t header;
   int16_t data[8];
}

y yo quiero tomar un flujo de caracteres y convertirla en una corriente myData. ¿Qué clase de secuencia debería extender? Me gustaría crear una clase de secuencia personalizado, de modo que pueda hacer cosas como

myDataStruct myData;
myDataStruct myDataArray[10];

myDataStream(ifstream("mydatafile.dat"));
myDataStream.get(myData);
myDataStream.read(myDataArray, 10);
¿Fue útil?

Solución

En lugar de myDataStream.get(myData), lo que haces es operator>> sobrecarga para su tipo de datos:

std::istream& operator>>(std::istream& is, myDataStruct& obj)
{
  // read from is into obj
  return is;
}

Si desea leer en una matriz, acaba de escribir un bucle:

for( std::size_t idx=0; idx<10; ++idx ) 
{
   myDataStruct tmp;
   if( is >> tmp )
     myDataArray[idx] = tmp;
   else
     throw "input stream broken!";
}

El uso de una plantilla de función, también debe poder sobrecargar el operador para las matrices en el lado derecho (pero esto nunca he intentado):

template< std::size_t N >
std::istream& operator>>(std::istream& is, myDataStruct (&myDataArray)[N])
{
  // use loop as above, using N instead of the 10
}

Pero no puedo decidir si este es precioso o despreciable.

Otros consejos

Si está trabajando con una entrada sin formato, probablemente debería leer directamente en forma binaria. Por lo general, se usaría alguna directiva específica del compilador para crear estructuras de datos sin relleno y luego sólo de lectura / escritura de un archivo.

// 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
}

La directiva del compilador para desactivar el relleno para VS puede ser diferente (creo que la directiva pragma funciona tanto en gcc y VS, pero siempre he utilizado el atributo).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top