سؤال

هل هناك أي نهج قياسي فاتني في المدرسة لتفريغ ج هيكل مع قوائم متداخلة مرتبطة على القرص بطريقة معقولة؟ ما لا أريد فعله هو:

  • استخدم قائص البروتوكول أو أي شخص آخر مثل المسلسلات ،
  • لا تريد إنشاء JSON أو XML أو غيرها

لدي القليل من الأفكار:

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

لتصوير هذا ، سأعطي المزيد من التفاصيل رمز النشر:

typedef struct{
   int b;
   List *next;
}List;

typedef struct{
   float b;
   List2 *next;
}List2;

typedef struct{
   List *head;
   List *tail;
} info;

typedef struct{
   List2 *head;
   List2 *tail;
} info2;

struct data
{
    int a;
    char t[10];
    info first;
    info second;
    info2 third;
};

هتافات P.

تعديل:

لقد مددت الهيكل الرئيسي ، يبدو أن السابق لم يشير إلى المشكلة بالكامل. أنا أدرك أن المؤشرات على القرص عديمة الفائدة. الأفكار والرمز الكاذب المسموح به.

هل كانت مفيدة؟

المحلول

قم بتسلسل البيانات بالترتيب الذي يتم الاحتفاظ به في القائمة المرتبطة ، على غرار السجل في ملف. fwrite هو جيد بشكل خاص لهذا. تأكد من أن المؤشرات dereference ، وكن على دراية بالدور الذي يلعبه Endianness في هذا.

إليك بعض الرمز الكاذب الغامض:

List *list_new();
List *list_add(List *, void *data);
List *list_next(List *);

while (node) {
    fwrite(node->data, sizeof(node->data), 1, fp);
    node = list_next(node);
}

رمز خشن للقراءة مرة أخرى في قائمة مباشرة:

List *node = list_new();
while (true) {
    struct data *buf = malloc(sizeof(*buf));
    if (1 != fread(buf, sizeof(*buf), 1, fp))
        break;
    list_add(node, buf);
}

update0

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

على سبيل المثال ، إذا كانت قائمة المرتبطة بمستوى الأعلى تحتوي على عضو في البيانات التي كانت قائمة أخرى ، فمن الأفضل أن تخزن هذا العضو كسجل متداخل ، مع حقل الطول ، ونوع. بدلاً من ذلك ، يمكنك تحديد سجلات Sentinel ، مثل \0 بالنسبة لسلاسل الأحرف (خيار واضح) ، وكتل صفر لبيانات الهيكل.

نصائح أخرى

لم أفهم مشكلتك بشكل صحيح ، لكنني ألقيت بنية على القرص وقراءته مرة أخرى بشكل موثوق به مشاكل متعددة.

أهم واحد هو حشوة الهيكل أو حشو البايت. لذلك يجب أن تعتني بذلك أيضًا.

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

struct rwBufferData{
    int a;
    char t[10];
};

وملء "rwbufferdata" قبل الكتابة باستخدام memset و memmove

struct rwBufferData rwBuf;
struct data *dataPtr;
memset(&rwBuf, '\0', sizeof(struct rwBufferData));
memmove(&rwBuf, dataPtr, sizeof(struct rwBufferData));

الآن يمكنك الكتابة بعد ذلك rwBuf لملف ... سأترك العملية العكسية كتمرين ...

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