Question

I ont une structure de données définie comme

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

et je veux prendre un flux de caractères et de le transformer en un flux myData. Quelle classe flux dois-je prolonger? Je voudrais créer une classe de flux personnalisé afin que je puisse faire des choses comme

myDataStruct myData;
myDataStruct myDataArray[10];

myDataStream(ifstream("mydatafile.dat"));
myDataStream.get(myData);
myDataStream.read(myDataArray, 10);
Était-ce utile?

La solution

Au lieu de myDataStream.get(myData), ce que vous faites est operator>> de surcharge pour votre type de données:

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

Si vous voulez lire dans un tableau, il suffit d'écrire une boucle:

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

En utilisant un modèle de fonction, vous devez également en mesure de surcharger l'opérateur pour les tableaux sur le côté droit (mais je n'ai jamais essayé):

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

Mais je ne peux pas décider si c'est magnifique ou méprisable.

Autres conseils

Si vous travaillez avec l'entrée non formaté, vous devriez probablement lire directement sous forme binaire. Habituellement, vous utilisez une directive spécifique du compilateur pour créer des structures de données sans rembourrage et puis juste lecture / écriture à partir d'un fichier.

// 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 directive du compilateur pour désactiver le rembourrage pour VS peut être différent (je crois que la directive pragma fonctionne aussi bien dans gcc et VS, mais je l'ai toujours utilisé l'attribut).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top