Transcript int

‫הקצאות דינאמיות‬
‫קרן כליף‬
‫ביחידה זו נלמד‪:‬‬
‫‪ ‬מוטיבציה להקצאות דינאמיות‬
‫‪ ‬מהי הקצאה דינאמית‬
‫‪ ‬יצירת מערך בגודל שאינו ידוע מראש‬
‫‪ ‬החזרת מערך מפונקציה‬
‫‪ ‬הקצאת מערך של מערכים‬
‫‪ ‬הגדלת מערך‬
‫‪ ‬הפונקציה ‪strdup‬‬
‫‪2‬‬
‫‪© Keren Kalif‬‬
‫מוטיבציה להקצאה דינאמית‬
‫‪‬‬
‫בעזרת הקצאה דינאמית נוכל‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪3‬‬
‫‪© Keren Kalif‬‬
‫להקצות מערך בזמן ריצה‪ ,‬בלי לדעת את גודלו בזמן קומפילציה‬
‫נוכל להחזיר מערך מפונקציה‬
‫מהי הקצאה דינאמית?‬
‫‪‬‬
‫הקצאה דינאמית היא הקצאת שטח זיכרון בגודל מבוקש‬
‫בזמן ריצת התוכנית‬
‫‪‬‬
‫‪‬‬
‫הקצאה דינאמית מוקצית על שטח הזיכרון ‪heap‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪4‬‬
‫‪© Keren Kalif‬‬
‫בניגוד להקצאה סטטית שמוקצית בתחילת התוכנית וגודלה ידוע‬
‫כבר בזמן קומפילציה‬
‫בניגוד להקצאה סטטית שמוקצית על ה‪ stack -‬של הפונקציה‬
‫ה‪ heap -‬הוא שטח זיכרון המשותף לכל הפונקציות‪ ,‬בניגוד ל‪-‬‬
‫‪stack‬‬
‫בהקצאת זיכרון דינאמית המתכנת מבקש ממערכת‬
‫ההפעלה זיכרון בגודל מסוים המוגדר בבתים ומקבל את‬
‫כתובת הבית הראשון בקטע הזיכרון שקיבל‬
‫הגדרה נוספת ל‪<type>* -‬‬
‫‪ ‬אנו יודעים שמשתנה מטיפוס *>‪<type‬מכיל כתובת של‬
‫משתנה מטיפוס >‪ <type‬כלשהו‬
‫‪ ‬כתובת התחלה של מערך מטיפוס >‪<type‬היא גם‬
‫כתובתו של האיבר הראשון במערך‪ ,‬שהוא משתנה‬
‫מטיפוס >‪<type‬‬
‫‪ ‬לכן משתנה מטיפוס *>‪ <type‬יכול להכיל גם כתובת‬
‫התחלה של מערך‬
‫‪ ‬לכן נאמר ש‪ <type>* -‬הוא פוטנציאל למערך‬
‫‪‬‬
‫‪5‬‬
‫‪© Keren Kalif‬‬
‫כלומר‪ ,‬יכול להכיל כתובת התחלה של מערך (ולא רק כתובת‬
‫של משתנה יחיד מטיפוס >‪)<type‬‬
‫הפקודה ‪new‬‬
‫;]‪int* arr = new int[size‬‬
‫‪ ‬נשתמש בה כאשר נרצה להקצות מערך בגודל שאינו ידוע‬
‫בזמן קומפילציה‬
‫‪ ‬כדי להקצות מערך נשתמש ב‪ ][ -‬ובתוכם גודל המערך‬
‫המבוקש‬
‫‪ ‬הפקודה מחזירה את כתובת ההתחלה של המערך‬
‫שהוקצה ובהמשך נשתמש עם כתובת זו‬
‫‪6‬‬
‫‪© Keren Kalif‬‬
7
© Keren Kalif
‫ – הקצאת מערך בגודל שאינו ידוע‬new
‫מראש‬
void main()
{
int size, *arr;
cout << "Please enter the size of the array: ";
cin >> size;
arr = new int[size];
,‫ אין שם‬heap -‫נשים לב שלמשתנה על ה‬
!‫אלא רק יש אליו הצבעה מאחת הפונקציות‬
if (!arr) // (arr == NULL) --> allocaton didn't succeed
{
cout << "ERROR! Out of memory!\n";
return;
}
cout << "Values in the array: ";
for (int i=0 ; i < size ; i++)
cout << *(arr+i) << “ “; //*(arr+i) == arr[i]
cout << "\nPlease enter “ << size << “ numbers: “;
for (int i=0 ; i < size ; i++)
cin >> arr[i];
}
cout << "Values in the array: ";
for (int i=0 ; i < size ; i++)
cout << arr[i] << “ “;
cout << endl;
int
???
1
3000
int
???
5
3004
int
???
8
3008
heap -‫זיכרון ה‬
int:size
???
3
1000
int*: arr
3000
???
1004
???
1008
int: i
main -‫הזיכרון של ה‬
‫שחרור הזיכרון שהוקצה‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫אחריות המתכנת לשחרר את כל זיכרון שהוקצה דינאמית‬
‫במילים אחרות‪ ,‬המתכנת אחראי להחזיר למערכת‬
‫ההפעלה כל שטח זיכרון שביקש ממנה בזמן ריצה‬
‫הסיבה‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪8‬‬
‫‪© Keren Kalif‬‬
‫שטח ה‪ heap -‬עליו מוקצות ההקצאות הדינאמיות מוגבל‬
‫בשטחו ומשותף לכל התוכניות‪ ,‬ואז התוכנית הבאה שתבקש‬
‫זיכרון עלולה לקבל ‪ NULL‬כי אנחנו לא החזרנו את הזיכרון‬
‫שביקשנו בסיום העבודה‪...‬‬
‫צריך לזכור‪ :‬כאשר יש סביבת עבודה משותפת‪ ,‬צריך להתחשב‬
‫גם באחרים (וזה שיעור חשוב בכלל לחיים ;‪))-‬‬
‫הקומפיילר לא מתריע על אי‪-‬שחרור הזיכרון ואין שום‬
‫אינדיקציה לדעת זאת‪ ,‬לכן חייבים לשים לב!!‬
‫פונקציה לשחרור הקצאות דינאמיות‬
‫‪ ‬הפונקציה ‪ delete‬משחררת הקצאה דינאמית‬
‫‪ ‬כאשר ההקצאה היא למערך צריך לזכור לשים [] לפני שם‬
‫המערך‬
‫‪delete [] arr‬‬
‫‪9‬‬
‫‪© Keren Kalif‬‬
void main()
{
int size, *arr;
‫ – שחרור זיכרון‬delete
cout << "Please enter the size of the array: ";
cin >> size;
arr = new int[size];
if (!arr) // (arr == NULL) --> allocaton didn't succeed
{
cout << "ERROR! Out of memory!\n";
return;
}
cout << "Values in the array: ";
for (int i=0 ; i < size ; i++)
cout << *(arr+i) << “ “; //*(arr+i) == arr[i]
cout << "\nPlease enter “ << size << “ numbers: “;
for (int i=0 ; i < size ; i++)
cin >> arr[i];
}
cout << "Values in the array: “;
for (int i=0 ; i < size ; i++)
cout << arr[i] << “ “;
cout << endl;
delete []arr;
int
???
1
3000
int
???
5
3004
int
???
8
3008
heap -‫זיכרון ה‬
int:size
???
3
1000
int*: arr
3000
???
1004
???
1008
int: i
main -‫הזיכרון של ה‬
10
© Keren Kalif
‫תזכורת‪ :‬החזרת מערך מפונקציה‬
‫‪‬‬
‫ראינו כי כאשר מעבירים מערך לפונקציה‪ ,‬מעבירים רק‬
‫את כתובת ההתחלה שלו‪ ,‬ולא עותק של כל המערך‬
‫‪ ‬ובאופן דומה‪ ,‬כאשר מחזירים מערך שהוגדר בפונקציה‪,‬‬
‫חוזרת כתובת ההתחלה שלו‪ ,‬ולא עותק של כל המערך‬
‫‪ ‬הבעייתיות‪ :‬כאשר יוצאים מהפונקציה שטח הזיכרון שלה‬
‫משתחרר ויש לנו מצביע לזיכרון שנמחק‪...‬‬
‫‪‬‬
‫הפתרון‪ :‬הקצאה דינאמית‬
‫‪11‬‬
‫‪© Keren Kalif‬‬
12
© Keren Kalif
‫ הבעייתיות בהחזרת מערך‬:‫תזכורת‬
‫ דוגמא‬- ‫מפונקציה‬
const int SIZE = 3;
int[]: arr
???
3
2000
int* readArray()
???
5
2004
{
int arr[SIZE];
???
6
2008
cout << "Please enter “ << SIZE << “ numbers: “;
???
3
int: i
2012
for (int i=0 ; i < SIZE ; i++)
readArray ‫הזיכרון של‬
cin >> arr[i];
return arr;
:warning ‫הקומפיילר נותן‬
}
void main()
{
int* arr;
arr = readArray();
}
returning address of local variable or temporary
‫שפירושה שאנחנו מחזירים כתובת למשתנה בזיכרון שישתחרר‬
cout << "The array is: \n";
for (int i=0 ; i < SIZE ; i++)
cout << arr[i] << “ “;
cout << endl;
‫לעולם לא נחזיר מפונקציה‬
‫כתובת של משתנה‬
!‫שהוגדר בה מקומית‬
int*: arr
2000
???
1000
int: i
???
1004
main -‫הזיכרון של ה‬
const int SIZE = 3;
‫ הקצאת‬:‫הפתרון‬
‫המערך דינאמית‬
int* buildArray()
{
int* arr = new int[SIZE];
if (!arr)
{
cout << "ERROR! Not enough memory!\n";
return;
}
for (int i=0 ; i < SIZE; i++)
arr[i] = i+1;
}
‫אם אנחנו יוצאים מפונקציה שהקצתה‬
‫ חובה להחזיר את‬,‫דינאמית ולא שחררה‬
‫ כדי שנוכל‬,‫כתובת ההתחלה של ההקצאה‬
!‫לשחרר אותה בהמשך‬
‫אחרת כאשר נצא מהפונקציה כבר לא יהיה‬
!‫משתנה שיכיל את מיקום ההקצאה‬
return arr;
int:i
void main()
{
int *arr, i;
int*: arr
}
delete []arr;
2000
3000
???
2004
buildArray ‫הזיכרון של‬
arr = buildArray();
cout << "Values in the array: "; int
for (i=0 ; i < SIZE ; i++)
int
cout << arr[i] << “ “;
cout << endl;
int
???
???
1
3000
???
2
3004
???
3
3008
heap -‫זיכרון ה‬
int*: arr
int: i
3000
???
1000
???
1004
main -‫הזיכרון של ה‬
13
© Keren Kalif
‫הקצאה בתוך פונקציה‬
‫‪‬‬
‫אחריות שלנו כמתכנתים לשחרר את כל הזיכרון שהקצינו‬
‫‪‬‬
‫יש לשים לב בייחוד במקרים בהם ההקצאה מתבצעת‬
‫בפונקציה אחת‪ ,‬והשחרור צריך להיות בפונקציה אחרת!‬
‫‪14‬‬
‫‪© Keren Kalif‬‬
‫החזרת מערך מפונקציה ‪by pointer‬‬
‫‪ ‬למדנו שפונקציה יכולה להחזיר ערכים ע"י קבלת כתובת‬
‫לעדכון התשובה‬
‫‪ ‬למשל‪:‬‬
‫;)‪int getSum(int arr[], int size‬‬
‫‪ ‬לעומת‪:‬‬
‫;)‪void getSum(int arr[], int size, int* sum‬‬
‫‪‬‬
‫באותו אופן ניתן גם להחזיר מערך שייוצר בתוך הפונקציה‬
‫‪‬‬
‫‪15‬‬
‫‪© Keren Kalif‬‬
‫לא לשכוח להעביר את המערך כ‪** -‬‬
void buildArray(int* arr, int size)
{
arr = new int[size];
‫החזרת מערך מפונקציה‬
‫ דוגמא‬- by pointer
if (!arr)
}
cout << "ERROR! Not enough memory!\n”;
return;
{
int
???
1
3000
int
???
2
3004
int
???
3
3008
for (int i=0 ; i < size ; i++)
arr[i] = i+1;
heap -‫זיכרון ה‬
{
void main()
{
int size, *arr=NULL;
int:size
int: i
cout << "Please enter the size of the array: “;
cin >> size;
buildArray(arr, size);
cout << "Values in the array: “;
for (int i=0 ; i < size ; i++)
cout << arr[i] << “ “;
cout << endl;
}
delete []arr;
int*: arr
2000
???
2004
NULL
3000
2008
buildArray ‫הזיכרון של‬
int:size
???
3
1000
int*: arr
NULL
???
1004
???
1008
int: i
...‫פה התוכנית תעוף‬
3
main -‫הזיכרון של ה‬
16
© Keren Kalif
void buildArray(int** arr, int size)
}
*arr = new int[size];
‫החזרת מערך מפונקציה‬
‫ התיקון‬- by pointer
if (!*arr)
}
cout << "ERROR! Not enough memory!\n”;
return;
{
int
???
1
3000
int
???
2
3004
int
???
3
3008
for (int i=0 ; i < size ; i++)
(*arr)[i] = i+1;
heap -‫זיכרון ה‬
{
void main()
{
int size, *arr=NULL;
int:size
int: i
int**: arr
cout << "Please enter the size of the array: “;
cin >> size;
buildArray(&arr, size);
cout << "Values in the array: “;
for (int i=0 ; i < size ; i++)
cout << arr[i] << “ “;
cout << endl;
}
delete []arr;
3
2000
???
2004
1004
2008
buildArray ‫הזיכרון של‬
int:size
???
3
1000
int*: arr
NULL
3000
???
1004
???
1008
int: i
main -‫הזיכרון של ה‬
17
© Keren Kalif
‫החזרת מערך מפונקציה ‪by ref‬‬
‫‪ ‬למדנו שפונקציה יכולה להחזיר ערכים ע"י קבלת פרמטר‬
‫‪ by ref‬שיעדכן את התשובה‬
‫‪ ‬למשל‪:‬‬
‫;)‪int getSum(int arr[], int size‬‬
‫‪ ‬לעומת‪:‬‬
‫;)‪void getSum(int arr[], int size, int& sum‬‬
‫‪‬‬
‫באותו אופן ניתן גם להחזיר מערך שייוצר בתוך הפונקציה‬
‫‪‬‬
‫‪18‬‬
‫‪© Keren Kalif‬‬
‫לא לשכוח להעביר את המערך כ‪*& -‬‬
void buildArray(int*& arr, int size)
}
arr = new int[size];
‫החזרת מערך מפונקציה‬
‫ התיקון‬- by ref
if (!arr)
}
cout << "ERROR! Not enough memory!\n”;
return;
{
int
???
1
3000
int
???
2
3004
int
???
3
3008
for (int i=0 ; i < size ; i++)
arr[i] = i+1;
heap -‫זיכרון ה‬
{
void main()
{
int size, *arr=NULL;
cout << "Please enter the size of the array: ";
cin >> size;
buildArray(arr, size);
cout << "Values in the array: “;
for (int i=0 ; i < size ; i++)
cout << arr[i] << “ “;
cout << endl;
}
delete []arr;
int:size
int: i
3
2000
???
2004
int*: arr
buildArray ‫הזיכרון של‬
int:size
???
3
1000
int*: arr
NULL
3000
???
1004
???
1008
int: i
main -‫הזיכרון של ה‬
19
© Keren Kalif
‫הקצאת מערך של מערכים (‪)1‬‬
‫‪‬‬
‫‪20‬‬
‫‪© Keren Kalif‬‬
‫כעת אנחנו יכולים לייצר מטריצה שבכל שורה יש מספר‬
‫שונה של איברים‬
21
© Keren Kalif
)2( ‫הקצאת מערך של מערכים‬
void main()
{
int rows, **matrix, *sizes;
cout << "Enter number of rows in the matrix: ";
cin >> rows;
matrix = new int*[rows];
sizes = new int[rows];
}
1000
???
3000
1004
int: i
???
0
1
2
3
1008
int: j
???
1012
int**: matrix
for ( int i=0; i < rows ; i++ )
{
cout << "Enter size of row #“ << i+1 << “: ”;
cin >> sizes[i];
matrix[i] = new int[sizes[i]];
for (int j=0 ; j < sizes[i] ; j++)
matrix[i][j] = (i+1)*10+j+1;
}
int* 4050
cout << "The matrix is:\n”;
??? 3000
for (int i=0 ; i < rows ; i++)
int* 5000
??? 3004
{
for (int j=0 ; j < sizes[i] ; j++) int*
2200
??? 3008
cout << matrix[i][j] << “ “;
cout << endl;
int
31
0
}
delete []sizes;
int
32
0
for ( int i=0 ; i < rows ; i++ )
int
33
0
delete []matrix[i];
delete []matrix;
int
???
3
int:rows
34
0
4000
??? 1016
main -‫הזיכרון של ה‬
int*: sizes
int
11
0
4050
int
12
0
4054
2200
2224
2228
2232
int
21
0
5000
int
22
0
5004
int
23
0
5008
int
???
2
4000
int
???
3
4004
int
???
4
4008
heap -‫זיכרון ה‬
‫הגדלת מערך‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫בדוגמא הבאה אנו קולטים מהמשתמש מספרים לתוך‬
‫מערך‪ ,‬לא ידוע כמה איברים המשתמש יכניס‬
‫כל פעם כאשר כבר אין מקום במערך צריך להגדיל אותו‬
‫פי ‪2‬‬
‫האלגוריתם‪:‬‬
‫‪‬‬
‫‪‬‬
‫קרא את האיבר החדש‪ ,‬אם ‪ -1‬צא‬
‫אם אין מקום במערך‪ ,‬הקצה מערך גדול פי ‪2‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪22‬‬
‫‪© Keren Kalif‬‬
‫העתק למערך החדש את האיברים מהמערך הישן‬
‫שחרר את המערך המקורי‬
‫שנה את מצביע המערך להצביע למערך החדש‬
‫הגדלת מערך ‪ -‬הפלט‬
‫‪23‬‬
‫‪© Keren Kalif‬‬
void main()
{
int num, physSize = 2, logicSize = 0;
int *arr = new int[physSize], *tmp;
}
‫הגדלת מערך – הקוד‬
cout << "Please enter numbers, -1 to stop:\n”;
while (1)
7
0
int
2200
{
4
0
int
cin >> num;
if (num == -1)
0
7
int
4300
break;
if (physSize == logicSize)
0
4
int
4304
{
0
5
physSize *= 2;
int
4308
tmp = new int[physSize];
0
int
4312
for (int i=0 ; i < logicSize ; i++)
tmp[i] = arr[i];
delete []arr;
heap -‫זיכרון ה‬
arr = tmp;
int: num
cout << "Doubled the array size to “ << physSize << endl;
-1
7
5
???
4
1000
1000
}
int: i
??? 1004
1004
cout << "Read number is “ << num << endl;
arr[logicSize] = num;
int: physSize
2
4
???
1008
1008
logicSize++;
}
int: logicSize
1
2
3
???
0
1012
1012
cout << "The array has “ << logicSize
int*: arr
<< “ elements (physSize=“ << physSize << “):\n”;
2200
4300
??? 1016
1016
for (int i=0 ; i < logicSize ; i++)
int*: tmp
4300
??? 1020
1020
cout << arr[i] << “ “;
cout << endl;
main -‫הזיכרון של ה‬
delete []arr;
24
© Keren Kalif
?‫מה יהיה פלט התוכנית הבאה‬
void main()
{
char* c = new char[5];
char** s = new char*[3];
int i;
for( i=0 ; i < 3 ; i ++ )
{
cout << "enter word : “;
cin.getline(c, 5);
s[i] = c;
{
for(i=0; i<3; i++)
cout << "strings : “ << s[i] << endl;
}
delete []c;
delete []s;
char
???
‘h’
‘b’
‘g’
4300
char
???
‘o’
‘y’
‘i’
4301
char
???
0
‘o’
‘e’
4302
char
???
0
‘d’
4303
char
???
0
4304
char*
???
4300
5300
char*
4300
???
5304
char*
???
4300
5308
heap -‫זיכרון ה‬
char*: c
4300
???
1000
5300
???
1004
???
0
1
2
3
1008
char**: s
int: i
main -‫הזיכרון של ה‬
25
© Keren Kalif
‫התיקון לתוכנית הקודמת‬
void main()
{
char* c;
char** s = new char*[2];
int i;
for( i=0 ; i < 2 ; i ++ )
{
c = new char[5];
cout << "enter word : ";
cin.getline(c, 5);
s[i] = c;
{
for(i=0; i<2; i++)
cout << "strings : “ << s[i] << endl;
}
for (i=0 ; i < 2 ; i++)
delete []s[i];
delete []s;
char
???
‘b’
6300
char
???
‘y’
6301
char
???
‘e’
6302
char
???
0
6303
char
???
6304
char
???
‘h’
4300
char
???
‘i’
4301
char
???
0
4302
char
???
4303
char
???
4304
char*
???
4300
5300
char*
???
6300
5304
heap -‫זיכרון ה‬
char*: c
4300
6300
???
1000
5300
???
1004
???
0
1
2
1008
char**: s
int: i
main -‫הזיכרון של ה‬
26
© Keren Kalif
‫הפונקציה ‪strdup‬‬
‫‪‬‬
‫)‪char* strdup(const char *str‬‬
‫מקבלת מחרוזת ומחזירה העתק שלה‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪‬‬
‫‪27‬‬
‫‪© Keren Kalif‬‬
‫מקצה דינאמית על ה‪ heap -‬מערך של תווים בגודל המחרוזת‬
‫המקורית‪ ,‬מעתיקה אליו את התוכן ומחזירה את כתובת‬
‫ההתחלה שלו‬
‫תחזיר ‪ NULL‬במידה וההקצאה נכשלה‬
‫אחריות המתכנת לשחרר את המחרוזת שחזרה!!‬
28
© Keren Kalif
‫ – דוגמא‬strdup
void main()
}
char str1[] = "hi";
char* str2 = "bye";
char* newStr1 = strdup(str1);
char* newStr2 = strdup(str2);
char
‘b’
5300
char
‘y’
5301
char
‘e’
5302
char
‘\0’
5303
static storage -‫זיכרון ה‬
cout << "The first duplicated string: |” << newStr1 << “|\n”;
cout << "The second duplicated string: |” << newStr2 << “|\n”;
delete []newStr1;
delete []newStr2;
{
char
‘b’
char
‘y’
char
‘e’
char
‘\0’
6300
6301
6302
6303
???
‘h’
1000
???
‘i’
1001
‘\0’
???
1002
char*: str2
5300
???
1003
char*: newStr1
4300
???
1007
char*: newStr2
6300
???
1011
char: str1[]
char
‘h’
4300
char
‘i’
4301
char
‘\0’
4302
heap -‫זיכרון ה‬
main -‫הזיכרון של ה‬
‫ביחידה זו למדנו‪:‬‬
‫‪ ‬מוטיבציה להקצאות דינאמיות‬
‫‪ ‬מהי הקצאה דינאמית‬
‫‪ ‬יצירת מערך בגודל שאינו ידוע מראש‬
‫‪ ‬החזרת מערך מפונקציה‬
‫‪ ‬הקצאת מערך של מערכים‬
‫‪ ‬הגדלת מערך‬
‫‪ ‬הפונקציה ‪strdup‬‬
‫‪29‬‬
‫‪© Keren Kalif‬‬
‫תרגיל ‪1‬‬
‫‪ ‬כתוב תוכנית המבקשת מהמשתמש להכניס את כמות‬
‫המספרים שהוא רוצה שיהיו במערך‪ ,‬והקצה מערך‬
‫בהתאם‬
‫‪ ‬הגרל ערכים למערך והגרל מספר נוסף (בטווח ‪)0-9‬‬
‫‪ ‬ייצר מערך חדש המכיל את האינדקסים במערך המקורי‬
‫שערך האיבר שבתוכם שווה למספר הנוסף שהתקבל‬
‫‪ ‬הצג את המערך שחדש שייצרת‬
‫‪ ‬דוגמא‪:‬‬
‫עבור המערך ‪ 1,2,5,2,2,9‬גודלו ‪ 6‬והמספר ‪ ,2‬יוחזר‬
‫מערך בגודל ‪ 3‬שערכיו ‪1,3,4‬‬
‫‪30‬‬
‫‪© Keren Kalif‬‬
‫תרגיל ‪2‬‬
‫‪ ‬כתוב פונקציה המקבלת מחרוזת ותו‪ .‬הפונקציה תייצר‬
‫ותחזיר מחרוזת חדשה שאורכה ככמות הפעמים שהתו‬
‫מופיעה במחרוזת המקורית והיא תכיל תו זה כמספר‬
‫פעמים זה‬
‫‪ ‬דוגמאות‪:‬‬
‫‪‬‬
‫‪‬‬
‫‪31‬‬
‫‪© Keren Kalif‬‬
‫עבור המחרוזת ”‪ “hello‬והתו ’‪ ‘l‬תוחזר המחרוזת ”‪“ll‬‬
‫עבור המחרוזת ”‪ “keren‬והתו ’‪ ‘e‬תוחזר המחרוזת ”‪“ee‬‬
‫תרגיל ‪3‬‬
‫‪ ‬כתוב פונקציה המקבלת ‪ 2‬מערכים וגודלם‪ .‬הפונקציה‬
‫תחזיר מערך חדש המכיל את הערכים שבשני המערכים‬
‫‪ ‬הפוקנציה גם תחזיר את גודל המערך המוחזר‬
‫‪ ‬דוגמא‪:‬‬
‫עבור המערך ‪ 1,8,2‬וגודלו ‪ 3‬והמערך ‪ 9,2,6,7‬וגודלו ‪4‬‬
‫יוחזר המערך החדש ‪ 1,8,2,9,2,6,7‬וגודלו ‪7‬‬
‫‪32‬‬
‫‪© Keren Kalif‬‬