سؤال

لدي وظيفة C التي تكتب بعض البيانات إلى ملف نصي. تتكون البيانات من العوامات ، ints والسلاسل. يبدو شيئًا كهذا:

writeAsTextFile(  mystruct_t* myStructWithIntsFloatsAndStrings , const char* fileName);

للقيام بذلك ، أستخدم المكالمات إلى FPRINTF ؛

الآن أود أن أكتب نفس البيانات ولكن ثنائي. يمكنني كتابة وظيفة ثانية لكتابة واستخدام المكالمات للكتاب بدلاً من ذلك. ولكن في كل مرة سأقوم بتغيير تصميم MyStruct_T ، سأضطر إلى تعديل كل من WriteAstextFile و Writeassbinaryfile. وبالطبع فإن ReadastExtFile المقابلة و ReadAsbinaryFile. علاوة على هذا سيزيد هذا الرموز. لذلك أود الحصول على وظيفة عامة واحدة مع وسيطة واحدة أو نص واحد والتي ستبدو هكذا:

writeToFile( mystruct_t* myStructWithIntsFloatsAndStrings , const char* fileName, myEnumType_t eOption)

حيث سيكون الخيار عبارة عن eBin = 0 و etxt = 1 على سبيل المثال. اعتمادًا على eoption ، ستقوم الوظيفة بكتابة بيانات ثنائية أو نصية.

لست متأكدًا مما قد يكون أفضل طريقة لتحقيق ذلك. هل يجب أن أستخدم Fwrite أيضًا للكتابة كنص ، هل يجب أن أحاول استخدام وحدات الماكرو؟ (لقد رأيت استخدام التوجيه ## في مكان ما ولكن لم أستخدمه أبدًا) ، أو عبارات التبديل/ifs في كل مكان أحتاج إلى الكتابة إلى ملف؟ أو يجب أن أكتب وظيفة عامة مثلmyWriteFunction( void *data, char const type, myEnumType_t eOption)

التي سيتم استدعاؤها بواسطة WriteTofile؟

أنا لست على دراية باستخدام Fread/Fwrite و Macros ، لذا فإن أي تعليقات أفضل الممارسات والأفكار وما إلى ذلك هي موضع ترحيب ،

شكرًا

بابا

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

المحلول

يمكنك إنشاء بضع وظائف لكتابة أنواع مختلفة من البيانات في struct:

writeInt(File *f, myEnumType_t eOption, int data);
writeFloat(File *f, myEnumType_t eOption, float data);
writeFloatArray(File *f, myEnumType_t eOption, float *data, size_t n_data);

.. ثم يتم إخفاء اختبار الثنائي أو النص في كل من هؤلاء. ستبدو وظيفة كتابة الهيكل الرئيسية الخاصة بك (مع حذف الخطأ):

writeToFile(mystruct_t *myStruct, const char *fileName, myEnumType_t eOption)
{
    const char *fmode = eOption == EOPT_BIN ? "wb" : "w";
    FILE *f = fopen(filename, fmode);

    writeInt(f, eOption, myStruct->a);
    writeInt(f, eOption, myStruct->b);
    writeFloatArray(f, eOption, myStruct->values, myStruct->n_values);
    /* ... */
 }

لذا فإن التغيير في تخطيط الهيكل يجب أن يغير مكانًا واحدًا فقط.

يمكنك أيضًا تنفيذ وظائف الكتابة المختلفة لمختلف "أنواع" مستوى التطبيق - على سبيل المثال writeTemperature() قد تكون متميزة عن عام writeFloat().

نصائح أخرى

لموقفك ، ببساطة جعل وظيفة التفاف:

writeToFile(...,bool isBinary) {
  if (isBinary) {
    // write as binary file
  } else {
    // write as text file
  }
}

بقدر ما تذهب وحدات الماكرو ، فهي مفيدة فقط إذا كنت تريد أن تكون جميع العمليات إما ثنائية أو نص:

#ifdef __BINARY
#define WriteToFile(a,b,c,d,e) WriteToBinary(a,b,c,d,e)
#else
#define WriteToFile(a,b,c,d,e) WriteToText(a,b,c,d,e)
#endif

يستخدم هذا في WinAPI للتبديل بين وظائف ASCII ووظائف الأحرف الواسعة.

راجع للشغل: إذا كان بنيتك يحتوي على char* أو std :: string ، فلن يتم نسخ محتويات السلسلة ، فقط عنوانه. ينطبق هذا على أي مؤشرات أخرى أيضًا ، مثل int* أو std :: vector.

أولاً ، لا تجمع بين الوظائف ، لا يوجد مدخرات عملية.

ثانياً ، سيتعين عليك كتابة كتابة جديدة كوظيفة نصية في كل مرة تستخدم فيها الهيكل ، لا توجد طريقة للتغلب عليها (باستثناء بعض مكتبة التسلسل غير القياسية).

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

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

تعديل

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

إذا كنت ترغب في الحفاظ على العلاقات بين الهياكل ، فسيتعين عليك الخروج بآليتك الخاصة. هذا يختلف في الصعوبة ، وسيتعين عليك التوصل إلى ترتيب محدد مسبقًا لكتابة الهياكل في ، وإعادة بناء جميع المؤشرات عند قراءة البنية.

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