سؤال

أريد تخزين السلاسل في ملف ثنائي، إلى جانب الكثير من البيانات الأخرى، أنا باستخدام الرمز أدناه (عندما استخدمه حقيقي، ستكون السلاسل Malloc'd) يمكنني الكتابة إلى الملف. نظرت إليها في محرر عرافة. أنا لست متأكدا من كتابة المنهي الفارغة بشكل صحيح (أو إذا كنت بحاجة إلى). عندما قرأت مرة أخرى أحصل على نفس طول السلسلة التي تخزينها، ولكن ليس السلسلة. ما الخطأ الذي افعله؟

FILE *fp = fopen("mybinfile.ttt", "wb");

char drumCString[6] = "Hello\0";
printf("%s\n", drumCString);    
//the string length + 1 for the null terminator
unsigned short sizeOfString = strlen(drumCString) + 1;
fwrite(&sizeOfString, sizeof(unsigned short), 1, fp);

//write the string
fwrite(drumCString, sizeof(char), sizeOfString, fp);

fclose(fp);

fp = fopen("mybinfile.ttt", "rb");  

unsigned short stringLength = 0;
fread(&stringLength, sizeof(unsigned short), 1, fp);

char *drumReadString = malloc(sizeof(char) * stringLength);
int count = fread(&drumReadString, sizeof(char), stringLength, fp);

//CRASH POINT
printf("%s\n", drumReadString);

fclose(fp); 
هل كانت مفيدة؟

المحلول

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

أزلت أنه يعمل بشكل جيد ويعود مرحبا بشكل صحيح.

int count = fread(drumReadString, sizeof(char), stringLength, fp);

نصائح أخرى

أرى بضعة قضايا، بعض إشكالية، بعض الأسلوبية.

  • يجب عليك حقا اختبار قيم الإرجاع من malloc, fread و fwrite نظرا لأنه من الممكن أن تفشل التخصيص، قد تتم قراءة أي بيانات أو كتابة بيانات.
  • sizeof(char) هو دائماً 1، ليست هناك حاجة لتضاعفها.
  • صفيف الشخصية "Hello\0" هو في الواقع 7 بايت طويلة. لا تحتاج إلى إضافة المنهي غير الضروري.
  • انا افضل المصطلح char x[] = "xxx"; بدلا من تحديد طول محدد (إلا إذا كنت تريد مجموعة أطول من السلسلة بالطبع).
  • عندما انت fread(&drumReadString ..., ، أنت في الواقع الكتابة فوق مؤشر, ، وليس الذاكرة التي يشير إليها. هذا هو سبب تحطمك. يجب أن يكون fread(drumReadString ....

بضع نصائح:

1

إنهاء \0 ضمنية في أي سلسلة اقتباس مزدوجة، وإضافة إضافية في النهاية، تنتهي بك الأمر مع اثنين. التهيدان التاليان متطابقان:

char str1[6] = "Hello\0";
char str2[6] = { 'H', 'e', 'l', 'l', 'o', '\0', '\0'};

لذا

char drumReadString[] = "Hello";

يكفي، وتحديد حجم الصفيف اختياري عند تهيئته مثل هذا، سيقوم المحول البرمجي بمعرفة الحجم المطلوب (6 بايت).

2

عند كتابة سلسلة، قد تكتب تماما أيضا، فقط كتابة جميع الأحرف في إحداها (بدلا من كتابة واحدة بواسطة أوقات SizeofString أحرف واحدة):

fwrite(drumCString, sizeOfString, 1, fp);

3

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

char *drumReadString = malloc(sizeof(char) * stringLength);
if (drumReadString == NULL) {
        fprintf(stderr, "drumReadString allocation failed\n");
        return;
}

أنت لا تكتب NUL إنهاء، فلن تحتاج إلى ذلك، لكن عليك أن تفكر في إضافة ذلك عند القراءة. أي malloc stringlength + 1 char، قراءة chars stringlength وإضافة \0 في نهاية ما تم قراءته.

الآن التحذير المعتاد: إذا كنت تكتب ملف ثنائي الطريقة التي تقوم بها بالطريقة التي تقوم بها هنا، فستكون لديك الكثير من الافتراضات غير المستحقة التي تجعل تنسيقك يصعب على المنفذ، في بعض الأحيان حتى إصدار آخر من نفس المحول البرمجي - لقد رأيت محاذاة افتراضية في تغييرات التغيرات بين إصدارات مترجم.

بعض أكثر لإضافة إلى Paxdiablo و Aproground - إذا كنت ستستخدم Malloc في المستقبل، فما عليك سوى القيام بذلك من الذهاب. إنه أفضل شكل ويعني أنك لن تضطر إلى تصحيح الأخطاء عند التبديل.

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

يمكنك فقط إزالة & drumreadstring الخاص بك في وظيفة FREAD.YOY ببساطة استخدام DrumReadString في هذه الوظيفة كما ذكرت Ganesh. Because، DrumReadString هو صفيف. يشبه هاي المؤشرات التي تشير إلى موقع الذاكرة مباشرة.

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