سؤال

لدي بنية بيانات محددة على أنها

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

وأريد أن آخذ دفق حرف وتحويله إلى تيار MyData. ما فئة الدفق التي يجب أن أقدمها؟ أرغب في إنشاء فئة دفق مخصصة حتى أتمكن من فعل أشياء مثل

myDataStruct myData;
myDataStruct myDataArray[10];

myDataStream(ifstream("mydatafile.dat"));
myDataStream.get(myData);
myDataStream.read(myDataArray, 10);
هل كانت مفيدة؟

المحلول

بدلاً من myDataStream.get(myData), ما تفعله هو الحمل الزائد operator>> لنوع البيانات الخاص بك:

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

إذا كنت ترغب في القراءة في صفيف ، فما عليك سوى كتابة حلقة:

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

باستخدام قالب الوظيفة ، يجب أن تتمكن أيضًا من زيادة تحميل المشغل للصفائف على الجانب الأيمن (لكن هذا لم أجربه أبدًا):

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

لكن لا يمكنني أن أقرر ما إذا كان هذا رائعًا أو بائسًا.

نصائح أخرى

إذا كنت تعمل مع مدخلات غير مفيدة ، فيجب عليك القراءة مباشرةً في شكل ثنائي. عادةً ما يمكنك استخدام بعض التوجيهات الخاصة بالمترجم لإنشاء هياكل بيانات بدون حشوة ثم فقط قراءة/الكتابة من ملف.

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

قد يكون توجيه التحويل البرمجي لتعطيل الحشو لـ VS مختلفًا (أعتقد أن توجيهات Pragma تعمل على حد سواء في GCC و VS ، لكنني دائمًا ما استخدمت السمة).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top