× מי אנחנו? התוכנית הראשונה משתנים קלט ופלט אופרטורים חשבוניים משפטי בקרה לולאות לולאות דו ממדיות casting sizeof typedef פונקציות רקורסיות מצביעים מצביע כפול מערכים מערכים דינאמיים מערכים דו ממדים מחרוזות חיפוש בינארי מיון בועות מיון בחירה מיון הכנסה מיון מהיר מיון מיזוג

Let's learn C

מערכים דינאמיים

למה אנו צריכים מערכים דינאמיים ?

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

הבעיה שלנו עם מערך סטטי הוא שאנו יכולים לבזבז מקום או שאנו יכולים להקצות מעט מדי מקום ואז אנו לא יכולים להכיל יותר מידע , לשם כך יש לנו את המערכים הדינאמיים.

יצירת מערך דינאמי

השימוש של מערך דינאמי מתאפשר בעזרת שימוש במצביעים ומוצהר כך:
;type *name

כדי שניצור מערך דינאמי אנו צריכים מצביע ועליו נפעיל את אחת מהפקודות של הקצאת זיכרון דינאמי:
malloc או calloc

malloc & calloc

פקודות אלו שייכות לספריות בשם: stdlib.h ו malloc.h ואנו משתמשים בהם כך:

הסבר:

  1. (*type) – אומר מאיזה סוג אנו ניצור את המערך הדינאמי שלנו.
  2. amount – מציין את כמות התאים שאנו רוצים במערך.
  3. sizeof(type) - מציין את הגודל של סוג המערך (הכוונה שאם אנו רוצים ליצור מערך דינאמי מסוג int אז אנו נרשום sizeof(int)).
בעזרת sizeof ו amount המחשב יודע כמה מקום בבתים הוא צריך להקצות למערך שלנו בזיכרון.

ההבדל בין malloc ל calloc

במילים אחרות ניתן לומר כי כאשר אנו יוצרים מערך דינאמי עם calloc אנחנו בעצם יוצרים את מערך עם malloc ואז עוברים על כל המערך בלולאה ומאפסים את כל התאים, ולכן ניתן לומר כי malloc יותר יעיל מ calloc.


ההבדל בין מערך דינאמי ללא דינאמי

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


שליחת מערך דינאמי לפונקציה

שליחת מערך דינאמי לפונקציה זהה לשליחת מערך רגיל. שליחת מערך רגיל:
;name_of_function(array , amount)

לעומת זאת חותמת הפונקציה במערך דינאמי בפונקציה תהיה שונה משל מערך רגיל:


הכוונה לכך היא כדי שנוכל לבצע שינויים בכתובת זיכרון של מערך בתוך פונקציה עלינו ליצור חותמת פונקציה שמקבלת שני כוכביות (שעליו עשינו נושא בנפרד מצביע כפול).
כאשר אנו רושמים בmain שלנו את הקוד אנו נשלח כתובת של המערך שלנו כלומר:
&arr

חשוב לציין!

()free

לפני שאנו קופצים לדוגמאות חשוב לזכור שזיכרון דינאמי לא משוחרר באופן אוטומטי מהזיכרון, ולכן זה התפקיד שלנו כמתכנתים לשחרר אותו.
נעשה זאת בכך שבכל פונקציה שאנחנו מגדירים מערך דינאמי אנו נדאג לכך שבסוף התוכנית זיכרון זה ישוחרר.
נשחרר את המערך כך:
;free(the_name_of_the_array)
אנו ברגע שפקודה זו מתבצעת היא משחררת מהזיכרון את כל המערך (אי אפשר לשחרר רק חלק מסויים).
אם ננסה לשחרר פעמיים את אותו הזיכרון תקפוץ לנו הודעת שגיאה.

()assert

אחרי שאנו עושים calloc, malloc או realloc אנו נשתמש בפונקציה בשם assert שתפקידה הוא להודיע לנו אם המחשב הצליח להגדיר בזיכרון את המערך עם הגודל המבוקש.
נשתמש בפונקציה זו בכך שאחרי שנשתמש ב calloc, malloc או realloc נרשום:
;assert(the_name_of_the_array)

כדי להשתמש ב assert נצטרך להוסיף בתחילת הקוד:
#include <assert.h>

דוגמה ליצירת מערך בגודל שהמשתמש רוצה:

CODE WITH CALLOC:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void main()
{
  int *dynamic_array, amount;
  printf("please enter the size you want for the array:");
  //for visual studio 2017 or above use scanf_s
  scanf("%d", &amount); //lets assume that we entered the number 4
  dynamic_array = (int*)calloc(amount , sizeof(int));
  assert(dynamic_array); //succeeded
  //the array that we created is: [0,0,0,0]
  free(dynamic_array);
}
CODE WITH MALLOC:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void main()
{
  int *dynamic_array, amount;
  printf("please enter the size you want for the array:");
  //for visual studio 2017 or above use scanf_s
  scanf("%d", &amount);//lets assume that we entered the number 4
  dynamic_array = (int*)malloc(amount * sizeof(int));
  assert(dynamic_array); //succeeded
  //the array that we created is: [-8421,50451,-32131,94321]
  free(dynamic_array);
}

שינוי הקצאה של מערך דינאמי בעזרת realloc

פונקציית realloc מאפשרת לנו להגדיל או להקטין את גודל המערך.
שימוש בפקודה זו יתבצע כך:
;array_name = (type*)realloc(array_name ,sizeof(type)*amount)

  1. array_name – מציין את המערך אותו אנו רוצים להקטין או להגדיל.
  2. sizeof(type) -במידה ואינכם לגמרי מבינים את הנושא עדיין כדאי לחזור לנושא sizeof.
  3. amount - הגודל החדש של המערך.
בעזרת sizeof ו amount אנו מציינים את הגודל החדש של המערך בבתים.

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

CODE WITH REALLOC:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
void enterValues(int **arr, int amount);
void main()
{
  int *dynamic_array, amount;
  printf("please enter the size you want for the array:");
  //for visual studio 2017 or above use scanf_s
  scanf("%d", &amount);//lets assume that we entered the number 5
  dynamic_array = (int*)malloc(amount * sizeof(int));
  assert(dynamic_array); //succeeded
  enterValues(dynamic_array,amount);
  //the array before the realloc is: [1,2,3,4,5]
  dynamic_array =(int*)realloc(dynamic_array,sizeof(int)*3);
  assert(dynamic_array); //succeeded
  //the array after the realloc is: [1,2,3]
  free(dynamic_array);
}
void enterValues(int**arr,int amount)
{ 
  //the values that entered are: 1,2,3,4,5
  int i;
  for (i = 0; i < amount; i++)
  {
    printf("please enter number:\n");
    //for visual studio 2017 or above use scanf_s
    scanf("%d",&arr[i]);
  }
}