מבוא למדעי המחשב מצביעים.

Slides:



Advertisements
Similar presentations
ממיבחניםC שאלות ++.
Advertisements

מבוא למדעי המחשב לתעשייה וניהול
מבוא למדעי המחשב לתעשייה וניהול דוגמאות ותרגול נוסף במערך חד ממדי הרצאה 12.
מבוא למדעי המחשב מערכים.
Pointers הרצאה קריטית. השאלות הפתוחות מה זה ה- & שמופיע ב scanf מדוע כשמעבירים מחרוזת ל scanf אין צורך ב & האם ניתן להכריז על מערך שגדלו אינו ידוע בתחילת.
1 מבוא למדעי המחשב הקצאה דינאמית. 2 הקצאת זיכרון דינאמית  כאשר אנו משתמשים במערכים, אנו מקצים אוטומטית את הזיכרון המקסימלי שנצטרך.  בפועל, אנו משתמשים.
תכנות מונחה עצמים Object Oriented Programming (OOP) אתגר מחזור ב'
1 מבוא למדעי המחשב משתנים. 2  סוגי משתנים בשפת C  ההבדלים בין סוגי המשתנים השונים.
תכנות תרגול 7 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
תכנות תרגול 9 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
תרגול 5 רקורסיות. רקורסיה קריאה של פונקציה לעצמה –באופן ישיר או באופן עקיף היתרון : תכנות של דברים מסובכים נעשה ברור ונוח יותר, מכיוון שזו למעשה צורת.
מבוא לשפת C חידות ונקודות חשובות נכתב על-ידי יורי פקלני. © כל הזכויות שמורות לטכניון – מכון טכנולוגי לישראל.
מבוא למדעי המחשב תרגול 8 - מחרוזות שעת קבלה : יום שני 11:00-12:00 דוא " ל :
מבוא למדעי המחשב תרגול מספר 3.
תכנות תרגול 9 שבוע : מערכים int a; a=5; int a[10]; a[2] = 5; 5 a a[0] a[1] a[2] a[9]  5 משתנה בודד מערך גישה למשתנה השלישי במערך.
תוכנה 1 - חזרה שולי לב יהודי 2 Arrays and Strings מערך - אוסף משתנים בעלי שם משותף. הפנייה לכל איבר נעשית ע ” י אינדקס. ב -C מערך מוגדר.
מבוא למדעי המחשב © אריק פרידמן 1 מצביעים כמערכים דוגמה.
1 מבוא למדעי המחשב ביטויים. 2 ביטויים expressions ביטויים (expressions) הינם יצורים תחביריים בעלי טיפוס וערך. הגדרה אינדוקטיבית של ביטויים : קבועים הם.
מבוא למדעי המחשב מחרוזות, מצביעים וכתובות
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
תכנות תרגול 10 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
מבוא כללי למדעי המחשב תרגול 3. לולאות while לולאות while while (condition) { loop body } במקרה של קיום התנאי מתבצע גוף הלולאה ברגע שהתנאי לא מתקיים נצא.
קורס תכנות – סימסטר ב ' תשס " ח שיעור שישי: מערכים
מבוא למדעי המחשב תרגול 6 - מערכים שעת קבלה : יום שני 11:00-12:00 דוא " ל :
תכנות תרגול 7 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא ידעו.
תכנות מונחה עצמים Object Oriented Programming (OOP) אתגר מחזור ב' Templates תבניות.
מבוא למדעי המחשב תרגול 3 שעת קבלה : יום שני 11:00-12:00 דוא " ל :
Last time on Clang משתנה: "פתק" המשמש את המחשב לשמירת מידע. לכל משתנה יש שם וטיפוס כללים לשמות משתנים –חייבים להכיל רק אותיות, מספרים ו '_' –חייבים להתחיל.
תוכנה 1 - תרגול שיעור 10 Pointers (2) שולי לב יהודי
מבוא כללי למדעי המחשב הקצאת זיכרון דינאמית
מתמטיקה בדידה תרגול 2.
1 מבוא למדעי המחשב סיבוכיות. 2 סיבוכיות - מוטיבציה סידרת פיבונאצ'י: long fibonacci (int n) { if (n == 1 || n == 2) return 1; else return (fibonacci(n-1)
1 מבוא למדעי המחשב backtracking. 2 מוטיבציה בעיית n המלכות: נתון: לוח שחמט בגודל. המטרה: לסדר על הלוח n מלכות כך שאף אחת לא תאיים על השנייה. דוגמא: עבור.
מבוא למדעי המחשב תרגול 12 – הקצאת זיכרון דינאמית שעת קבלה : יום שני 11:00-12:00 דוא " ל :
Sscanf example #include int main () { char sentence []="Rudolph is 12 years old"; char str [20]; int i; sscanf (sentence,"%s %*s %d",str,&i); printf ("%s.
תכנות תרגול 8 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
1 מבוא למדעי המחשב רקורסיה. 2 רקורסיה היא שיטה לפתרון בעיות המבוססת על העיקרון העומד ביסוד אינדוקציה מתמטית: אם ידועה הדרך לפתור בעיה עבור המקרים הבסיסיים.
הגדרת משתנים יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר.
קורס תכנות שיעור עשירי: מיונים, חיפושים, וקצת סיבוכיות חישוב.
תכנות מכוון עצמים ושפת ++C וויסאם חלילי. TODAY TOPICS: 1. Function Overloading & Default Parameters 2. Arguments By Reference 3. Multiple #include’s 4.
מבוא למדעי המחשב לתעשייה וניהול הרצאה 12. ספריות.
מבנים קרן כליף. ביחידה זו נלמד :  מהו מבנה (struct)  איתחול מבנה  השמת מבנים  השוואת מבנים  העברת מבנה לפונקציה  מבנה בתוך מבנה  מערך של מבנים.
Programming Pointers. נדגים היום בעזרת מצביעים העברת משתנים לפונקציה שמשנה אותם  פונקציה שמקבלת מצביעים לסמן תא בזיכרון  פונקציה שמחזירה מצביע מערך.
הגדרת משתנים יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016 יום שלישי 14 יוני 2016.
מחרוזות – הטיפוס String
מספרים אקראיים ניתן לייצר מספרים אקראיים ע"י הפונקציה int rand(void);
Programming Arrays.
מבוא למדעי המחשב לתעשייה וניהול
מבוא למדעי המחשב סיבוכיות.
מ- JAVA ל- C קרן כליף.
מערכים ומצביעים הקצאה דינאמית של מערכים דו-מימדיים
שיעור חמישי: מערכים ומחרוזות
מצביעים קרן כליף.
SQL בסיסי – הגדרה אינדוקטיבית
תירגול 14: מבני נתונים דינאמיים
Static and enum קרן כליף.
קורס תכנות – סמסטר ב' תשס"ח
הקצאות דינאמיות קרן כליף.
מבנים קרן כליף.
שיעור שישי: מחרוזות, מצביעים
פרוקטוז, C6H12O6 , חד-סוכר מיוחד
Introduction to Programming in C
מצביעים קרן כליף.
הקצאת זיכרון דינאמית מבוא כללי למדעי המחשב
ניתוח מערכות מידע תכנות ב C#
מבוא כללי למדעי המחשב תרגול 6
מערכים של מצביעים הקצאה דינאמית
Programming in C תרגול Introduction to C - Fall Amir Menczel.
תכנות מכוון עצמים ו- C++ יחידה 02 העמסת פונקציות, ערכי ברירת מחדל, enum, קימפול מותנה קרן כליף.
תירגול 8:מצביעים והקצאה דינאמית
Presentation transcript:

מבוא למדעי המחשב מצביעים

מצביעים (pointers) מצביע הוא משתנה המכיל כתובת של משתנה. אם p הוא מצביע ל- c, אזי תוכן המשתנה p הוא הכתובת של c, כלומר, מצביע על התא ששמו הוא c. c p

מצביעים - תחביר האופרטור האונארי & מחזיר את הכתובת של האובייקט בזיכרון. אובייקט ← משתנה, תא של מערך. לא קבוע ולא ביטוי. האופרטור האונארי * (dereference) לוקח מצביע ומחזיר את הערך (תוכן התא) שעליו מצביע המצביע. דוגמא: char c; char *p; p=&c; שימו לב: ב- C אין טיפוס למצביעים. בדוגמא הנ"ל p הוא מצביע ל- char, הוא אינו char. char תופס בדיוק בית אחד בזיכרון. לא כך הדבר לגבי מצביע ל- char.

מצביעים - דוגמא int x= 1, y=2, *ip, z[10]; x ip y z 1 2 int pointer

מצביעים - דוגמא int x= 1, y=2, *ip, z[10]; : ip=&x; x ip y z 1 1 2 2 int pointer

מצביעים - דוגמא int x= 1, y=2, *ip, z[10]; : ip=&x; y=*ip; x ip y z 1

מצביעים - דוגמא int x= 1, y=2, *ip, z[10]; : ip=&x; y=*ip; *ip=0; x ip 1

מצביעים - דוגמא int x= 1, y=2, *ip, z[10]; : ip=&x; y=*ip; *ip=0; 1

מצביעים - דוגמאות int *ip; *ip הוא מטיפוס int (ip הוא מצביע ל- int) double *fp; *fp הוא מטיפוס double (fp הוא מצביע ל- double) double func( char *); הצהרה על הפונקציה func, שמקבלת מצביע ל- char ומחזירה double.

אם ip ו- iq שניהם מצביעים ל- int כל מצביע מצביע לערכים מטיפוס מסוים ולהם בלבד. פוינטר לערכים מטיפוס מסוים לא יכול להצביע על ערכים מטיפוס אחר. המקום שאותו מצביע תופס בזכרון הוא זהה לכל המצביעים והוא תלוי מערכת הפעלה. הוא לא תלוי בגודל הערך שאליו מצביע הפוינטר. אם ip מצביע ל- x, אזי *ip יכול להופיע בכל מקום שבו יכול להופיע x: *ip+=10; *ip=*ip*2; ++*ip; ip=iq אם ip ו- iq שניהם מצביעים ל- int

העברת פרמטרים בשפת C העברת פרמטרים לפונקציות היא by value בלבד. פונקציה לא יכולה באופן ישיר להשפיע על ערכים בסביבה שקראה לה. תזכורת: /* swap: WRONG!!! */ void swap(int a, int b) { int temp; temp=a; a=b; b=temp; return; }

העברת פרמטרים באמצעות פוינטרים אפשר להעביר כתובות של משתנים מהסביבה הקוראת אל הפונקציה. /* 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 מפת הזיכרון: בפונקציה בסביבה הקוראת

פוינטרים ומערכים … בשפת C ישנו קשר הדוק בין מצביעים ומערכים: כל פעולה שקשורה להשגת ערך ממערך ניתן לבצע באמצעות מצביעים. החיסרון: פחות ברור. ערכו של ביטוי מטיפוס מערך הוא כתובת האיבר הראשון ([0]) של המערך. דוגמא: int a[10]; int *pa; pa=&(a[0]); x=*pa; x=*(pa+2); 1 2 9 … a: לאחר ההשמה ל- pa ול- a יש ערך זהה. לכן, ניתן לכתוב גם pa=a;

פוינטרים ומערכים באופן כללי: אם pa מצביע לתוך התא ה- i של a , אזי pa+j מצביע לתוך התא ה- i+j של a. לכן *(a+i) שקול ל- a[i] . כמו כן, &a[i] שקול ל- (a+i). פעולות כאלו על מצביעים אפשריות ללא תלות בטיפוס או בגודל של אברי המערך! i i+j … a: pa: pa+j

מערכים ופוינטרים שימו לב: יש הבדל בין שם של מערך ובין מצביע: מצביע הוא משתנה, לכן ניתן לבצע pa++; או pa=a; שם של מערך אינו משתנה, לכן a=pa; וגם a++; אינם חוקיים.

אריתמטיקה של פוינטרים אם p ו-q שני מצביעים המצביעים לאותו מערך ניתן להשוות ביניהם: < , <= , != , == , … p < q אם התא ש- p מצביע עליו נמצא לפני התא ש- q מצביע עליו. הוספה והחסרה של שלם: p+2 ← p + פעמיים הטיפוס ש- p מצביע עליו. כנ"ל לגבי p-1 , p++ וכו' השמה של מצביעים מאותו טיפוס: p=q רק אם p,q מצביעים לאותו טיפוס. אסור להציב int לתוך מצביע. הערך השלם היחיד שניתן להציב לתוך מצביע הוא אפס. משמעות האיפוס היא שהמצביע מאותחל, אך הוא אינו מצביע על שום תא בזיכרון. ניתן לרשום באופן שקול p=NULL;

העברת מערכים לפונקציות בכותרת הפונקציה יש להצהיר על טיפוס המערך ושמו הפורמלי, ללא אורך. בסביבה הקוראת יצוין שם המערך. int mystrlen (char s[ ]) { int n; for (n=0; s[n]!=‘\0’; n++); return n; }

העברת מערכים לפונקציות בכותרת הפונקציה יש להצהיר על טיפוס המערך ושמו הפורמלי, ללא אורך. בסביבה הקוראת יצוין שם המערך. הערך האקטואלי שיועבר לפונקציה הוא כתובת התחלת המערך. בתוך הפונקציה, הארגומנט הוא למעשה משתנה פנימי מאותחל, ולפיכך ניתן להתייחס אליו כאל מצביע. int mystrlen (char s[ ]) { int n; for (n=0; *s!=‘\0’; s++) n++; return n; } s מועבר by value ולכן ניתן להגדיל אותו ללא השפעה על הסביבה הקוראת!

העברת מערכים לפונקציות #include<stdio.h> int mystrlen (char s[ ]) { int n; for (n=0; *s!=‘\0’; s++) n++; return n; } 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)(; return 0; ניתן לכתוב באופן שקול: int mystrlen (char *s)

העברת מערכים לפונקציות כשפונקציה מקבלת מערך כפרמטר היא יכולה להתייחס אליו כאל מערך או כאל מצביע או בשני האופנים. ניתן להעביר חלק ממערך כפרמטר לפונקציה: strlen(&array[2]) strlen(array+2)

מערכים ↔ מצביעים int main() { char str[]=“hello"; char *ptr="hello"; printf("%s\n",str); printf("%s\n",ptr); ptr++; strcpy(str,"vv"); return 0; } מוקצה מקום למצביע והוא מאותחל להצביע אל קבוע. ניתן לשנות את המצביע אך לא את הקבוע. לא ניתן לבצע str++; לא ניתן לבצע strcpy(ptr,"vv");

strcpy – גרסאות שונות לאותה פונקציה /* strcpy: copy a string from t to s */ void strcpy(char *s, char *t) { int i=0; while ((s[i] = t[i]) != '\0') i++; } האלגוריתם הנאיבי 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') ; } קיצור כתיבה

strcpy – גרסאות שונות לאותה פונקציה void strcpy(char *s, char *t) { while ((*s++ = *t++) != '\0') ; } קיצור כתיבה void strcpy(char *s, char *t) { while (*s++ = *t++) ; } ההשוואה ל- ‘\0’ מיותרת

מערכים דו-ממדיים – דוגמא (1) נרצה לכתוב תכנית המבצעת המרה מיום בחודש ליום בשנה ולהיפך. למשל: ה- 1 במרץ הוא היום ה- 60 בשנה רגילה והיום ה- 61 בשנה מעוברת. לכן, עבור הקלט: יום 60 בשנת 2005 נקבל את הפלט: 1 במרץ עבור הקלט: יום 60 בשנת 2000 נקבל את הפלט: 29 בפברואר (*) תזכורת: שנה היא מעוברת אם היא מתחלקת ב- 4 אך לא ב- 100, או לחלופין אם היא מתחלקת ב- 400.

מערכים דו-ממדיים – דוגמא (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);

חיבור מטריצות - שיפור 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);

חיבור מטריצות - שיפור #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){ PrintMatrix(a, *row, *col); return;