سؤال

لدي صورة قرص تحتوي على صورة قياسية باستخدام الصمامات. يحتوي SuperBlock على ما يلي، ولدي وظيفة READ_SUPERBLOCK (* BUF) التي ترجع البيانات الأولية التالية:

Bytes 0-3: Magic Number (0xC0000112)
      4-7: Block Size (1024)
     8-11: Total file system size (in blocks)
    12-15: FAT length (in blocks)
    16-19: Root Directory (block number)
  20-1023: NOT USED

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

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

char *buf;
read_superblock(*buf);
printf("%s", buf);
هل كانت مفيدة؟

المحلول

نعم، أعتقد أنك ستكون أفضل حالا في قراءة هذا في هيكل. الحقول التي تحتوي على بيانات مفيدة هي أعداد صحيحة 32 بت، حتى تتمكن من تحديد هيكل يشبه هذا (باستخدام الأنواع المعرفة في ملف الرأس القياسي stdint.h):

typedef struct SuperBlock_Struct {
  uint32_t magic_number;
  uint32_t block_size;
  uint32_t fs_size;
  uint32_t fat_length;
  uint32_t root_dir;
} SuperBlock_t;

يمكنك أن يلقي الهيكل ل char* عند الاتصال read_superblock, ، مثله:

SuperBlock_t sb;
read_superblock((char*) &sb);

الآن لطباعة بياناتك، يمكنك إجراء مكالمة مثل ما يلي:

printf("%d %d %d %d\n",
  sb.magic_number,
  sb.block_size,
  sb.fs_size,
  sb.fat_length,
  sb.root_dir);

لاحظ أنك بحاجة إلى أن تكون على دراية بإنزام منصة الخاص بك عند استخدام تقنية مثل هذا، لأنك تقرأ بيانات عدد صحيح (أي، قد تحتاج إلى تبديل بايت عند قراءة بياناتك). يجب أن تكون قادرا على تحديد ذلك بسرعة باستخدام الرقم السحري في الحقل الأول.

لاحظ أنه عادة ما يكون من الأفضل اجتياز بنية مثل هذا دون إلقاء ذلك؛ يتيح لك ذلك الاستفادة من فحص نوع المحول البرمجي وتزيل المشكلات المحتملة التي قد تخفيها الصب. ومع ذلك، فإن ذلك سوف يستلزم تغيير تنفيذك read_superblock لقراءة البيانات مباشرة في هيكل. هذا ليس صعبا ويمكن القيام به باستخدام وظيفة وقت تشغيل C قياسي fread (على افتراض أن بياناتك موجودة في ملف، كما هو موضح في سؤالك)، مثل ذلك:

fread(&sb.magic_number, sizeof(sb.magic_number), 1, fp);
fread(&sb.block_size, sizeof(sb.block_size), 1, fp);
...

نصائح أخرى

شيئين لإضافته هنا:

  1. إنها فكرة جيدة، عند سحب البيانات الخام إلى بنية، لتعيين الهيكل للحصول على حشوة صفرية، حتى لو كانت مكونة تماما من أعداد صحيحة غير موقعة 32 بت. في دول مجلس التعاون الخليجي تفعل هذا مع #pragma pack(0) قبل تعريف الهيكل و #pragma pack() بعد ذلك.
  2. للتعامل مع قضايا الانتصاف المحتملة، دعا دعوة للنظر إليها ntohs() و ntohl(), ، لمدة 16 و 32 بت على التوالي. لاحظ أن هذه المبادلة من بايت الشبكة أمر لاستضافة أمر بايت؛ إذا كانت هذه هي نفسها (التي لا تكون في منصات X86 القائمة)، فهي لا يفعلون شيئا. أنت تذهب من المضيف إلى Network Byte Order مع htons() و htonl(). وبعد ومع ذلك، نظرا لأن هذه البيانات تأتي من نظام الملفات الخاص بك وليس الشبكة، لا أعرف ما إذا كانت النزاه مشكلة. يجب أن يكون من السهل معرفة ذلك بمقارنة القيم التي تتوقعها (مثل حجم الكتلة) بالقيم التي تحصل عليها، في عرافة.

ليس من الصعب طباعة البيانات بعد نسخ البيانات بنجاح في هيكل يقترح. لنفترض أن مثيل الهيكل الذي تستخدمه لعقد البيانات يسمى superblock_t_instance.

ثم يمكنك طباعة حقولها مثل هذا:

printf("Magic Number:\t%u\nBlock Size:\t%u\n etc", 
SuperBlock_t_Instance.magic_number, 
SuperBlock_t_Instance.block_size);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top