Menu
Coddy logo textTech

הקצאה דינמית של מבנים

חלק מהיחידה לוגיקה וזרימת תוכנית במסלול ה-C של Coddy. שיעור 48 מתוך 63.

עד כה למדת איך ליצור מבנים במחסנית — הם קיימים בתחום שבו הם מוגדרים, ומתנקים אוטומטית כשהתחום הזה מסתיים. אבל מה אם צריך שמבנה ימשיך להתקיים מעבר לתחום המקורי שלו, או כשלא ידוע בזמן הקומפילציה כמה מבנים תצטרך?

כאן נכנסת לתמונה הקצאה דינמית. אפשר להשתמש ב־malloc() כדי ליצור מבנים בערימה, בדיוק כפי שהיית עושה עבור כל סוג נתונים אחר. ההבדל העיקרי הוא שמבנים שהוקצו באופן דינמי נשארים בזיכרון עד שמשחררים אותם במפורש באמצעות free().

הנה התחביר להקצאה דינמית של מבנה:

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

פעולה זו מקצה מספיק זיכרון בערימה כדי להכיל מבנה Point אחד ומחזירה מצביע לזיכרון הזה. לאחר מכן אפשר להשתמש באופרטור החץ כדי לגשת לחברי המבנה ולשנות אותם:

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

זכור תמיד לבדוק אם malloc() הצליחה (החזירה ערך שאינו NULL) ולקרוא ל-free(ptr) כשתסיים להשתמש במבנה, כדי למנוע דליפות זיכרון. הטכניקה הזו חיונית לבניית תוכניות גמישות שיכולות ליצור ולנהל מבני נתונים בזמן ריצה.

challenge icon

אתגר

קל

צרו תוכנית C שמדגימה הקצאה דינמית של מבנים באמצעות malloc(). התוכנית שלכם צריכה:

  1. להגדיר struct בשם Car עם השדות הבאים:
    • מספר שלם year לאחסון שנת הייצור
    • מערך תווים brand בגודל 20 לאחסון מותג המכונית
    • מערך תווים model בגודל 25 לאחסון דגם המכונית
    • מספר ממשי מסוג float בשם price לאחסון מחיר המכונית
    • מספר שלם mileage לאחסון הקילומטראז׳ של המכונית
  2. בפונקציה main, להכריז על מצביע למבנה Car בשם carPtr
  3. להשתמש ב-malloc() כדי להקצות באופן דינמי זיכרון למבנה Car אחד, ולהציב את הכתובת שהוחזרה בתוך carPtr
  4. לבדוק אם הקצאת הזיכרון הצליחה:
    • אם carPtr הוא NULL, להדפיס Memory allocation failed ולצאת מהתוכנית
    • אם ההקצאה הצליחה, להדפיס Memory allocation successful
  5. לקרוא את ערכי הקלט הבאים ולשייך אותם לשדות המבנה באמצעות אופרטור החץ:
    • לקרוא מספר שלם עבור השנה ולשייך אותו באמצעות carPtr->year
    • לקרוא מחרוזת עבור המותג ולשייך אותה באמצעות carPtr->brand
    • לקרוא מחרוזת עבור הדגם ולשייך אותה באמצעות carPtr->model
    • לקרוא מספר ממשי מסוג float עבור המחיר ולשייך אותו באמצעות carPtr->price
    • לקרוא מספר שלם עבור הקילומטראז׳ ולשייך אותו באמצעות carPtr->mileage
  6. לאחר קריאת כל הערכים, לבצע את החישובים הבאים באמצעות אופרטור החץ:
    • לחשב את גיל המכונית על ידי חיסור השנה מ-2024: int age = 2024 - carPtr->year;
    • לחשב את שיעור ירידת הערך לפי הגיל: אם הגיל גדול מ-10, להגדיר את depreciation כ-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(). תתרגלו את מחזור החיים המלא של ניהול זיכרון דינמי עם מבנים.

נסו בעצמכם

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

// TODO: להגדיר כאן את המבנה Car

int main() {
    // TODO: להצהיר על מצביע למבנה Car בשם carPtr
    
    // TODO: להשתמש ב-malloc() כדי להקצות זיכרון למבנה Car אחד
    
    // 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בחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה לוגיקה וזרימת תוכנית

תרגלו בעצמכם: קומפיילר C אונליין