מבו א למדע י המחש ב מצביעים 1
מצביע ים (pointers) מצביע הוא משתנה המ כ יל כתובת של משתנה. p c,c אם p הוא מצביע ל- c, אזי תוכן המשתנה כלומר, מצביע על התא ששמו הוא c. p הוא הכ תובת של 2
מצביע ים - תח בי ר האופרטור האונארי & מחזיר את הכתובת של האובייקט בזיכרון. אובייקט משתנה, תא של מערך. לא קבוע ולא ביטוי. האופרטור האונארי * (dereference) לוקח מצביע ומחזיר את הערך (תוכן התא) שעליו מצביע המצביע. דוגמא: char c; char *p; p=&c; שימו לב: ב- C אין טיפוס למצביעים. בדוגמא הנ"ל p הוא מצביע ל-,char הוא אינו.char.char תופס בדיוק בית אחד בזיכרון. לא כך הדבר לגבי מצביע ל- char 3
מצביע ים - דוגמא int x= 1, y=2, *ip, z[10]; x ip y z 1 2 int pointer 4
מצביע ים - דוגמא int x= 1, y=2, *ip, z[10]; : ip=&x; x ip y z 1 2 int pointer 5
מצביע ים - דוגמא int x= 1, y=2, *ip, z[10]; : ip=&x; y=*ip; x ip y z 1 21 6
מצביע ים - דוגמא int x= 1, y=2, *ip, z[10]; : ip=&x; y=*ip; *ip=0; x ip y z 10 1 7
מצביע ים - דוגמא int x= 1, y=2, *ip, z[10]; : ip=&x; y=*ip; *ip=0; ip=&(z[0]); x ip y z 0 1 8
מצביע ים - דוגמאות int *ip; double *fp; (double *ip הוא מטיפוס ip) int הוא מצ בי ע ל- (int *fp הוא מטיפוס fp) double הוא מצ ביע ל- double func( char *);.double ומחזירה char הצהרה על הפונק ציה,func שמק בלת מצ בי ע ל- 9
מצביע ים כל מצביע מצביע לערכים מטיפוס מסוים ולהם בלבד. פוינטר לערכים מטיפוס מסוים לא יכול להצביע על ערכים מטיפוס אחר. המקום שאותו מצביע תופס בזכרון הוא זהה לכל המצביעים והוא תלוי מערכת הפעלה. הוא לא תלוי בגודל הערך שאליו מצביע הפוינטר. אם ip מצביע ל- x, אזי *ip יכול להופיע בכל מקום שבו יכול להופיע x: *ip+=10; *ip=*ip*2; ++*ip; ip=iq אם ip ו- int שניהם מצביעים ל- iq 10
העבר ת פרמ ט רים בשפת C העברת פרמטרים לפונקציות היא by value בלבד. פונקציה לא יכולה באופן ישיר להשפיע על ערכים בסביבה שקראה לה. תזכורת: /* swap: WRONG!!! */ void swap(int a, int b) int temp; temp=a; a=b; b=temp; return; 11
העברת פ רמטרי ם ב אמ צ עו ת פוינטרים אפשר להע ביר כתובות של משתנים מהס ביב ה הקוראת אל הפונק ציה. /* swap: CORRECT */ void swap(int *px, int *py) int temp; temp= *px; *px = *py; *py =temp; return; int a,b; a=7; b=3; swap(&a,&b); סביבה קוראת: a b px py מ פ ת הז י כרון: 12 בפונקצ י ה בסביבה הקוראת
פו ינ טרי ם ו מערכ י ם בשפת C ישנו קשר הדוק בין מצביעים ומערכים: כל פעולה שקשורה להשגת ערך ממערך ניתן לבצע באמצעות מצביעים. החיסרון: פחות ברור. ערכו של ביטוי מטיפוס מערך הוא כתובת האיבר הראשון ([0]) המערך. דוגמא: של int a[10]; a: int *pa; 0 1 2 9 pa=&(a[0]); x=*pa; x=*(pa+2); לאחר ההשמה ל- pa ול- a יש ערך זהה. לכן, ניתן לכתוב גם pa=a; 13
הקשר בין מצביעים ומערכים 14
פוינטר י ם ו מערכים pa+j באופן כללי: אם pa מצביע לתוך התא ה- i של a, מצביע לתוך התא ה- i+j של a. אזי a: pa: i pa+j i+j לכן *(a+i) שקול ל-.a[i] כמו כן, &a[i] שקול ל-.(a+i) פעולות כאלו על מצביעים אפשריות ללא תלות בטיפוס או בגודל של אברי המערך! 15
מערכים ו פוינטר י ם שימו לב: יש הב ד ל בין שם של מערך ובין מצביע: pa=a; מצב יע הוא משת נה, לכן ניתן לב צ ע pa++; או שם של מערך אי נו משת נה, לכן a=pa; וגם ;++a אינם חוקיים. 16
אריתמ ט י ק ה של פוינ ט רים אם p ו- q שני מצביעים המצביעים לאותו מערך ניתן להשוות ביניהם:, < <=,!=, ==, p מצביע עליו נמצא לפני התא ש- q מצביע עליו p < q אם התא ש- (השוואה בין כתובות). הוספה והחסרה של שלם: 2+p + p פעמיים הטיפוס ש- p מצביע עליו. וכו' כנ"ל לגבי ++p 1-p, p,q מצביעים לאותו p=q רק אם השמה של מצביעים מאותו טיפוס: טיפוס. int לתוך מצביע. אסור להציב משמעות הערך השלם היחיד שניתן להציב לתוך מצביע הוא אפס. האיפוס היא שהמצביע מאותחל, אך הוא אינו מצביע על שום תא בזיכרון. p=null; ניתן לרשום באופן שקול 17
העבר ת מערכים ל פונקציות בכותרת הפונקציה יש להצהיר על טיפוס המערך ושמו הפורמלי, ללא אורך. בסביבה הקוראת יצוין שם המערך. הערך האקטואלי שיועבר לפונקציה הוא כתובת התחלת המערך. בתוך הפונקציה, הארגומנט הוא למעשה משתנה פנימי מאותחל, ולפיכך ניתן להתייחס אליו כאל מצביע. int mystrlen (char s[ ]) int n; for (n=0; *s!= \0 ; s++) n++; return n; s מועבר by value ולכן ניתן להגדיל אותו ללא הסביבה על השפעה הקוראת! 18
#include<stdio.h> העברת מערכים לפונקציות int mystrlen (char s[ ]) int n; for (n=0; *s!= \0 ; s++) n++; return n; ני ת ן לכת וב באו פ ן שקו ל: int mystrlen (char *s) int main() char array[10]= hello ; char *ptr; printf( %d\n, mystrlen( hello world )); printf( %d\n, mystrlen(array)); ptr=array; ptr[0]= a ; ptr[1]= b ; ptr[2]= c ; ptr[3]= \0 ; printf( %d\n, mystrlen(ptr)); printf( %d\n, mystrlen(array)); return 0;
העבר ת מערכים ל פונקציות כשפונק ציה מקבל ת מערך כפ רמטר היא יכולה להתייחס אליו כא ל מערך או כאל מצביע או בשני האופנים. ניתן להעביר חלק ממערך כפר מטר לפונקציה: strlen(&array[2]) strlen(array+2) 20
מח רוז ו ת מצביע ים int main() char str[]= hello"; char *ptr="hello"; printf("%s\n",str); printf("%s\n",ptr); ptr++; printf("%s\n",ptr); strcpy(str,"vv"); return 0; מוקצה מערך בגודל מספיק. ניתן לשנות את אברי המערך, אך str יצביע תמיד לאותו מקום (אותה כתובת). מוקצה מקום למצביע והוא מאותחל להצביע אל קבוע. ניתן לשנות את המצביע אך לא את הקבוע. לא נ י ת ן לבצע לא נ י ת ן לבצע str++; strcpy(ptr,"vv"); 21
ג רסאות שונות לא ותה פונק צ יה /* strcpy: copy a string from t to s */ void strcpy(char *s, char *t) int i=0; while ((s[i] = t[i])!= '\0') i++; strcpy האלגוריתם הנא י בי 22 void strcpy(char *s, char *t) while ((*s = *t)!= '\0') s++; t++; מצב יעים במק ום מערכים
ג רסאות שונות לא ותה פונק צ יה strcpy void strcpy(char *s, char *t) while ((*s = *t)!= '\0') s++; t++; מצב יעים במק ום מערכים void strcpy(char *s, char *t) while ((*s++ = *t++)!= '\0') ; קיצור כת יבה 23
ג רסאות שונות לא ותה פונק צ יה strcpy void strcpy(char *s, char *t) while ((*s++ = *t++)!= '\0') ; קיצור כת יבה void strcpy(char *s, char *t) while (*s++ = *t++) ; ההשוואה ל- 0\ מיותרת 24
מערכים ד ו-מ מדי ים (1) דוגמ א נרצה לכתוב תכנית המבצעת המרה מיום בחודש ליום בשנה ולהיפך. למשל: ה- 1 במרץ הוא היום ה- 60 בשנה רגילה והיום ה- 61 בשנה מעוברת. לכן, עבור הקלט: יום 60 בשנת 2005 נקבל את הפלט: 1 במרץ עבור הקלט: יום 60 בשנת 2000 נקבל את הפלט: 29 בפברואר (*) תזכורת: שנה היא מעוב רת אם היא מתחל קת ב- 4 אך לא ב- 100, או לחלופין אם היא מתחל קת ב- 400. 25
מערכים דו-ממדיים דוגמא (1) /* day_of_year.c -- K&R page 111 */ #include <stdio.h> int daytable[2][13] = 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ; /* day_of_year: set day of year from month and day */ int day_of_year (int year, int month, int day) int i, leap; leap = (((year % 4) == 0) && ((year % 100)!= 0)) ((year % 400) == 0); for (i=1; i<month; i++) day += daytable[leap][i]; return day;
מערכים דו-ממדיים דוגמא (1) #include <stdio.h> int daytable[2][13] = 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ; /* month_day: set month, day from day of year */ void month_day (int year, int yearday) int i, leap; leap = (((year % 4) == 0) && ((year % 100)!= 0)) ((year % 400) == 0); for (i=1; yearday>daytable[leap][i]; i++) yearday -= daytable[leap][i]; return???
מערכים דו-ממדיים דוגמא (1) #include <stdio.h> int daytable[2][13] = 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ; /* month_day: set month, day from day of year */ void month_day(int year, int yearday, int *pmonth, int *pday) int i, leap; leap = (((year % 4) == 0) && ((year % 100)!= 0)) ((year % 400) == 0); for (i=1; yearday>daytable[leap][i]; i++) yearday -= daytable[leap][i]; *pmonth=i; *pday=yearday; return;
חיבו ר מ טרי צ ו ת - ת זכו ר ת #include <stdio.h> #include <stdlib.h> #define SIZE 10 #define FALSE 0 #define TRUE 1 void ReadMatrix (int a[size][size], int row, int col); void CheckSize (int size); int add (int a[size][size], int row1, int col1, int b[size][size], int row2, int col2, int c[size][size]); void PrintMatrix (int a[size][size], int row, int col);
חיבו ר מ טרי צ ו ת - ת זכו ר ת int main() int a[size][size], b[size][size], c[size][size]; int row1, row2, col1, col2; printf("enter the number of rows and columns of the first matrix and the second matrix\n"); if (scanf("%d%d%d%d",&row1, &col1, &row2, &col2)!=4) printf("input error\n"); return 1; CheckSize(row1); CheckSize(col1); CheckSize(row2); CheckSize(col2); ReadMatrix(a,row1,col1); ReadMatrix(b,row2,col2); if (add(a,row1,col1,b,row2,col2,c)==false) printf("matrices cannot be added\n"); return 0; else printf("the result matrix:\n"); PrintMatrix(c,row1,col1); return 0;
חיבו ר מ טרי צ ו ת - שי פו ר int main() int a[size][size], b[size][size], c[size][size]; int row1, row2, col1, col2; ReadMatrix(a, &row1, &col1); ReadMatrix(b, &row2, &col2); if (add(a,row1,col1,b,row2,col2,c)==false) printf("matrices cannot be added\n"); return 0; else printf("the result matrix:\n"); PrintMatrix(c,row1,col1); return 0;
חיבו ר מ טרי צ ו ת - שי פו ר #include <stdio.h> #include <stdlib.h> #define SIZE 10 #define FALSE 0 #define TRUE 1 void ReadMatrix (int a[size][size], int *row, int *col); void CheckSize (int size); int add (int a[size][size], int row1, int col1, int b[size][size], int row2, int col2, int c[size][size]); void PrintMatrix (int a[size][size], int row, int col);
/* read a matrix*/ void ReadMatrix (int a[size][size], int *row, int *col) int i,j; printf("please enter the number of rows and columns:\n"); if (scanf("%d%d",row,col)!=2) printf("input error"); exit (1); CheckSize (*row); CheckSize (*col); printf("please enter matrix [%d][%d]\n",*row,*col); for (i=0; i < *row; i++) for (j=0; j < *col; j++) if(scanf("%d", &(a[i][j]))!=1) printf("input error"); exit (1); PrintMatrix(a, *row, *col); return; חיבור מטריצות - שיפור