Programming in C תרגול 8 1 1 Introduction to C - Fall 2010 - Amir Menczel.

Slides:



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

קורס תכנות שיעור שנים-עשר: ניהול זיכרון 1. הקצאת זיכרון דינאמית עד עכשיו עשינו "הקצאה סטטית" הגדרנו את משתני התוכנית כבר כשכתבנו אותה הקומפיילר הקצה עבורם.
Pointers הרצאה קריטית. השאלות הפתוחות מה זה ה- & שמופיע ב scanf מדוע כשמעבירים מחרוזת ל scanf אין צורך ב & האם ניתן להכריז על מערך שגדלו אינו ידוע בתחילת.
1 מבוא למדעי המחשב הקצאה דינאמית. 2 הקצאת זיכרון דינאמית  כאשר אנו משתמשים במערכים, אנו מקצים אוטומטית את הזיכרון המקסימלי שנצטרך.  בפועל, אנו משתמשים.
תכנות תרגול 7 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
תכנות תרגול 9 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
תכנות תרגול 6 שבוע : חישוב e זוהי הנוסחא לחישוב e נראה כיצד לתרגם אותה לפונקציה n n.
תרגול 5 רקורסיות. רקורסיה קריאה של פונקציה לעצמה –באופן ישיר או באופן עקיף היתרון : תכנות של דברים מסובכים נעשה ברור ונוח יותר, מכיוון שזו למעשה צורת.
תכנות תרגול 4 שבוע : לולאות while לולאות while while (condition) { loop body } במקרה של קיום התנאי מתבצע גוף הלולאה ברגע שהתנאי לא מתקיים נצא.
מבוא לשפת 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 תרגול
מבוא למדעי המחשב © אריק פרידמן 1 מצביעים כמערכים דוגמה.
1 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
1 מבוא למדעי המחשב מבנה של תכנית. 2 מבנה של תכנית – חלוקה לקבצים  תכנית בשפת C הינה אוסף של הגדרות של:  משתנים (חיצוניים)  פונקציות  ניתן לפרוש תכנית.
תכנות תרגול 6 שבוע : תרגיל שורש של מספר מחושב לפי הסדרה הבאה : root 0 = 1 root n = root n-1 + a / root n-1 2 כאשר האיבר ה n של הסדרה הוא קירוב.
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, …) הגדרת סוג הערכים שהפונקציה מחזירה שם הפונקציהרשימת.
תכנות – שיעור 7. חזרה -מערכים נגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו מספר רב של משתנים זהים נגדיר בעזרתו קבוצת משתנים כאשר יהיה לנו מספר רב של משתנים.
תכנות תרגול 10 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
1 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
מבוא כללי למדעי המחשב תרגול 3. לולאות while לולאות while while (condition) { loop body } במקרה של קיום התנאי מתבצע גוף הלולאה ברגע שהתנאי לא מתקיים נצא.
מבוא למדעי המחשב תרגול 6 - מערכים שעת קבלה : יום שני 11:00-12:00 דוא " ל :
תכנות תרגול 7 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא ידעו.
תכנות תרגול 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
מבוא למדעי המחשב תרגול 3 שעת קבלה : יום שני 11:00-12:00 דוא " ל :
תוכנה 1 - תרגול שיעור 10 Pointers (2) שולי לב יהודי
מבוא כללי למדעי המחשב הקצאת זיכרון דינאמית
מתמטיקה בדידה תרגול 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 תרגול
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 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
הגדרת משתנים יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר 2015 יום שישי 18 ספטמבר.
Methods public class Demonstrate { public static void main (String argv[]) { public static void main (String argv[]) { int script = 6, acting = 9, directing.
קורס תכנות שיעור שמיני: הקצאת זיכרון דינאמית, הצצה לייצוג ועיבוד תמונות 1.
קורס תכנות שיעור עשירי: מיונים, חיפושים, וקצת סיבוכיות חישוב.
תכנות מכוון עצמים ושפת ++C וויסאם חלילי. TODAY TOPICS: 1. Function Overloading & Default Parameters 2. Arguments By Reference 3. Multiple #include’s 4.
1 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
מספרים אקראיים ניתן לייצר מספרים אקראיים ע"י הפונקציה int rand(void);
Programming Arrays.
Computer Architecture and Assembly Language
Programming Languages and Paradigms
מצביעים והקצאה דינאמית
מערכים ומצביעים הקצאה דינאמית של מערכים דו-מימדיים
מצביעים, הקצאה דינאמית ומבנים
Introduction to Programming in C
מצביעים קרן כליף.
Introduction to Programming in C
הקצאות דינאמיות קרן כליף.
שיעור שישי: מחרוזות, מצביעים
Introduction to Programming in C
מצביעים קרן כליף.
הקצאת זיכרון דינאמית מבוא כללי למדעי המחשב
Computer Programming תרגול 9 Summer 2016
מבוא כללי למדעי המחשב תרגול 4
תרגול 8 תחומי הכרה פונקציות
מבוא כללי למדעי המחשב תרגול 6
מערכים של מצביעים הקצאה דינאמית
מבוא למדעי המחשב מצביעים.
תירגול 8:מצביעים והקצאה דינאמית
Computer Programming תרגול 3 Summer 2016
Engineering Programming A
Presentation transcript:

Programming in C תרגול 8 1 1 Introduction to C - Fall 2010 - Amir Menczel

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

מצביעים תאור הזיכרון של המחשב: ניתן לחשוב על זיכרון המחשב כעל רצף של תאים, כל אחד בגודל בית (byte) כאשר כל בית בגודל של 8 סיביות (bits). כל תא בזיכרון מזוהה ע"י ערך מספרי המתאר את מיקומו המדוייק. ערך זה הינו הכתובת של התא בזיכרון (memory address). למשל, אם נגדיר את המשתנים הבאים: char var1; // storage for type char is 1 byte. double var2; // storage for type char is 8 byte. int var3; // storage for type char is 4 byte. כתובת של משתנה הינה הכתובת של הבית הראשון ברצף הבתים שמשתנה זה תופס בזיכרון.  ברגע שנצהיר על משתנים כמצביעים, נוכל להציב לתוכם כתובות של משתנים. לדוגמא:   int x = 200 ; int p; /*Declaration of a pointer “p” that is of type “int *”.*/ p=&x; /*Assign the address of “x” to be the value of “p”.*/ בשלב זה המשתנה p מכיל את הכתובת של המשתנה x. var1 var2 var3 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119

אופרטורים מצביעים האופרטור & אם x הוא משתנה אזי &x היא כתובת הזיכרון של x, כלומר האופרטור & מציין "כתובתו של…". מצביעים (pointers): מצביע הינו משתנה שהערך שלו הוא כתובת של משתנה כלשהו. במילים אחרות, מצביע הינו משתנה שמצביע למשתנה אחר. אם נרצה להגדיר את p כמצביע למשתנה כלשהו מטיפוסint , שורת ההצהרה תיראה כך: int *p; באופן כללי, תבנית הצהרה על מצביעים הינה: <variable-type> *<variable name>; האופרטור  האופרטור  הינו אופרטור שפועל על מצביעים. למשל עבור הדוגמה הקודמת *p שקול ל-x. כלומר *p הוא התוכן של תא הזיכרון ש-p מצביע עליו.

דוגמאות int x = 200 ; int p; /*Declaration of a pointer “p” that is of type “int *”.*/ p=&x; /*Assign the address of “x” to be the value of “p”.*/ p=500; // < שקול= => x=500;. זהירות בעת שימוש במצביעים: כשמצהירים על מצביע p אין הוא בהכרח מצביע על ערך חוקי! int *pi; *pi = 100; /*wrong!!!!*/ טעות זו ידועה בשם segmentation fault ,זוהי אינה שגיאת קומפילציה, אלא, שגיאה בזמן ריצה.

העברת מצביעים כפרמטרים לפונקציה מכיוון שמצביעים הם משתנים לכל דבר, ניתן להעביר את ערכיהם בתור פרמטרים לפונקציות. מנגנון זה מאפשר לפונקציה נקראת לשנות את ערכיהם של משתנים בסביבה הקוראת. לדוגמא ,נכתוב פונקציה אשר מחליפה בין ערכיהם של זוג משתנים מטיפוס int: void swap(int a, int b){ int tmp = a; a = *b; *b = tmp; } כתובת של מערך שמו של מערך דומה למצביע המייצג את הכתובת של האיבר הראשון בתוך המערך. על אף הדמיון, חשוב לזכור ששם של מערך אינו מצביע שכן הוא מייצג כתובת קבועה, לא ניתן לשנותה במהלך התוכנית.

דוגמא נוספת #include <stdio.h> void main(){ int x , *px; /*Define a variable of type int named "x" and a variable of type pointer to int named "px".*/ int y, *py ; px=&x; /*Assign the address of "x" to be the value of "px".*/ py=&y; scanf("%d%d",px,py); /*Read two integers values from the input and assign them to "x" and "y". Make sure that you understand why!!! */ printf("x=%d , y=%d\n",*px,*py); /*Print the values of the x and y which are the variables pointed to by px and py. */

תרגיל 1 שאלה 1: נתונה השורה הבאה של תכנית בשפת C: int a, *b, c[4]; סמנו את כל ההוראות שאינן יכולות להופיע באופן חוקי בהמשך התכנית. הוראה חוקית היא הוראה נכונה מבחינה תחבירית שעוברת קומפילציה.   א) *(c+3) = 8; ב) a = *(c + *b); ג) *(c++) = 12; ד) c = b; ה) b = c; ו) a = (*c)++; ז) *(b+1) = (*c)++; ח) a = *b - *c; ט) *c = *(b++); י) *(b++)= *(&a); יא) *b==2=a; יב) c[3] = *b == 2; int x=2, y=5; unsigned int addr; addr = (unsigned int) &x; y = *((int *)addr); y=2

תרגיל 1 שאלה 1: נתונה השורה הבאה של תכנית בשפת C: int a, *b, c[4]; סמנו את כל ההוראות שאינן יכולות להופיע באופן חוקי בהמשך התכנית. הוראה חוקית היא הוראה נכונה מבחינה תחבירית שעוברת קומפילציה.   א) *(c+3) = 8; // c[2]=8; ב) a = *(c + *b); ג) *(c++) = 12; /*Compilation Error: error C2105: '++' needs l-value*/ ד) c = b; /*Compilation Error: error C2106: '=' : left operand must be l-value*/ ה) b = c; ו) a = (*c)++; ז) *(b+1) = (*c)++; ח) a = *b - *c; ט) *c = *(b++); י) *(b++)= *(&a); יא) *b==2=a; /*Compilation Error: error C2106: '=' : left operand must be l-value*/ יב) c[3] = *b == 2;

מה תדפיס התוכנית הבאה ? char * func1 () { char A [5]= "1234"; return A; { char * func2 () { char A [5]= "abcd"; } void main () { char * Arr1, * Arr2; Arr1=func1(); Arr2=func2(); printf("Arr1 is %s, Arr2 is %s\n", Arr1, Arr2); “Arr1 is 1234, Arr2 is abcd” “Arr1 is abcd, Arr2 is abcd” התוכנית תרוץ אך תדפיס ערכים לא צפויים עבור Arr1 ו Arr2 נקבל הודעת שגיאה בקומפילציה נקבל הודעת שגיאה בזמן ריצה

תרגיל 2 תוכנית לחישוב אורך המחרוזת עם שימוש במצביעים: #include <stdio.h> #define MAX_LENGTH 80 int my_strlen (char *s){ char *p = s; while (*p) p++; return p - s; } void main(){ char str[MAX_LENGTH]; int len; printf("Enter a string:"); gets(str); len = my_strlen(str); printf("The lenght of the string %s is %d \n",str,len);

תרגיל 3 תוכנית לחיבור 2 מחרוזות הממחישה שימוש במצביעים: תוכנית לחיבור 2 מחרוזות הממחישה שימוש במצביעים:  #include <stdio.h> #include <string.h> #define MAX_LENGTH 81   /*Option #1*/ void stringCat(char *s1, char *s2){ while (*s1 ) ++s1; /*We could equivalently have written: s1++; */ do } *s1 = *s2; s1++; s2++; } while(*s2); *s1 = '\0'; /*Option #2*/ while (*s1 ) ++s1; while(*(s1++) = *(s2++)); {

המשך תרגיל 3 /*Option #3*/ void stringCat(char *s1, char *s2){ strcpy(s1+strlen(s1),s2); } void main(){ char str1[MAX_LENGTH], str2[MAX_LENGTH]; printf("Enter a string #1 with maximum %d characters:",(MAX_LENGTH-1)/2); gets(str1); printf("Enter a string #2 with maximum %d characters:",(MAX_LENGTH-1)/2); gets(str2); stringCat(str1,str2); /*We can use any (but not more than one) of the options above! */ printf("The final string is \"%s\" \n",str1);

תרגיל 4 כתוב פונקציה char * strstr(char *st1, char *st2) שמקבלת כארגומנט שתי מחרוזות. במידה שהמחרוזת st2 מוכללת במחרוזתst1 , הפונקציה מחזירה מצביע לתו של st1 שממנו מתחילה המחרוזת הזאת, אחרת הפוקציה מחזירה NULL. #include <stdio.h> #include <stdlib.h> char * iterStrstr(char *st1, char *st2){ char *p1,*p2; int len2 = strlen(st2); int len1 = strlen(st1); while (len1>=len2){ for(p1=st1,p2=st2;*p2 && *p1==*p2;p1++,p2++); if(!*p2) return st1; st1++; len1--; } return NULL;

המשך תרגיל 4 void main(){ char st1[]="bnbnbacdhghg",st2[]="acd"; char *c; if(c= strstr(st1,st2)) printf ("The first character in both st2 and st1 is %c\n ",*c); else printf ("Sorry, st2 isn't contained in st1!!!\n"); {

זיכרון דינמי ישנן שתי שיטות לביצוע הקצאת זיכרון: הקצאת זיכרון סטטית והקצאת זיכרון דינאמית. הקצאת זיכרון סטטית - המהדר קובע את דרישות האחסון על פי הצהרת המשתנים, בזמן הקומפילציה (כך הקצאנו זיכרון עד כה!). בעיה שלעיטים צצה היא שאין אנו יכולים לנחש מראש את כמות הזיכרון שהתוכנית שלנו עלולה לצרוך. הקצאת זיכרון דינאמית - הקצאת מקום נעשה בזמן בריצה על יד קריאה לפונקציה malloc() (קיצור ל-memory allocation). פונקציה זו מקבלת כפרמטר את מס' הבתים שברצונינו להקצות ומחזירה את הכתובת של הבית הראשון ברצף הבתים שהקצאתה. אם הפונקציה נכשלת מוחזר הערך NULL. שחרור זיכרון דינאמית - מכיוון שהקצאת הזיכרון נעשתה בזמן ביצוע התוכנית, יש לדאוג לשחרר את הזיכרון לאחר שנסיים להשתמש בו. שיחרור של זיכרון דינאמי נעשה ע"י קריאה לפונקציה free(). הפונקציה מקבלת מצביע לכתובת תחילת קטע הזיכרון שרוצים לשחרר.

אופרטורים האופרטור sizeof האופרטור sizeof מחזיר את גודלו של הטיפוס בבתים. תבנית: sizeof (name_of_charecter) לדוגמא:sizeof (float) מחזיר 4. אילו הינו כותבים: float f; sizeof(f) היה מחזיר את אותו דבר (4). שימוש בפונקציה malloc: variable_pointer = (pointer_type) malloc (size_of_memory); דוגמא: int size, *p_list; printf("Enter the number of elements:"); scanf("%d", &size); p_list = (int*)malloc (size * sizeof(int)); if (l_list == NULL){ printf ("Failed to allocate memory , quiting… "); return; } free(l_list);

תרגיל 5 תוכנית להדגמה של מערך דו-מימדי דינאמי: כשרוצים להגדיר מערך דו מימדי בעל גודל משתנה, עלינו ליצור מערך של מצביעים למערכים. גודל המערך לא ידוע בתחילת התכנית ולכן נגדיר את המערך באמצעות פונקצית malloc(). בתחילה נאתחל מערך של מצביעים, ולאחר מכן נאתחל כל מצביע להיות מערך של ה- type הרצוי. למשל, יצירת מערך של int-ים בגודל המוגדר ע"י המשתמש שבכל איבר בו יש את הערך של מכפלת האינדקסים שלו: #include <stdio.h> #include <stdlib.h> void main(){ int i,j,rows,cols,t; int **array; printf("enter num of rows: "); scanf("%d",&rows); printf("enter num of columns: "); scanf("%d",&cols); if (!(array=(int **)malloc(rows*sizeof(int *)))){ printf("Memory allocation failed, quiting… "); return; } . . .

המשך תרגיל 5 for (i=0;i<rows;i++) } /*Fill in the different rows:*/ if (!(array[i]=(int *)malloc(cols*sizeof(int))))} for (t=0;t<i;t++) /*Free all priory allocated memory:*/ free(array[t]); free(array); printf("Memory allocation failed, quiting… "); return; /*Terminate the program!*/ } for (j=0;j<cols;j++) /*Fill in the different columns:*/ array[i][j]=i*j; for (i=0;i<rows;i++){ /*Print the different rows:*/ for (j=0;j<cols;j++) printf("%d ",array[i][j]); printf("\n");

המשך תרגיל 5 /*Free allocated memory:*/ for(i=0;i<rows;i++) free(array[i]); free(array); }

תרגיל 6 התכנית לא מדפיסה כלום. יש שגיאה בזמן ריצה .(run time error) עיין בקטע הבא וסמן את כל התשובות הנכונות:   #include <stdio.h> #include <stdlib.h> #define MAX 10 void main(){ int *ptr, *arr[MAX]; int i, j; for (i=MAX-1 ; i>=0; i--) if (arr[i] = (int *) malloc(i * sizeof(int))) for (j=0; j<i; j++) *(*(arr+i)+j) = j*i; ptr = *(arr+MAX-1); while (*ptr) printf ("%d ", *ptr--); }    התכנית לא מדפיסה כלום. יש שגיאה בזמן ריצה .(run time error) התכנית תדפיס: 9 18 27 36 45 54 63 72. התכנית תדפיס אינסוף אפסים. התכנית תדפיס 0. התכנית תדפיס ערכים לא ידועים. אף לא אחת מהתשובות לעיל.

פתרון תרגיל 6