Domanda

Ho una struttura di dati definita come

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

e voglio prendere un flusso di caratteri e di trasformarlo in un flusso myData. Che classe di flusso dovrei prolungare? Vorrei creare una classe di flusso personalizzato in modo che io possa fare le cose come

myDataStruct myData;
myDataStruct myDataArray[10];

myDataStream(ifstream("mydatafile.dat"));
myDataStream.get(myData);
myDataStream.read(myDataArray, 10);
È stato utile?

Soluzione

Al posto di myDataStream.get(myData), quello che fai è sovraccarico operator>> per il tipo di dati:

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

Se si desidera leggere in un array, basta scrivere un ciclo:

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

Utilizzando un modello di funzione, si dovrebbe anche in grado di sovraccaricare l'operatore per gli array sul lato destro (ma questo non ho mai provato):

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

Ma io non riesco a decidere se questo è stupendo e spregevole.

Altri suggerimenti

Se si sta lavorando con l'input non formattato, probabilmente si dovrebbe leggere direttamente in forma binaria. Di solito si usa un po 'di direttiva specifica del compilatore per creare strutture di dati senza imbottitura e poi basta lettura / scrittura da un file.

// 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 direttiva del compilatore per disabilitare imbottitura per VS potrebbe essere diverso (credo che la direttiva pragma funziona sia in gcc e VS, ma ho sempre usato l'attributo).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top