תרגול 11

23
ללללל11 םםםםםם םם םםםםםםם םםםםם םםםםםםם

Upload: amethyst-webster

Post on 31-Dec-2015

29 views

Category:

Documents


0 download

DESCRIPTION

תרגול 11. מערכים של מצביעים הקצאה דינאמית. מערך של מצביעים. כמו שניתן להגדיר מערך לכל טיפוס בשפת C , ניתן להגדיר גם מערך של מצביעים לדוגמא: אם נרצה לכתוב ברצף 4 משפטים קיימות בפנינו מספר אפשרויות (לפי מה שראינו עד כה): החזקת פוינטר נפרד לכל משפט char *s1 = “HELLO”; - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: תרגול 11

11תרגול

מערכים של מצביעים

הקצאה דינאמית

Page 2: תרגול 11

מערך של מצביעים

כמו שניתן להגדיר מערך לכל טיפוס בשפתC ,ניתן להגדיר גם מערך של מצביעים

:משפטים4 ברצףאם נרצה לכתוב לדוגמא קיימות בפנינו מספר אפשרויות )לפי מה שראינו

עד כה(:החזקת פוינטר נפרד לכל משפט1.

char *s1 = “HELLO”;

char *s2 = “How are you?”;

char *s3 = “I am the longest line here!!!”;

char *s4 = “THE END”; המשפטים לא יהיו

ברצף!

Page 3: תרגול 11

מערך של מצביעים - המשךמערך דו מימדי של תווים:2.

שורות, וכמה עמודות ? כמספר התווים 10במערך תהינה במשפט הארוך ביותר

פתרון סביר אך בזבזני במקום )בהנחה שיש משפטים הרבה יותר קצרים מהמשפט הארוך ביותר!(

HELLO\0

Howareyou?\0

Iamthelongestlinehere!!\0

THEEND\0

Page 4: תרגול 11

מערך של מצביעים - המשך

הפתרון: מערך של מצביעים משפטים ייראה כך:4 מערך של

char* message[] = {

“HELLO!”,

“How are you?”,

“I am the longest line here!!”,

“THE END”}

“HELLO”

“How are you?”

“THE END”

“I am the longest line here!!”

Page 5: תרגול 11

מערך של מצביעים - המשך

תוכנית לדוגמאתוכנית המקבלת מערך של שמות )שם פרטי+שם משפחה(

ויוצרת ממנו מערך של שמות המשפחה בלבד.

חישבו מה הייתם משנים אם הייתם צריכים לקרוא את השמות ?names לתוך המערך מהמשתמש

Page 6: תרגול 11

הקצאת זיכרון דינאמית

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

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

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

נתונים, אך אז 20נתונים, נוכל להניח שלא יהיו יותר מ- נתונים,32 את המשתמש )אם רצה לכתוב נגביל

זיכרון )אם יכתוב בסך הכל נבזבזלדוגמא(, או לחילופין- נתונים(. 2

Page 7: תרגול 11

הקצאת זיכרון דינאמית - המשך

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

:כדי להשתמש בפונקציות אלו יש לכלול את הקובץstdlib.h

Page 8: תרגול 11

הקצאת זיכרון דינאמית - המשך

:פונקציה להקצאת זיכרון

void* malloc(unsigned size)

הפונקציהmalloc) ( מקצה רצף של ,size ומחזירה בתים, אם ההקצאה לא NULLמצביע לכתובת הבית הראשון, או

הצליחה.

המצביע שהפונקציה מחזירה הוא מטיפוסvoid* כלומר מצביע ,צריך לבצע המרה של המצביע לטיפוס מטיפוס לא ידוע, ולכן

.הרצוי

Page 9: תרגול 11

הקצאת זיכרון דינאמית - המשך

חשוב לזכור : לאחר כל הקצאת זיכרון צריך לבדוק.שההקצאה הצליחה

לא תמיד הקצאות זיכרון מצליחות, מכיוון שזה תלויבמקום הרצוף הפנוי שמערכת ההפעלה יכולה לתת לנו-

אם מערכת ההפעלה לא תוכל להקצות את המקום הנחוץ, ואנו ננסה להשתמש בו זו תהיה גישה לכתובת לא

חוקית והתוכנית "תעוף" בזמן ריצה

כדי לבדוק אם ההקצאה הצליחה בודקים אםNULLהמצביע שונה מ-

Page 10: תרגול 11

הקצאת זיכרון דינאמית - המשך

חשוב לזכור : לאחר כל הקצאת זיכרון צריך לבדוק.שההקצאה הצליחה

לא תמיד הקצאות זיכרון מצליחות, מכיוון שזה תלויבמקום הרצוף הפנוי שמערכת ההפעלה יכולה לתת לנו-

אם מערכת ההפעלה לא תוכל להקצות את המקום הנחוץ, ואנו ננסה להשתמש בו זו תהיה גישה לכתובת לא

חוקית והתוכנית "תעוף" בזמן ריצה

כדי לבדוק אם ההקצאה הצליחה בודקים אםNULLהמצביע שונה מ-

Page 11: תרגול 11

הקצאת זיכרון דינאמית - המשך

מספרים שלמים:50נניח שרוצים להקצות מערך של int *p;

p = malloc)50*sizeof)int((; )int*(

*(void)המרה ממספר בתים

Page 12: תרגול 11

הקצאת זיכרון דינאמית - המשך

מספרים שלמים:50נניח שרוצים להקצות מערך של int *p;

if ) p = )int*(malloc)50*sizeof)int(( == NULL(

{

printf)“Allocation failed\n”(;

return 1; /* exit)1( */

}

Page 13: תרגול 11

הקצאת זיכרון דינאמית - המשך

לשחרר אותואחרי שמקצים זכרון צריך

void free(void* ptr)

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

;)free)pלמשל: •

Page 14: תרגול 11

דוגמא – הקצאת מערך חד מימדי בפונקציה

#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 */

Page 15: תרגול 11

דוגמא – הקצאת מערך חד מימדי

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;

}

Page 16: תרגול 11

דוגמא – הקצאת מערך חד מימדי

void create_array(int** a, int size)

{

if))*a = )int*(malloc)size*sizeof)int((( == NULL(

error)MEMORY(;

return;

}

Page 17: תרגול 11

דוגמא – הקצאת מערך חד מימדי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(

error)INPUT(;

return;

}

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"(; break;}exit )1(;return;

}

Page 18: תרגול 11

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

הקצאה כמערך חד-מימדי – כמו שראיתםבהרצאה

הקצאה כמערך של מערכים

Page 19: תרגול 11

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

ייצוג מערך דו-מימדי כמערך של מערכים:

מערכים המייצגים כל אחד שורה

מערך של מצביעים – כל מצביע מצביע לשורה המתאימה

Matrix :

Page 20: תרגול 11

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

כדי להקצות דינאמית מערך דו-מימדי )למשל של מס' שלמים( כמערך של מערכים צריך:להקצות מערך חד מימדי של מצביעים )המערך המאונך בציור(1.להקצות מערך חד-מימדי עבור כל שורה, כך שעל כל שורה יצביע המצביע המתאים מהמערך שהקצנו 2.

.1בסעיף

וזה הקוד שעושה זאת: )מצביע למצביע למס' שלם(**int, והוא יהיה מסוג matrixלמערך של המצביעים נקרא

יש לנו את מימדי המטריצה אותה אנו רוצים להקצות.col ו-rowונניח כי במשתנים 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){

printf(“Allocation failed\n”);return 1;

}}

Page 21: תרגול 11

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

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

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

בעזרת מצביע לאותו משתנה )ושליחת הכתובת שלו לפונקציה(1.

להחזיר את הערך שרוצים להציב כערך מוחזר מהפונקציה2.

בעזרת מצביע:

)הערך שאנו רוצים להציב הוא הכתובת matrixהמשתנה שבו אנחנו רוצים להציב ערך בפונקציה הוא ***int אז מצביע אליו יהיה מטיפוס **int הוא מטיפוס matrix מחזיר לנו(. מאחר ו-mallocש-

והפונקציה תיראה כך:

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הקריאה לפונקציה תהיה:

וכמובן להוסיף בדיקות שההקצאה הצליחה

Page 22: תרגול 11

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

בעזרת ערך מוחזר:

הפונקציה תיראה כך:

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[זה יעבוד בגלל שהזיכרון שקיבלנו מ-אותו יותר.]

Page 23: תרגול 11

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

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

הוגדר סטטית. כלומר:

matrix[i][j]