תכנות תרגול 8 שבוע : 18.12.05. מערכים עד היום התוכניות שלנו...

Preview:

Citation preview

88 תכנות תרגולתכנות תרגול

::שבועשבוע

18.12.0518.12.05

מערכיםמערכים

עד היום התוכניות שלנו לא ידעו לשמור כמות עד היום התוכניות שלנו לא ידעו לשמור כמות •גדולה של מידע ללא הגדרת כמות גדולה של גדולה של מידע ללא הגדרת כמות גדולה של

משתנים. משתנים.

מספרים מספרים 100100אתגר: כתוב תוכנית שקולטת אתגר: כתוב תוכנית שקולטת •שלמים ומדפיסה אותם מהאחרון שנקלט שלמים ומדפיסה אותם מהאחרון שנקלט

לראשון. לראשון. 100100 9999 , ... , , ... , 55 44 33 22 11קלט: קלט: 11 22 33 44 55 , ... , , ... , 9999 100100פלט: פלט:

הבית האדום

2כתובת : רחוב קוקוריקו

הבית הירוק

4כתובת : רחוב קוקוריקו

הבית הצהוב

1כתובת : רחוב קוקוריקו

הבית הורוד

3כתובת : רחוב קוקוריקו

2?”הבית האדום“מה הכתובת של

?2מי גר בבית מספר

רמי

יוסי

שמעון

אבנר

רמי

רמי?”בית האדום“מי גר ב

2000כתובת :

a 2000?מה הכתובת של2000מה נמצא בתא ?

a

80

3

7

5

a?5מה נמצא ב

5

b

cd

1000כתובת :

3000כתובת : 4000כתובת :

מצביעיםמצביעים

לכל משתנה שמוגדר בתוכנית יש כתובת לכל משתנה שמוגדר בתוכנית יש כתובת •

הכתובת שלו היא מיקומו בזכרוןהכתובת שלו היא מיקומו בזכרון•

למשללמשל

. . bytesbytes 44 אזי צורכים אזי צורכים intintכאשר משכנים מספר מסוג כאשר משכנים מספר מסוג

int a; a5000

מצביעיםמצביעים

int a, b;int *p1;int *p2;a = 5;b = 7;p1 = &a;p2 = &b;

a5000

b5004

2

2

p17026

p27030

5000

5004

*p1 = 2;*p2 = *p1;

מצביעים ופונקציותמצביעים ופונקציותעד היום הפונקציות שלנו ידעו לקבל ערכים של עד היום הפונקציות שלנו ידעו לקבל ערכים של

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

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

5

3

printf

3

a

2020

5

b

2034

int a=3,b=5;printf(“%d %d”,a,b)

, b ואת aאין צורך לדעת את כתובותיהם שלאלא רק את ערכיהם

scanfa

2020

b

2034

int a,b;scanf(“%d %d”,&a,&b)

, ולא b ו aצריך לדעת את כתובותיהם שלאת ערכיהם

35

int main(){ int a;

scanf(“%d”,&a);}

a5000

scanf

*pa = ערך מהמשתמש

void swap (int* q,int* p)void swap (int* q,int* p)

{{

int temp = *p;int temp = *p;

*p = *q; *p = *q;

*q = temp;*q = temp;

}}

int main(){ int a=10,b=2,x=3,y=5;

swap(&x,&y);

swap(&a,&b);

}

x5000

y5004

3

5

p7026

q7030

5000

5004

7034 temp3

5

3

הקשר בין מערכים למצביעיםהקשר בין מערכים למצביעיםנרצה לעמוד על הקשר בין מערך למצביענרצה לעמוד על הקשר בין מערך למצביע

מאחר ומערכים הם הכללה של משתנים הרי שברור מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו יש כתובת שלמערך ולכל אחד מאיבריו יש כתובת

a[0]

a[1]

a[2]

a[9]

5

5000

5004

5008

כדי להגיע לכתובת של תא כדי להגיע לכתובת של תא a[2]a[2]&&במערך פשוט נכתוב במערך פשוט נכתוב

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

המערךהמערך

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

הפונקציה תקבל מערך )את כתובתו( ותדפיס אותו:הפונקציה תקבל מערך )את כתובתו( ותדפיס אותו:void PrintArray(int a[],int size)void PrintArray(int a[],int size){{

int i;int i;for (i=0;i<size;i++)for (i=0;i<size;i++)

printf(“%d”,a[i]);printf(“%d”,a[i]);}}

הקשר בין מערכים לפונקציותהקשר בין מערכים לפונקציות

הפונקציה תקלוט איברים לתוך מערךהפונקציה תקלוט איברים לתוך מערך

void GetArray(int a[],int size)void GetArray(int a[],int size){{

int i;int i;for (i=0;i<size;i++)for (i=0;i<size;i++)

scanf(“%d”,&a[i]);scanf(“%d”,&a[i]);}}

void PrintArray(int a[],int size);

int main(){

int a[SIZE];GetArray(a,SIZE);PrintArray(a,SIZE);return 0;

}

void GetArray(int a[],int size);

22תרגיל תרגיל כתבו את הפונקציות הבאות: כתבו את הפונקציות הבאות:

פונקציה שממלא מערך במספרים אקראייםפונקציה שממלא מערך במספרים אקראיים•פונקציה שמדפיסה מערךפונקציה שמדפיסה מערך• ( (swapswapפונקציה שהופכת את המערך )רמז: השתמשו בפונקציה פונקציה שהופכת את המערך )רמז: השתמשו בפונקציה •

פתרוןפתרון

מילוי מערךמילוי מערך

void fill_array(int array[], int size){

int i;srand(time(NULL));for (i = 0; i < size; i++)

array[i] = rand()/327;}

פתרוןפתרון

הדפסת מערךהדפסת מערך

void print_array(int array[], int size){

int i;for (i = 0; i < size; i++)

printf("%d ", array[i]);printf("\n");

}

פתרוןפתרון

הפיכת מערךהפיכת מערך

void reverse_array(int array[], int size){

int i;for (i = 0; i < size/2; i++)

swap(&array[i], &array[size - 1 - i]);}

#include <stdio.h>#include <stdlib.h>#include <time.h>#define SIZE 5void fill_array(int array[], int size);void reverse_array(int array[], int size);void print_array(int array[], int size);void swap(int *a, int *b);int main(){

int my_arr[SIZE];fill_array(my_arr, SIZE);print_array(my_arr, SIZE);reverse_array(my_arr, SIZE);print_array(my_arr, SIZE);return 0;

}

חשבון מצביעיםחשבון מצביעים

a[0]

a[1]

a[2]

a[9]

5

5000

5004

5008

כדי להגיע לתא השלישי כדי להגיע לתא השלישי a[2]a[2]במערך נוכל לעשות במערך נוכל לעשות

או או

*(a+2)*(a+2)

void reverse_array(int *begin, int *end){

while (begin < end){

swap(begin, end);begin++;end--;

}}

reverse_array(my_arr, my_arr + SIZE -1);חשבון מצביעיםחשבון מצביעים

begin end

a ee ad r

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

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

..NULLNULL אם לא אז יוחזר אם לא אז יוחזר

100 11 2231 445 35 15 22 445 35

קלט

a[4]&פלט

a b

22 445 35

int *findSubArray (int *array, int array_size, int int *findSubArray (int *array, int array_size, int *sub_array, int sub_size)*sub_array, int sub_size)

{{int i, j;int i, j;for (i = 0; i <= array_size - sub_size; i++,array+for (i = 0; i <= array_size - sub_size; i++,array++)+){{

for (j = 0; j < sub_size; ++j)for (j = 0; j < sub_size; ++j)if ( *(array + j) != sub_array[j] )if ( *(array + j) != sub_array[j] )

break;break;if (j == sub_size)if (j == sub_size)

return array;return array;}}return NULL;return NULL;

}}

#include <stdio.h>#include <stdio.h>int *findSubArray (int *array, int array_size, int *sub_array, int int *findSubArray (int *array, int array_size, int *sub_array, int

sub_size);sub_size);int main()int main(){{

int array1[] = {1, 45, 67, 1001, -19, 67, 89, 1004, -867, 34, int array1[] = {1, 45, 67, 1001, -19, 67, 89, 1004, -867, 34, 3, -1900, 10029},3, -1900, 10029}, array2[] = {34, 3, -1900}, *position;array2[] = {34, 3, -1900}, *position;position = findSubArray (array1, sizeof (array1) / sizeof (int), position = findSubArray (array1, sizeof (array1) / sizeof (int),

array2, sizeof (array2) / sizeof(int));array2, sizeof (array2) / sizeof(int));printf ("array2 appears in array1 starting from place : %d.\printf ("array2 appears in array1 starting from place : %d.\n", n",

(position == NULL)? -1 : position - array1 + 1);(position == NULL)? -1 : position - array1 + 1);

return 0;return 0;}}

מחרוזותמחרוזותמחרוזת זה מערך של תווים אשר מחרוזת זה מערך של תווים אשר מחרוזת – מחרוזת –

. . ’’00‘\‘\מסתיים ב מסתיים ב

a[0]

a[1]

a[2]

a[3]

5000

5001

5002

a[4]

a[5]

5003

5004

5005

‘S’

‘h’

‘a’

‘i’

‘\0’

char a[6] = “Shai”;

printf(“%s”,a);

s%הדפסה באמצעות

מחרוזותמחרוזות מאפשר לנו להעביר מחרוזות מאפשר לנו להעביר מחרוזות ’’00‘\‘\ הסיום בהסיום ב

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

void string_func(const char *s)

{…

while (*s != ’\0’)…{

מונע שינוי של המחרוזת

#include <stdio.h>#include <stdio.h>int strlen (const char * str)int strlen (const char * str){{ const char *eos = str;const char *eos = str; while( *eos++ ) ;while( *eos++ ) ; return( eos - str - 1 );return( eos - str - 1 );}}int main()int main(){{

char str[]="Shai";char str[]="Shai";printf("%d",strlen(str));printf("%d",strlen(str));return 0;return 0;

}}

? מה קורה פה

N U XIL ‘\0’

str

eos

100 101 102 103 104105 106

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

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

..NULLNULL אם לא אז יוחזר אם לא אז יוחזר

100 11 2231 445 35 15 22 445 35

קלט

a[4]&פלט

a b

22 445 35

int *findSubArray(int *array, int array_size, int int *findSubArray(int *array, int array_size, int *sub_array, int sub_size)*sub_array, int sub_size)

{{int i, j;int i, j;for (i = 0; i <= array_size - sub_size; i++)for (i = 0; i <= array_size - sub_size; i++){{

for (j = 0; j < sub_size; j++)for (j = 0; j < sub_size; j++)if ( *(array + i + j) != sub_array[j] )if ( *(array + i + j) != sub_array[j] )

break;break;if (j == sub_size)if (j == sub_size)

return array+i;return array+i;}}

return NULL;return NULL;}}

! נניח שהמערכים הם מחרוזות

אפשר להעביר לפונקציה רק מצביע לתחילת אפשר להעביר לפונקציה רק מצביע לתחילת •המערך )המחרוזת(המערך )המחרוזת(

int *findSubArray(int *array, int array_size, int *sub_array, int sub_size)int *findSubArray(int *array, int array_size, int *sub_array, int sub_size)

for (i = 0; i <= array_size – sub_size; i++)for (i = 0; i <= array_size – sub_size; i++){{

for (j = 0; j < sub_size; j++)for (j = 0; j < sub_size; j++)if ( *(array + i + j) != sub_array[j])if ( *(array + i + j) != sub_array[j])

break;break;if (j == sub_size)if (j == sub_size)

return array+i;return array+i;}}

while (*cp)while (*cp)

#include <stdio.h>#include <stdio.h>char * strstr ( char * str1, char * str2)char * strstr ( char * str1, char * str2){{ char *cp = str1;char *cp = str1; char *s1, *s2;char *s1, *s2; if ( !*str2 )if ( !*str2 ) return(str1);return(str1); while (*cp)while (*cp) {{ s1 = cp;s1 = cp; s2 = str2;s2 = str2; while ( *s1 && *s2 && !(*s1-*s2) )while ( *s1 && *s2 && !(*s1-*s2) ) s1++, s2++;s1++, s2++; if (!*s2)if (!*s2) return(cp);return(cp); cp++;cp++; }} return(NULL);return(NULL);}}void main()void main(){{

char s1[]="I am a boy";char s1[]="I am a boy";char s2[]="am";char s2[]="am";printf("%s", strstr(s1,s2));printf("%s", strstr(s1,s2));

}}

בדיקת תת המחרוזת

נניח שהמערכים ! הם מחרוזות

תרגילתרגיל

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

המילים מופרדות על ידי רווחים המילים מופרדות על ידי רווחיםרמז:רמז: isspace(char c)isspace(char c)ניתן להשתמש בפונקציה ניתן להשתמש בפונקציה

שנמצאת שנמצאת <<include <ctype.hinclude <ctype.h##ב ב

int word_cnt (const char *s)int word_cnt (const char *s){{

int cnt = 0;int cnt = 0;const char *next = s + 1;const char *next = s + 1;if (*s == '\0') /*empty string*/if (*s == '\0') /*empty string*/

return 0;return 0;while(*next != '\0')while(*next != '\0'){{

if (!isspace(*s) && isspace(*next))if (!isspace(*s) && isspace(*next))cnt++;cnt++;

s++;s++;next++;next++;

}}if (!isspace(*s))if (!isspace(*s))

cnt++;cnt++;return cnt;return cnt;

}}

דרכים נוספות להגדיר מחרוזותדרכים נוספות להגדיר מחרוזות

h

p

e l l o \0 h e l l o \0s

char *p = “hello”; char *p = “hello”; char s[ ] = char s[ ] = “hello”;“hello”;

קלט למחרוזתקלט למחרוזת

scanf(“%s”, str); scanf(“%s”, str); gets(str);gets(str);

עד לרווח

עד לאנטר

Recommended