שיעור שישי: מחרוזות, מצביעים

Slides:



Advertisements
Similar presentations
מבוא למדעי המחשב לתעשייה וניהול
Advertisements

Pointers הרצאה קריטית. השאלות הפתוחות מה זה ה- & שמופיע ב scanf מדוע כשמעבירים מחרוזת ל scanf אין צורך ב & האם ניתן להכריז על מערך שגדלו אינו ידוע בתחילת.
רקורסיות נושאי השיעור פתרון משוואות רקורסיביות שיטת ההצבה
תכנות תרגול 7 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
תכנות תרגול 9 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
תרגול 5 רקורסיות. רקורסיה קריאה של פונקציה לעצמה –באופן ישיר או באופן עקיף היתרון : תכנות של דברים מסובכים נעשה ברור ונוח יותר, מכיוון שזו למעשה צורת.
תכנות תרגול 4 שבוע : לולאות while לולאות while while (condition) { loop body } במקרה של קיום התנאי מתבצע גוף הלולאה ברגע שהתנאי לא מתקיים נצא.
תכנות תרגול 2 שבוע : שבוע שעבר כתבו תוכנית המגדירה שלושה משתנים מאתחלת אותם ל 1 2 ו 3 ומדפיסה את המכפלה שלהם את ההפרש שלהם ואת הסכום שלהם.
מבוא לשפת C חידות ונקודות חשובות נכתב על-ידי יורי פקלני. © כל הזכויות שמורות לטכניון – מכון טכנולוגי לישראל.
11 Introduction to Programming in C תרגול
מבוא למדעי המחשב תרגול 8 - מחרוזות שעת קבלה : יום שני 11:00-12:00 דוא " ל :
מבוא כללי למדעי המחשב תרגול. הבית האדום כתובת : רחוב קוקוריקו 2 הבית הירוק כתובת : רחוב קוקוריקו 4 הבית הצהוב כתובת : רחוב קוקוריקו 1 הבית הורוד כתובת.
תכנות תרגול 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 מערך מוגדר.
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
שיעור שישי: מערכים ופונקציות
תכנות תרגול 6 שבוע : תרגיל שורש של מספר מחושב לפי הסדרה הבאה : root 0 = 1 root n = root n-1 + a / root n-1 2 כאשר האיבר ה n של הסדרה הוא קירוב.
מבוא למדעי המחשב מחרוזות, מצביעים וכתובות
מבוא לשפת C תרגול 12: עוד רקורסיה
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
תכנות תרגול 6 שבוע : הגדרת פונקציות return-value-type function-name(parameter1, parameter2, …) הגדרת סוג הערכים שהפונקציה מחזירה שם הפונקציהרשימת.
Backpatching 1. תזכורת מתרגול קודם קוד ביניים - שפת הרביעיות שיטות לייצור קוד ביניים –שימוש בתכונת code –כתיבה ישירה ל-buffer של פקודות שיטות לתרגום מבני.
תכנות – שיעור 7. חזרה -מערכים נגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו מספר רב של משתנים זהים נגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו מספר רב של משתנים.
תכנות תרגול 10 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
מבוא כללי למדעי המחשב תרגול 3. לולאות while לולאות while while (condition) { loop body } במקרה של קיום התנאי מתבצע גוף הלולאה ברגע שהתנאי לא מתקיים נצא.
קורס תכנות – סימסטר ב ' תשס " ח שיעור שישי: מערכים
מבוא למדעי המחשב תרגול 6 - מערכים שעת קבלה : יום שני 11:00-12:00 דוא " ל :
תכנות תרגול 5 שבוע : הגדרת פונקציות return-value-type function-name(parameter1, parameter2, …) הגדרת סוג הערכים שהפונקציה מחזירה שם הפונקציהרשימת.
מערכים עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר int grade1, grade2, …, grade20; int grade1, grade2, …, grade20;
עקרון ההכלה וההדחה.
תכנות תרגול 4 שבוע : לולאות for לולאות for for (counter=1 ;counter
תכנות מונחה עצמים Object Oriented Programming (OOP) אתגר מחזור ב' Templates תבניות.
מבוא למדעי המחשב תרגול 3 שעת קבלה : יום שני 11:00-12:00 דוא " ל :
תוכנה 1 - תרגול שיעור 10 Pointers (2) שולי לב יהודי
מבוא כללי למדעי המחשב הקצאת זיכרון דינאמית
1 מבוא למדעי המחשב סיבוכיות. 2 סיבוכיות - מוטיבציה סידרת פיבונאצ'י: long fibonacci (int n) { if (n == 1 || n == 2) return 1; else return (fibonacci(n-1)
מבוא למדעי המחשב תרגול 12 – הקצאת זיכרון דינאמית שעת קבלה : יום שני 11:00-12:00 דוא " ל :
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
תכנות תרגול 8 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
Structure. מה לומדים היום ? דרך לבנות מבנה נתונים בסיסי – Structure מייצר " טיפוס " חדש מתאים כאשר רוצים לאגד כמה משתנים יחד דוגמאות : עובד : שם, טלפון,
מבנה נתונים ואלגוריתמים ) לשעבר - עיבוד מידע( ד"ר אבי רוזנפלד ד"ר אריאלה ריכרדסון.
קורס תכנות שיעור עשירי: מיונים, חיפושים, וקצת סיבוכיות חישוב.
תכנות מכוון עצמים ושפת ++C וויסאם חלילי. TODAY TOPICS: 1. Function Overloading & Default Parameters 2. Arguments By Reference 3. Multiple #include’s 4.
מבנים קרן כליף. ביחידה זו נלמד :  מהו מבנה (struct)  איתחול מבנה  השמת מבנים  השוואת מבנים  העברת מבנה לפונקציה  מבנה בתוך מבנה  מערך של מבנים.
מבנה נתונים ואלגוריתמים ) לשעבר - עיבוד מידע( ד"ר אבי רוזנפלד ד"ר אריאלה ריכרדסון.
Programming Pointers. נדגים היום בעזרת מצביעים העברת משתנים לפונקציה שמשנה אותם  פונקציה שמקבלת מצביעים לסמן תא בזיכרון  פונקציה שמחזירה מצביע מערך.
מחרוזות – הטיפוס String
מספרים אקראיים ניתן לייצר מספרים אקראיים ע"י הפונקציה int rand(void);
Programming Arrays.
מבוא למדעי המחשב לתעשייה וניהול
מבוא למדעי המחשב סיבוכיות.
מחרוזות קרן כליף.
שיעור חמישי: מערכים ומחרוזות
מצביעים קרן כליף.
קורס תכנות – סמסטר ב' תשס"ח
מצביעים קרן כליף.
מבוא כללי למדעי המחשב פונקציות
הקצאת זיכרון דינאמית מבוא כללי למדעי המחשב
מבוא כללי למדעי המחשב תרגול 4
מבוא כללי למדעי המחשב שיעור 2
מבוא כללי למדעי המחשב תרגול 6
סוגי משתנים קרן כליף.
מחרוזות קרן כליף.
מערכים של מצביעים הקצאה דינאמית
Programming in C תרגול Introduction to C - Fall Amir Menczel.
מבוא למדעי המחשב מצביעים.
תירגול 8:מצביעים והקצאה דינאמית
שיעור עשירי: מיונים, חיפושים, וקצת סיבוכיות חישוב
Computer Programming תרגול 3 Summer 2016
Engineering Programming A
Presentation transcript:

שיעור שישי: מחרוזות, מצביעים קורס תכנות שיעור שישי: מחרוזות, מצביעים

מערכים אוסף סדור של משתנים מאותו סוג המשתנים נמצאים ברצף בזיכרון העברת מערך לפונקציה Define רקורסיה במערך מערכים דו מימדיים

char str[20] = "hello world"; מחרוזות מהי מחרוזת? רצף של תוים ייצוג ב-C ההבדל ממערך מחרוזת כפרמטר לפונקציה char str[20] = "hello world"; h e l o w r d \0 str[0] str[19] סוף המחרוזת

קלט/פלט של מחרוזת שלמה אפשר לקלוט מחרוזות שלמה ב- scanf באמצעות הקידוד %s למשל: הקלט יהיה רק עד רווח או ירידת-שורה (כלומר זו דרך לקלוט מילים) התו ‘\0’ מוכנס אוטומטית ע"י scanf אחרי תווי המחרוזת שנקלטה שימו לב שלא רושמים את הסימן & ב- scanf של מחרוזת שלמה. שימו לב: באחריות המשתמש לדאוג שיש במערך מספיק מקום (אחרת התכנית תעוף) אפשר להגביל את מספר התווים שנקראים: דרך אחרת להגבלת מספר התווים היא לקלוט תו-תו בלולאה char answer[100]; scanf("%s", answer); char answer[100]; scanf("%99s", answer);

פלט של מחרוזת שלמה נשתמש ב printf להדפסת המחרוזת יודפסו התווים מתחילת המערך ועד לתו ‘\0’ printf("%s", answer);

דוגמא: תוכנית שמרווחת מילה #include <stdio.h> #define WORD_SIZE 30 int main() } char word[WORD_SIZE + 1], spaced_word[WORD_SIZE * 2 + 1]; int i; scanf("%29s", word); for (i = 0; word[i] != '\0'; i++) { spaced_word[i * 2] = word[i]; spaced_word[i * 2 + 1] = ' '; spaced_word[i * 2] = '\0' ; printf("The word after spacing: %s\n", spaced_word); return 0; h e l o \0 h e l o \0 ‘ ‘

דוגמא: העתקה של מחרוזת #include <stdio.h> #define WORD_SIZE 20 void string_copy(const char source[], char destination[]) } int i; for (i = 0; source[i] != '\0'; i++) destination[i] = source[i]; destination[i] = '\0'; int main() char text[WORD_SIZE + 1], copy[WORD_SIZE + 1]; scanf("%s", text); string_copy(text, copy); printf("%s\n", copy); return 0; {

פעולות על מחרוזות מאחר ומחרוזות ממומשות בעזרת מערכים לא נוכל לבצע פעולות על מחרוזת שלמה, כמו השוואה או השמה. נבצע פעולות כאלו בעזרת הפונקציות המוגדרות בספרייה - string.h. השוואת מחרוזות strcmp העתקת מחרוזות strcpy שירשור מחרוזות strcat ועוד ...

הספריה string.h – פונקציות לדוגמה מציאת אורך של מחרוזת: השוואה לקסיקוגרפית בין מחרוזות: מחזירה 0 אם שתי המחרוזות זהות. מספר חיובי אם הראשונה קודמת לשנייה. מספר שלילי אם השנייה קודמת לראשונה. העתקת מחרוזת למחרוזת אחרת: שרשור מחרוזת למחרוזת אחרת: int strlen( const char str[] ); int strcmp( const char str1[], const char str1[] ); char* strcpy( char target[], const char source[] ); char* strcat( char target[], const char source[] );

כל עוד אותו התו ולא הסתיימו המחרוזות דוגמה למימוש strcmp int my_strcmp(const char str1[], const char str2[]) { int i=0; while ( (str1[i] == str2[i]) && (str1[i] != '\0') ) i++; return (str2[i] – str1[i]); } כל עוד אותו התו ולא הסתיימו המחרוזות

חישוב אורך מחרוזת ברקורסיה הגדרה רקורסיבית של אורך מחרוזת: אם התו הראשון הוא ‘\0’  אורך המחרוזת str הוא: 0 אחרת – אורך מחרוזת str הוא: 1 + (אורך המחרוזת str החל מהתו השני) int strlen_rec(char str[], int index) } if (str[index] == '\0') return 0; return 1 + strlen_rec(str, index + 1); {

מה עושה התכנית הבאה? #include <stdio.h> #include <string.h> int main() { int mccain_votes = 0 , obama_votes=0, loopFlag = 1; char vote[10] = {0}; while (loopFlag) scanf(“%s”, vote); if (strcmp(vote, “Mccain”)==0) mccain_votes++; else if ( strcmp(vote, “Obama”)==0 ) obama_votes++; else if (strcmp(vote, “Stop”)==0) loopFlag = 0; else printf(“Wrong vote!\n”) } printf(“Mccain: %d votes\nObama: %d votes\n”, mccain_votes, obama_votes); return 0;

int atoi( const char str[] ); double atof( const char str[] ); תרגום מחרוזת למספר פונקציות לתרגום מחרוזות למספרים בספריה stdlib.h תרגום למספר שלם: תרגום למספר ממשי: למשל: int atoi( const char str[] ); double atof( const char str[] ); int num = atoi(“12345”);

שאלה ממבחן (בתלות בזמן) סמסטר א' תשס"ז

שאלה ממבחן סעיף א' כתבו פונקציה בעלת המפרט (prototype) הבא: void kth_word (char words[], int k, char kth[]); words היא מחרוזת המכילה מילים באנגלית בין כל שתי מילים סמוכות יש תו-רווח אחד בדיוק kהוא מספר שלם חיובי kth היא מחרוזת נוספת בסיום הפונקציה, המחרוזת kth צריכה להיות המילה ה-k-ית מבין המילים שהועברו ב-words אם יש ב-words פחות מ- k מילים, הפונקציה תשים ב-kth מחרוזת ריקה (תו '0\') הניחו שב- kth יש מספיק מקום לצורך ההעתקה

כיצד נממש? עוברים על המחרוזת words תוך כדי מעבר על המחרוזת: סופרים רווחים עוצרים במקרה שקורה אחד מהשניים: הגענו לסוף המחרוזת (כלומר ל-‘\0’). הגענו לתחילת המילה ה-k (כלומר מצאנו את הרווח ה k-1). אם הגענו לסוף המחרוזת, מכניסים '0\' לתא הראשון ב-kth. אם הגענו לרווח ה- (k-1) : לולאה עד תו הרווח הבא או עד '0\'. מעתיקים כל תו ב- words ל- kth.

פתרון חלק א' void kth_word (char words[], int k, char kth[]) { int j=0, i=0, word_counter=1; while ((words[i]!=‘\0’) && (word_counter < k)) { if (words[i]==‘ ‘) word_counter++; i++; } if (words[i]==‘\0’) kth[0]=‘\0’; else { for (j=0; words[i]!=‘\0’ && words[i]!=‘ ‘; i++,j++) kth[j]=words[i]; kth[j]=‘\0’; נמצא את האינדקס i בו מתחילה המילה ה- k אם אורך המשפט קצר מ- k מילים, נחזיר מחרוזת ריקה אחרת, נעתיק את המילה ה- k למחרוזת kth

שאלה ממבחן סמסטר א' תשס"ז

שאלה ממבחן לדוגמא: סעיף ב' כיתבו תוכנית הקולטת: משפט באנגלית, באורך 300 תווים לכל היותר ,שבסיומו מוקלד Enter. מילה באנגלית, באורך 30 אותיות לכל היותר, שבסיומה מוקלד Enter. על התוכנית להדפיס את מספר הפעמים שהמילה הזו מופיעה במשפט, בהנחה שהמשפט מכיל רק מילים באנגלית ובין כל שתי מילים סמוכות יש תו-רווח יחיד. לדוגמא: אם המשפט הוא "I am what I am" והמילה היא "am" אז התוכנית תדפיס 2 אם המשפט הוא "I am what I am" והמילה היא "at" אז התוכנית תדפיס 0 הערות: ניתן להניח שאורך כל מילה במשפט הוא 30 אותיות לכל היותר. ניתן להניח שהקלט תקין, וגם שהמשתמש יודע איזה קלט להכניס.

כיצד נממש? נקלוט משפט לתוך מחרוזת. נקלוט מילה לתוך מחרוזת נוספת. נשתמש בפונקציה מהסעיף הקודם: נרוץ בלולאה על מיקום המילה במשפט: נקרא לפונקציה kth_word עם הפרמטרים: המשפט שקלטנו מספר המילה הנוכחית מחרוזת ריקה אליה תועתק המילה אם המילה שחזרה היא מחרוזת ריקה, נסיים אם לא, נשווה אותה למילה שנקלטה אם המילים זהות, נקדם מונה. void kth_word (char words[], int k, char kth[])

פתרון חלק ב' לולאה על המילים במשפט #include<string.h> #define WORD_SIZE 30 #define SENTENCE_SIZE 300   int main() { char sentence[SIZE+1], word[W_SIZE+1], kth[W_SIZE+1]; int k=1, count=0; gets(sentence); gets(word); kth_word(sentence,k,kth)); while(kth[0]!='\0') if (strcmp(kth, word) == 0) count++; k++; } printf("The word appeared %d times in the sentence\n", count); return 0; לולאה על המילים במשפט לכל מילה במשפט – נבדוק אם היא זהה למילה word נדפיס את התוצאה

כתובות ומצביעים מהן כתובות בזיכרון פעולות עם כתובות מהם מצביעים ומה אפשר לעשות איתם מצביעים ומערכים

זיכרון - תזכורת רצף (מערך) של בתים (bytes) כל בית מזוהה על ידי כתובתו הכתובת היא האינדקס של הבית במערך הכתובת היא מספר הכתובת 0 שמורה ואינה מקום חוקי בזיכרון 1 2 3 4 5 232 …

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

כתובות בזיכרון שם כתובת x 784658 c 26537 10 'a' 784658 26537 int main() { int x = 10; char c = ‘a’; ... return 0; } 10 'a' 784658 26537 שם כתובת x 784658 c 26537

כתובות בזיכרון – גודל המשתנה בטבלת הכתובות נשמר נתון נוסף - מספר התאים שמשמשים לייצוג המשתנה שהוגדר תלוי בטיפוס המשתנה

כתובות בזכרון האופרטור & מחזיר את כתובת המשתנה בזיכרון. שם כתובת x 784658 c 26537 &x יחזיר 784658 &c יחזיר 26537

כיצד נשמור כתובות? מספרים שלמים נשמור במשתנה מטיפוס int מספרים ממשיים נשמור במשתנה מטיפוס double וכתובות? משתנה שמחזיק כתובת נקרא מצביע (pointer) טיפוס המצביע תלוי בטיפוס המשתנה שאליו הוא מצביע

הגדרת מצביע (pointer variable) למשתנה מצביע יש שם לפני השם תופיע כוכבית * כדי לסמן שזהו מצביע הטיפוס מתאר את המשתנה שמצביעים עליו type *variable_name; מצביע ל char char *str; int *ptr; double d, *pd; מצביע ל int double ומצביע ל double

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

מצביעים וכתובות שם כתובת ערך x 784658 10 c 26537 'a' iptr 43745 cptr int main() { int x = 10; char c = 'a'; int *iptr = &x; char *cptr = &c; ... return 0; } שם כתובת ערך x 784658 10 c 26537 'a' iptr 43745 cptr 32545

מצביעים וכתובות 10 'a' x c iptr cptr int main() { int x = 10; char c = 'a'; int *iptr = &x; char *cptr = &c; ... return 0; } 10 'a' x c iptr cptr

האופרטור * (dereference) int main() { int x = 10; char c = 'a'; int *iptr = &x; char *cptr = &c; *iptr = 30; *cptr = 'A'; ... return 0; } ניגש לזיכרון הנמצא בכתובת מסוימת 10 30 'a' 'A' x c iptr cptr

✘ ✘ ✘ הגבלות על פעולות לא ניתן לשנות כתובת של משתנה לקבועים ולביטויים אין כתובת אסור לגשת לזיכרון שלא שייך לנו ✘ &i = 6000; &i = &num; ✘ i = &5; i = &(6*a+1); ✘ *(4000) = 5;

מצביע ל"כלום" NULL מסמל כתובת לא חוקית קבוע המוגדר בספריה stdlib.h כדי לסמן שמצביע אינו מצביע למשתנה ניתן לו את הערך NULL נוכל לבדוק אם המצביע מכיל כתובת חוקית int *my_pointer = NULL; if (my_pointer == NULL) { ... }

מצביע כללי נוכל להחזיק מצביע (כתובת) ללא ציון הטיפוס המוצבע קיימות מגבלות על השימוש ב void pointer לא ניתן לגשת למשתנה בכתובת בעזרת האופרטור * לא ניתן לבצע פעולות אריתמטיות משמש להחזקת כתובת שנידרש להמיר אותה לטיפוס ספציפי כדי להשתמש בה void *my_void_pointer = NULL;

סיכום ביניים משתנה מוגדר ע"י טיפוס ושם (int k) משתנה מצביע מוגדר ע"י טיפוס ושם (int *ptr) הכוכבית מסמנת שהמשתנה הוא מצביע והטיפוס מציין את הטיפוס של המשתנה שמצביעים אליו אחרי שהגדרנו משתנה נוכל להשיג את כתובתו בעזרת האופרטור & ניתן לגשת לערך שהמצביע מצביע עליו בעזרת האופרטור *

הדפסת מצביעים int x = 5; int *pointer = &x; printf(“address: %p\n", pointer); ההדפסה של כתובת תהיה בבסיס הקסדצימלי (בסיס 16) בספירה ההקסדצימלית הספרות מ-0 עד 9 נראית כמו דומותיהן העשרוניות, והספרות הבאות הן האותיות מ-A , המייצגת 10, עד F , המייצגת 15. address = 0012FF60

אריתמטיקה של מצביעים ניתן לבצע פעולות אריתמטיות על מצביעים כתובות הן מספרים קיימים הבדלים בין פעולות על מספרים ובין פעולות על מצביעים output: char *cptr = (char*) 2; printf("cptr before: %p\n", cptr); cptr++; printf("and after: %p\n", cptr); cptr before: 00000002 and after: 00000003

אריתמטיקה של מצביעים (המשך) נחליף את המצביע מ char* ל int* output: מקדם את המצביע למשתנה הבא תלוי בטיפוס המשתנה לא ניתן לבצע פעולות אריתמטיות על void* int *iptr = (int*) 2; printf("iptr before: %p\n", iptr); cptr++; printf("and after: %p\n", iptr); iptr before: 00000002 and after: 00000006

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

מערכים כשמגדירים מערך יוקצה זיכרון רציף המספיק לעשרה משתנים מטיפוס int array הוא הכתובת של התא הראשון במערך array שקול ל &array[0] אי אפשר לשנות כתובת של מערך int array[10]; ✘ array = (int*) 2;

השמה בין מערך למצביע מצביע מכיל כתובת, שם המערך הוא כתובת ניתן לבצע השמה בין המערך ומצביע לאחר ההשמה ניתן להשתמש במצביע כאילו היה שם המערך ניתן להשתמש במערך כאילו היה מצביע int *ptr; int array[10]; ptr = array; ptr[2] = 25; *array = 4;

כיצד זה עובד הקומפיילר מתרגם גישה לאיבר במערך לגישה לכתובת האיבר המתאים הפקודה array[5] = 100 תתורגם ל - *(array + 5) = 100 הפעולות הבאות הן שקולות array[5] = 100; *(array + 5) = 100; *(ptr + 5) = 100;

שימוש בלולאות מעבר על איברי המערך בעזרת אינדקס int i, array[10], *ptr; מעבר על איברי המערך בעזרת אינדקס גישה לפי כתובת יחסית להתחלה גישה בעזרת מצביע for (i = 0; i < 10; i++) { printf("%d ", array[i]); } for (i = 0; i < 10; i++) { printf("%d ", *(array + i)); } for (ptr = array; ptr < &array[10]; ptr++) { printf("%d ", *ptr); }

עוד דוגמא: מה יודפס? 89 array 45 67 89 array_ptr int array[] = {45, 67, 89}; int *array_ptr = &array[1]; printf("%d\n", array_ptr[1]); 89 array 45 67 89 array_ptr

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

? Swap כפונקציה ראינו כבר קוד לביצוע פעולת ההחלפה (Swap) כיצד נהפוך קטע קוד זה לפונקציה? int temp, i, j; ... temp = i; i = j; j = temp; void swap(int i, int j) { int temp; temp = i; i = j; j = temp; } ?

פתרון בעזרת מצביעים נעביר לפונקציה את הכתובת של המשתנים במקום את ערכי המשתנים void swap(int *pi, int *pj) { int temp; temp = *pi; *pi = *pj; *pj = temp; }

דוגמא 10 20 20 10 x y pi pj void swap(int *pi, int *pj) { int temp = *pi; *pi = *pj; *pj = temp; } int main() int x = 10; int y = 20; swap(&x, &y); printf("x is %d – y is %d\n", x, y ); return 0; 10 20 20 10 x y pi pj

דוגמא שפגשנו כבר הפונקציה scanf מקבלת את כתובת המשתנה שאליו יוכנס הקלט המשתנה grade לא מוגדר בפונקציה scanf הפונקציה scanf מקבלת את הכתובת של המשתנה בזיכרון int main() { int grade; ... scanf("%d“, &grade); return 0; }

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

מצביע כערך מוחזר &i = 0012FF60, &j = 0012FF54, max_ptr = 0012FF54 #include <stdio.h> int* max(int *a, int *b) } return (*a > *b) ? a : b; { int main() int i = 10, j = 20; int *max_ptr = max(&i, &j); printf("&i = %p, &j = %p, max_ptr = %p\n", &i, &j, max_ptr); return 0; &i = 0012FF60, &j = 0012FF54, max_ptr = 0012FF54

✘ שימו לב! אין להחזיר את הכתובת של משתנה לוקאלי משתנים לוקאליים אינם קיימים לאחר שהפונקציה הסתיימה int* pointer_to_zero() } int zero = 0; return &zero; { ✘

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

הגדרות שקולות void init_array(int array[], int size) } int i; for (i = 0; i < size; i++) array[i] = 0; void init_array(int *array, int size)

הגדרות שקולות void init_array(int *array, int size) } int *ptr; for (ptr = array; ptr < &array[size]; ptr++) *ptr = 0;

מצביעים ומחרוזות מימוש strlen בעזרת מצביע int strlen(const char* str) } int len = 0; if (str == NULL) return -1; /* Error! */ while (*str != '\0') { len++; str++; return len;

חיפוש תו במחרוזת הפונקציה strchr מחפשת תו במחרוזת מוגדרת ב string.h מחזירה מצביע למופע הראשון של התו או NULL אם לא קיים char* strchr(const char* str, char c) } if (str == NULL) return NULL; while (*str != '\0') { if (*str == c) return str; str++;

הפונקציה strstr חיפוש תת-מחרוזת char* strstr(const char *haystack, const char *needle) { int needlelen; if (*needle == '\0') return (char *) haystack; needlelen = strlen(needle); for (; (haystack = strchr(haystack, *needle)) != NULL; haystack++) if (strncmp(haystack, needle, needlelen) == 0) return NULL; }

הפונקציה strstr printf(“res=%p\n”,res); printf(“res=%s\n”,res); char str[] = “Ding Dong”; char *res = strstr(str,”Don”); D i n g o \0 6500 str res printf(“res=%p\n”,res); printf(“res=%s\n”,res); res=6505 res=Dong

דוגמא – כמה פעמים מופיעה מילה בשיר int main() { const char *rhyme = "Humpty Dumpty sat on a wall,\n " "Humpty Dumpty had a great fall.\n " "All the king's horses,\n" "And all the king's men,\n" "Couldn't put Humpty together again.\n"; const char *humpty = "Humpty"; char *ptr = NULL; int count = 0; for (ptr = strstr(rhyme, humpty); ptr != NULL; ptr = strstr(ptr + 1, humpty)) { count++; } printf("The string %s appears %d times\n", humpty, count); return 0;

תרגיל לבית: strcpyבשורה אחת char* strcpy(char *dst, const char *src) } char *s = dst; while (*dst++ = *src++); return s;