Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

التخصيص الديناميكي للهياكل

جزء من قسم Logic & Flow في رحلة C على Coddy — الدرس 48 من 63.

حتى الآن، تعلمت كيفية إنشاء الـ structs على الـ stack - فهي توجد ضمن النطاق (scope) الذي تم التصريح عنها فيه ويتم تنظيفها تلقائياً عند انتهاء ذلك النطاق. ولكن ماذا لو كنت بحاجة إلى بقاء الـ struct إلى ما بعد نطاقه الأصلي، أو عندما لا تعرف في وقت التجميع (compile time) عدد الـ structs التي ستحتاج إليها؟

هنا يأتي دور التخصيص الديناميكي. يمكنك استخدام malloc() لإنشاء هياكل (structs) في الذاكرة الكومة (heap)، تماماً كما تفعل مع أي نوع بيانات آخر. الفرق الجوهري هو أن الهياكل المخصصة ديناميكياً تبقى في الذاكرة حتى تقوم بتحريرها صراحةً باستخدام free().

إليك الصيغة البرمجية لتخصيص struct ديناميكيًا:

struct Point *ptr = malloc(sizeof(struct Point));

يقوم هذا بتخصيص ذاكرة كافية في الـ heap لاستيعاب هيكل Point واحد ويعيد مؤشراً إلى تلك الذاكرة. يمكنك بعد ذلك استخدام عامل السهم (arrow operator) للوصول إلى أعضاء الهيكل وتعديلها:

ptr->x = 10;
ptr->y = 20;

تذكر دائماً التحقق مما إذا كان malloc() قد نجح (أعاد قيمة non-NULL) واستدعاء free(ptr) عند الانتهاء من استخدام الـ struct لمنع تسرب الذاكرة. هذه التقنية ضرورية لبناء برامج مرنة يمكنها إنشاء وإدارة هياكل البيانات في وقت التشغيل (runtime).

challenge icon

التحدي

سهل

قم بإنشاء برنامج بلغة C يوضح التخصيص الديناميكي للهياكل (structs) باستخدام malloc(). يجب أن يقوم برنامجك بما يلي:

  1. تعريف struct باسم Car بالأعضاء التالية:
    • عدد صحيح year لتخزين سنة التصنيع
    • مصفوفة أحرف brand بحجم 20 لتخزين علامة السيارة التجارية
    • مصفوفة أحرف model بحجم 25 لتخزين طراز السيارة
    • رقم عشري price لتخزين سعر السيارة
    • عدد صحيح mileage لتخزين المسافة المقطوعة للسيارة
  2. في الدالة الرئيسية (main function)، قم بالتصريح عن مؤشر لهيكل Car باسم carPtr
  3. استخدم malloc() لتخصيص ذاكرة ديناميكيًا لهيكل Car واحد وتعيين العنوان المرتجع إلى carPtr
  4. تحقق مما إذا كان تخصيص الذاكرة ناجحًا:
    • إذا كان carPtr يساوي NULL، اطبع Memory allocation failed واخرج من البرنامج
    • إذا نجح التخصيص، اطبع Memory allocation successful
  5. اقرأ قيم الإدخال التالية وقم بتعيينها لأعضاء الهيكل باستخدام عامل السهم (arrow operator):
    • اقرأ عددًا صحيحًا للسنة وقم بتعيينه باستخدام carPtr->year
    • اقرأ سلسلة نصية للعلامة التجارية وقم بتعيينها باستخدام carPtr->brand
    • اقرأ سلسلة نصية للطراز وقم بتعيينها باستخدام carPtr->model
    • اقرأ رقمًا عشريًا للسعر وقم بتعيينه باستخدام carPtr->price
    • اقرأ عددًا صحيحًا للمسافة المقطوعة وقم بتعيينه باستخدام carPtr->mileage
  6. بعد قراءة جميع القيم، قم بإجراء الحسابات التالية باستخدام عامل السهم:
    • احسب عمر السيارة بطرح السنة من 2024: int age = 2024 - carPtr->year;
    • احسب معدل الاستهلاك بناءً على العمر: إذا كان العمر أكبر من 10، اضبط الاستهلاك على 0.6، وإلا فاضبطه على 0.8
    • احسب القيمة الحالية: carPtr->price * depreciation
  7. اطبع معلومات السيارة باستخدام عامل السهم بهذا التنسيق الدقيق:
    • Car Information:
    • Year: [year]
    • Brand: [brand]
    • Model: [model]
    • Original Price: [price]
    • Mileage: [mileage]
    • Age: [age] years
    • Current Value: [current_value]
  8. قم بتحرير الذاكرة المخصصة ديناميكيًا باستخدام free(carPtr)
  9. اطبع Memory freed successfully

يختبر هذا التحدي فهمك للتخصيص الديناميكي للهياكل باستخدام malloc()، والتحقق من فشل التخصيص، والوصول إلى أعضاء الهيكل من خلال المؤشرات باستخدام عامل السهم، وتحرير الذاكرة المخصصة بشكل صحيح باستخدام free(). ستتدرب على دورة الحياة الكاملة لإدارة الذاكرة الديناميكية مع الهياكل.

ورقة مرجعية

استخدم malloc() لتخصيص الهياكل (structs) ديناميكيًا على الكومة (heap):

struct Point *ptr = malloc(sizeof(struct Point));

الوصول إلى أعضاء الهيكل (struct) من خلال المؤشرات باستخدام عامل السهم (arrow operator):

ptr->x = 10;
ptr->y = 20;

تحقق دائمًا مما إذا كان malloc() قد نجح وقم بتحرير الذاكرة عند الانتهاء:

if (ptr == NULL) {
    // معالجة فشل التخصيص
}
// استخدم الهيكل...
free(ptr);

جرّب بنفسك

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// TODO: هنا Car قم بتعريف هيكل

int main() {
    // TODO: carPtr باسم Car قم بالإعلان عن مؤشر لهيكل
    
    // TODO: لتخصيص ذاكرة لهيكل واحد malloc() استخدم
    
    // TODO: تحقق مما إذا كان تخصيص الذاكرة ناجحاً
    
    // قراءة قيم المدخلات
    int year, mileage;
    char brand[20], model[25];
    float price;
    
    scanf("%d", &year);
    scanf("%s", brand);
    scanf("%s", model);
    scanf("%f", &price);
    scanf("%d", &mileage);
    
    // TODO: قم بتعيين قيم المدخلات لأعضاء الهيكل باستخدام عامل السهم
    
    // TODO: احسب العمر، الاستهلاك، والقيمة الحالية
    
    // TODO: اطبع معلومات السيارة بالتنسيق المطلوب
    
    // TODO: قم بتحرير الذاكرة المخصصة واطبع رسالة نجاح
    
    return 0;
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Logic & Flow