Download presentation
Presentation is loading. Please wait.
1
מערכים של מצביעים הקצאה דינאמית
תרגול 11 מערכים של מצביעים הקצאה דינאמית
2
מערך של מצביעים כמו שניתן להגדיר מערך לכל טיפוס בשפת C, ניתן להגדיר גם מערך של מצביעים לדוגמא: אם נרצה לכתוב ברצף 4 משפטים קיימות בפנינו מספר אפשרויות (לפי מה שראינו עד כה): החזקת פוינטר נפרד לכל משפט char *s1 = “HELLO”; char *s2 = “How are you?”; char *s3 = “I am the longest line here!!!”; char *s4 = “THE END”; המשפטים לא יהיו ברצף!
3
מערך של מצביעים - המשך מערך דו מימדי של תווים:
במערך תהינה 10 שורות, וכמה עמודות ? כמספר התווים במשפט הארוך ביותר \0 O L E H ? u o y e r a w ! h n i l t s g m I D N T פתרון סביר אך בזבזני במקום (בהנחה שיש משפטים הרבה יותר קצרים מהמשפט הארוך ביותר!)
4
מערך של מצביעים - המשך הפתרון: מערך של מצביעים
מערך של 4 משפטים ייראה כך: char* message[] = { “HELLO!”, “How are you?”, “I am the longest line here!!”, “THE END”} “HELLO” “How are you?” “I am the longest line here!!” “THE END”
5
מערך של מצביעים - המשך תוכנית לדוגמא
תוכנית המקבלת מערך של שמות (שם פרטי+שם משפחה) ויוצרת ממנו מערך של שמות המשפחה בלבד. חישבו מה הייתם משנים אם הייתם צריכים לקרוא את השמות מהמשתמש לתוך המערך names?
6
הקצאת זיכרון דינאמית לעיתים קרובות אנחנו לא נוכל להניח הנחות מראש על גודל הזיכרון הדרוש לנו, לדוגמא- גודל מערך. עד כה הגבלנו גודל זה והגדרנו מערכים בגודל קבוע, אך הגבלה שכזאת אינה נוחה (כיוון שאינה מאפשרת גמישות בתוכנית) ומובילה לבזבוז זיכרון. לדוגמא, אם נרצה לקלוט מהמשתמש מספר כלשהו של נתונים, נוכל להניח שלא יהיו יותר מ-20 נתונים, אך אז נגביל את המשתמש (אם רצה לכתוב 32 נתונים,לדוגמא), או לחילופין- נבזבז זיכרון (אם יכתוב בסך הכל 2 נתונים).
7
הקצאת זיכרון דינאמית - המשך
לשם כך קיימות פונקציות להקצאה דינאמית של זיכרון, בזמן ריצה. כדי להשתמש בפונקציות אלו יש לכלול את הקובץ: stdlib.h
8
הקצאת זיכרון דינאמית - המשך
פונקציה להקצאת זיכרון: void* malloc(unsigned size) הפונקציה malloc( ), מקצה רצף של size בתים ,ומחזירה מצביע לכתובת הבית הראשון, או NULL אם ההקצאה לא הצליחה. המצביע שהפונקציה מחזירה הוא מטיפוס void*, כלומר מצביע מטיפוס לא ידוע, ולכן צריך לבצע המרה של המצביע לטיפוס הרצוי.
9
הקצאת זיכרון דינאמית - המשך
חשוב לזכור : לאחר כל הקצאת זיכרון צריך לבדוק שההקצאה הצליחה. לא תמיד הקצאות זיכרון מצליחות, מכיוון שזה תלוי במקום הרצוף הפנוי שמערכת ההפעלה יכולה לתת לנו- אם מערכת ההפעלה לא תוכל להקצות את המקום הנחוץ, ואנו ננסה להשתמש בו זו תהיה גישה לכתובת לא חוקית והתוכנית "תעוף" בזמן ריצה כדי לבדוק אם ההקצאה הצליחה בודקים אם המצביע שונה מ-NULL
10
הקצאת זיכרון דינאמית - המשך
חשוב לזכור : לאחר כל הקצאת זיכרון צריך לבדוק שההקצאה הצליחה. לא תמיד הקצאות זיכרון מצליחות, מכיוון שזה תלוי במקום הרצוף הפנוי שמערכת ההפעלה יכולה לתת לנו- אם מערכת ההפעלה לא תוכל להקצות את המקום הנחוץ, ואנו ננסה להשתמש בו זו תהיה גישה לכתובת לא חוקית והתוכנית "תעוף" בזמן ריצה כדי לבדוק אם ההקצאה הצליחה בודקים אם המצביע שונה מ-NULL
11
הקצאת זיכרון דינאמית - המשך
נניח שרוצים להקצות מערך של 50 מספרים שלמים: int *p; p = malloc(50*sizeof(int)); (int*) המרה מ(void*) מספר בתים
12
הקצאת זיכרון דינאמית - המשך
נניח שרוצים להקצות מערך של 50 מספרים שלמים: int *p; if ( p = (int*)malloc(50*sizeof(int)) == NULL) { printf(“Allocation failed\n”); return 1; /* exit(1) */ }
13
הקצאת זיכרון דינאמית - המשך
אחרי שמקצים זכרון צריך לשחרר אותו void free(void* ptr) הפונקציה free מקבלת מצביע לכתובת בזכרון ומשחררת את הזכרון שהוקצה מכתובת זו. למשל: free(p);
14
דוגמא – הקצאת מערך חד מימדי בפונקציה
#include <stdio.h> #include <stdlib.h> #define INPUT 0 #define MEMORY 1 int get_array_size(void); /* get the array size from the user */ void create_array(int**, int) /* create the array */ void read_array(int* , int); /* read numbers into the array */ void print_array(int* , int); /* print the array */ void error(int); /* print an error message */
15
דוגמא – הקצאת מערך חד מימדי
int main( ) { int *arr, size; size = get_array_size( ); create_array(&arr,size); read_array(arr,size); print_array(arr,size); free (arr); return 0; }
16
דוגמא – הקצאת מערך חד מימדי
void create_array(int** a, int size) { if((*a = (int*)malloc(size*sizeof(int))) == NULL) error(MEMORY); return; }
17
דוגמא – הקצאת מערך חד מימדי
void print_array (int a[],int size) { int i; printf(“\nThe array is : \n”); for (i=0;i<size-1;i++) printf(“%d ,”,a[i]); printf(“%d\n”,a[size-1]); return; } void error (int type) switch(type) { case INPUT: printf("Input error!!!! "); break; case MEMORY: printf("memory allocation failed"); exit (1); int get_array_size( ) { int size; printf("\nHow many numbers do you want to write ? \n"); if (scanf("%d",&size)!=1) error(INPUT); return size; } void read_array(int a[], int size) int i; for (i=0 ; i<size ; i++) if (scanf("%d",&a[i])<1) return;
18
הקצאה דינאמית של מערך דו מימדי
הקצאה כמערך חד-מימדי – כמו שראיתם בהרצאה הקצאה כמערך של מערכים
19
הקצאה דינאמית של מערך דו מימדי
ייצוג מערך דו-מימדי כמערך של מערכים: Matrix : מערכים המייצגים כל אחד שורה מערך של מצביעים – כל מצביע מצביע לשורה המתאימה
20
הקצאה דינאמית של מערך דו מימדי
כדי להקצות דינאמית מערך דו-מימדי (למשל של מס' שלמים) כמערך של מערכים צריך: להקצות מערך חד מימדי של מצביעים (המערך המאונך בציור) להקצות מערך חד-מימדי עבור כל שורה, כך שעל כל שורה יצביע המצביע המתאים מהמערך שהקצנו בסעיף 1. וזה הקוד שעושה זאת: למערך של המצביעים נקרא matrix, והוא יהיה מסוג int** (מצביע למצביע למס' שלם) ונניח כי במשתנים row ו-col יש לנו את מימדי המטריצה אותה אנו רוצים להקצות. int row,col,i; int** matrix; … matrix = (int**)malloc(row*sizeof(int*)); if(matrix==NULL) { printf(“Allocation failed\n”); return 1; } for(i=0;i<row;i++) matrix[i] = (int*)malloc(col*sizeof(int)); if(matrix[i]==NULL)
21
הקצאה דינאמית של מערך דו מימדי בפונקציה
אם נרצה לעשות את ההקצאה בפונקציה נפרדת, זה אומר שאנחנו צריכים להציב ערך במשתנה matrix לא באותה פונקציה בה הוא מוגדר, אלא בפונקציה שונה. הצבת ערך בתוך משתנה שהוגדק בפונקציה אחרת יכולה להתבצע בשתי דרכים (בדיוק כמו שלמדנו כשהתחלנו לדבר על מצביעים): בעזרת מצביע לאותו משתנה (ושליחת הכתובת שלו לפונקציה) להחזיר את הערך שרוצים להציב כערך מוחזר מהפונקציה בעזרת מצביע: המשתנה שבו אנחנו רוצים להציב ערך בפונקציה הוא matrix (הערך שאנו רוצים להציב הוא הכתובת ש-malloc מחזיר לנו). מאחר ו-matrix הוא מטיפוס int** אז מצביע אליו יהיה מטיפוס int*** והפונקציה תיראה כך: void mymalloc( int*** m, int row, int col) { int i; (*m) = (int**)malloc(row*sizeof(int*)); for(i=0;i<row;i++) (*m)[i] = (int*)malloc(col*sizeof(int)); return; } הקריאה לפונקציה תהיה: mymalloc(&matrix,row,col); וכמובן להוסיף בדיקות שההקצאה הצליחה
22
הקצאה דינאמית של מערך דו מימדי בפונקציה
בעזרת ערך מוחזר: הפונקציה תיראה כך: int** mymalloc(int row, int col) { int**m; int i; m = (int**)malloc(row*sizeof(int*)); for(i=0;i<row;i++) m[i] = (int*)malloc(col*sizeof(int)); return m; } הקריאה לפונקציה תהיה: matrix = mymalloc(row,col); [זה יעבוד בגלל שהזיכרון שקיבלנו מ-malloc נשאר עד סוף התוכנית. צריך לזכור לשחרר אותו כשלא צריך אותו יותר.]
23
הקצאה דינאמית של מערך דו מימדי בפונקציה
לאחר הקצאה כמערך של מערכים השימוש במערך הדו-מימדי יהיה בדיוק באותו אופן בו השתמשנו כשהמערך הוגדר סטטית. כלומר: matrix[i][j]
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.