Presentation is loading. Please wait.

Presentation is loading. Please wait.

Introduction to Programming in C

Similar presentations


Presentation on theme: "Introduction to Programming in C"— Presentation transcript:

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

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

3 מצביעים תאור הזיכרון של המחשב:
ניתן לחשוב על זיכרון המחשב כעל רצף של תאים, כל אחד בגודל בית (byte) כאשר כל בית בגודל של 8 סיביות (bits) כאשר כל סיבית יכולה לקבל או ערך 1 או ערך 0. סה"כ כל בית (byte) יכול לכן לקבל 256 ערכים שונים המייצגים את מנעד המספרים הבינאריים באורך 8. כתובת הזיכרון- כל תא בזיכרון מזוהה ע"י ערך מספרי המתאר את מיקומו המדוייק. ערך זה הינו הכתובת של התא בזיכרון (memory address). למשל, אם נגדיר את המשתנים הבאים: char var1; // storage for type char is 1 byte on any platform. double var2; // storage for type double is mostly 8 bytes but can varies - it’s platform dependent int var3; // storage for type int is mostly 4 bytes but can varies -it’s platform dependent sizeof המחזירה את גודל הטיפוס בבתים.sizeofעל מנת לדעת גודל טיפוס ניתן להשתמש בפונקציה sizeof (name_of_character)בצורה: sizeof (char) אילו הינו כותבים לדוגמה: היינו מקבלים 1. תוכן הזיכרון- בכל כתובת בזיכרון מופיע ערך מספרי כלשהו המייצג את הערך הספציפי של הטיפוס הנמצא בכתובת זו. טווח ערכים זה נע בין 0 ל ^(8*sizeof(type)) . משמעות הערך נגזרת מגודל מספר זה ומסוג הטיפוס עצמו השמור בכתובת זו.

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

5 תיאור הזיכרון במחשב var1 var2 var3 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 כתובת של משתנה הינה הכתובת של הבית הראשון ברצף הבתים שמשתנה זה תופס בזיכרון.  ברגע שנצהיר על משתנים כמצביעים, נוכל להציב לתוכם כתובות של משתנים. לדוגמא: 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.

6 תאור סכמתי של הזיכרון 200 466675 x 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 מכיל את הכתובת של המשתנה x. הערה: לשם פשטות מתואר המצב בציור בו לטיפוס המצביע ולמשתנה int מוקצה לכאורה בית אחד בלבד אולם במציאות דרושים מספר בתים לייצג שני טיפוסים אלה.

7 דוגמאות 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”.*/ printf(“%p”, p) ;//print the address of p printf(“%d”, *p) ;//print 200 p=500; // < שקול= => x=500;. זהירות בעת שימוש במצביעים: כשמצהירים על מצביע p אין הוא בהכרח מצביע על ערך חוקי! int *pi; *pi = 100; /*wrong!!!! to correct : do before this operation : ” pi = <concrete address>; ” */ טעות זו ידועה בשם segmentation fault ,זוהי אינה שגיאת קומפילציה, אלא, שגיאה בזמן ריצה. מצביעים למצביעים - כאמור מצביע הוא משתנה המכיל כתובת של משתנה. אותו משתנה מוצבע יכול עקרונית גם הוא להיות מצביע. לדוגמה נוכל להוסיף לקוד: int **p2=&p printf(“%d”,**p2);//print 200

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

9 דוגמא נוספת #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. */

10 תרגיל 1 שאלה 1: נתונה השורה הבאה של תכנית בשפת C: int a, *b, c[4];
סמנו את כל ההוראות שאינן יכולות להופיע באופן חוקי בהמשך התכנית. הוראה חוקית היא הוראה נכונה מבחינה תחבירית שעוברת קומפילציה. א) *(c+3) = 8; //same as 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;

11 תרגיל 1 נתונה השורה הבאה של תכנית בשפת C: int a, *b, c[4];
סמנו את כל ההוראות שאינן יכולות להופיע באופן חוקי בהמשך התכנית. הוראה חוקית היא הוראה נכונה מבחינה תחבירית שעוברת קומפילציה. א) *(c+3) = 8; //same as c[3]=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;

12 עדכון מספר ערכים ראינו כבר כי ע"י שימוש בפונקציה ניתן לקבל ערך החזרה יחיד בלבד. לדוגמה: רוצים לחשב שני שורשים של משוואה ריבועית. דרך ראשונה לחשב זאת ע"י קריאות מתאימות לפונקציה: #include<stdio.h> #include<Math.h> double roots(double a,double b,double ,int discriminant_sign){ double discriminant = sqrt(b*b-4*a*c); discriminant *=discriminant_sign; return (-b+discriminant)/(2*a); } void main(){ double root1 = roots(2,-6,4, 1); double root2 = roots(2,-6,4, -1); כאשר 1 מסמל חישוב שורש עם דיסקרימיננטה חיובית ו-(-1) עם דיסקרימיננטה שלילית.

13 תרגיל 2 כתוב אותה פונקציה כך שהשורשים נשלחים כארגומנטים ומתעדכנים בפונקציה עצמה

14 פתרון ע"י שימוש במצביעים
void roots(double a,double b,double c,double *pz1,double *pz2){ double discriminant = sqrt(b*b-4*a*c); *pz1=(-b+discriminant)/(2*a); *pz2=(-b-discriminant)/(2*a); } void main(){ double root1, root2; roots(2,-6, 4, &root1, &root2); printf(“roots: %f %f\n”, root1, root2); דרך זו עדיפה מכיוון שמבנה הפונקציה פשוט וטבעי יותר וגם הקריאה לפונקציה מתבצעת פעם אחת בלבד. במקרה זה אמנם עידכנו סה"כ 2 משתנים אבל יתכנו מקרים בהם נרצה לעדכן מספר רב יותר של משתנים ואז הדבר יהיה משמעותי יותר

15 תרגיל 3 כתוב פונקציה char * strstr(char *st1, char *st2) שמקבלת כארגומנט שתי מחרוזות. במידה שהמחרוזת st2 מוכללת במחרוזתst1 , הפונקציה מחזירה מצביע לתו של st1 שממנו מתחילה המחרוזת הזאת, אחרת הפוקציה מחזירה NULL.

16 תרגיל 3 #include <stdio.h> #include <stdlib.h>
char * strstr (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;

17 המשך תרגיל 3 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"); {

18 ניהול הזיכרון בתוכנית עד כה כל המשתנים שראינו היו לוקאליים. משך הקיום של משתנים מקומיים הוא הזמן אשר הפונקציה בה הם נמצאים פועלת. משתנים אלה מאוחסנים בכל כניסה לפונקציה במקום בזיכרון שנקרא מחסנית שהוא למעשה "שולחן העבודה" של הפונקציה אשר רצה ברגע הנתון. ברגע שהפונקציה סיימה את עבודתה, "שולחן העבודה" שלה על משתניו כבר אינו רלוונטי ולכן אותו קטע בזיכרון יכול לשמש את הפונקציות הבאות בתור לרוץ. לעיתים כאשר ברצוננו להקצות מקום בזיכרון למשתנה כך שגודלו אינו ידוע לנו מראש (למשל בהצהרה על מערך אנו מבזבזים הרבה זיכרון רק משום שאנו לא יודעים מראש את הגודל המתאים לקלט) אנו זקוקים להקצאה זיכרון דינאמית בזמן ריצת התוכנית. סיבה נוספת להקצאה דינאמית היא רצון למשל ליצור מבנה נתונים שישמש לאורך כל התוכנית ולא רק בפונקציה בה נוצר. בהקצאת זיכרון דינאמית – בשונה מהקצאה סטטית המקום המוקצה בזיכרון נמצא בחלק הנקרא ערימה וקיומו שם משך כל זמן ריצת התוכנית ולא רק בפונקציה שם הוא נוצר. בנוסף בניגוד להקצאה סטטית בהקצאה דינאמית על המשתמש חובת שחרור זיכרון מפורשת עם סיום התוכנית (או אפילו קטע הקוד המשתמש באותו משתנה שהוגדר דינאמית).

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

20 הקצאת זיכרון דינאמית שימוש בפונקציות: malloc ,free #include <stdlib.h> //must add this library pointer_variable = (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)); …. free(p_list); שחרור הזיכרון בסיום השימוש בו

21 דוגמא להקצאת ושחרור זיכרון
כאשר מקצים זיכרון הערך המוחזר על ידי פונקצית הקצאת זיכרון היא כתובת. יש מקרים שבעבורם הקצאת הזיכרון נכשלת והערך המוחזר על ידי הפונקציה הוא NULL. מכיוון שלא קיבלנו כתובת, לא ניתן להשתמש במצביע כמצביע "חוקי" ונרצה לסיים את התוכנית. לכן, לאחר הקצאת זיכרון תמיד צריך לבדוק האם ההקצאה הצליחה. void main(){ long *l_list; l_list =(long*) malloc (5*sizeof(long)); if (l_list == NULL){ printf ("Failed to allocate memory"); return; } … free(l_list); }

22 דוגמא נתבונן בתוכנית הבאה: printf("%d",x[0]);
#include <stdio.h> #include <stdlib.h> int* foo (); int* foo (){ int arr[3]={1,2,3}; return arr; } void main(){ int* x = foo (); printf("%d",x[0]); התנהגות תוכנית זו אינה מוגדרת מכיוון שהפונקציה מחזירה מצביע למערך לוקאלי. כאשר הפונקציה מסתיימת הזיכרון בו נמצא המערך אינו חוקי עוד לשימוש. נתקן את הפונקציה בצורה הבאה: int *arr = (int*) malloc(sizeof(int)*3); arr[0]=1; arr[1]=2; arr[2]=3; לאחר סיום ריצת הפונקציה ולאחר שסיימנו להשתמש במערך, נדאג לשחרר את הזיכרון ע"י הוספת הפקודה הבאה ל- main או לכל פונקציה אחרת בה זיהינו כי אין עוד צורך בזיכרון שהוקצה. free(x);

23 תרגיל 1 תוכנית להדגמה של מערך דו-מימדי דינאמי: כשרוצים להגדיר מערך דו מימדי בעל גודל משתנה, עלינו ליצור מערך של מצביעים למערכים. גודל המערך לא ידוע בתחילת התכנית ולכן נגדיר את המערך באמצעות פונקצית malloc(). בתחילה נאתחל מערך של מצביעים, ולאחר מכן נאתחל כל מצביע להיות מערך של ה- type הרצוי. למשל, יצירת מערך של int-ים בגודל המוגדר ע"י המשתמש שבכל איבר בו יש את הערך של מכפלת האינדקסים שלו:

24 תרגיל 1 #include <stdio.h> #include <stdlib.h> void main(){ int i, j, k, rows, cols; 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; } . . .

25 המשך תרגיל 1 for (i=0; i<rows; i++) } /*Fill in the different rows:*/ if ( !(array[i]=(int *)malloc(cols*sizeof(int)) ))} for (k=0; k<i; k++) /*Free all priory allocated memory:*/ free( array[k] ); 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");

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

27 תרגיל 2 התכנית לא מדפיסה כלום. יש שגיאה בזמן ריצה .(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; //same as arr[i][j]=j*i ptr = *(arr+MAX-1); while (*ptr) printf ("%d ", *ptr--); }    התכנית לא מדפיסה כלום. יש שגיאה בזמן ריצה .(run time error) התכנית תדפיס: התכנית תדפיס אינסוף אפסים. התכנית תדפיס 0. התכנית תדפיס ערכים לא ידועים. אף לא אחת מהתשובות לעיל.

28 פתרון תרגיל 2

29 פתרון תרגיל 2

30 תרגיל 3: נתונה הפונקציה הבאה:
char *search(char *str1, char *str2){ int i, j, k, length; char *temp, *aux=NULL; for(i=0, length=0; *(str1+i); i++) for(j=0; *(str2+j); j++){ for(k=0; *(str1+i+k) && *(str1+i+k) == *(str2+j+k); k++); if( k>length ){ length=k; aux=str1+i; } //if } //for j if(aux) if( temp = (char *)malloc(length+1) ){ for(i=0; i<length; i++) *(temp+i )= *(aux+i); *(temp+i)='\0'; return temp; return NULL; } תרגיל 3: נתונה הפונקציה הבאה:

31 תרגיל 3 הסבר בקצרה מה יעודה של הפונקציה הנ"ל. מה הפלט של קטע קוד הבא:
מה הפלט של קטע קוד הבא: char sentence1[]=”It is clever of him to solve the problem”; char sentence2[]=”I am glad to solve your problem”, *sentence3; sentence3 = search(sentence1, sentence2); puts(sentence3);

32 תרגיל 3 - תשובות הפונקציה מוצאת את המחרוזת המשותפת הארוכה ביותר לשתי המחרוזות הניתנות. הפונקציה מעתיקה את המחרוזת שנמצאה למחרוזת חדשה ומחזירה מצביעה לתחילתה. במקרה שלא קיימת מחרוזת משותפת או שהקצאת הזיכרון נכשלה, הפונקציה מחזירה NULL

33 structures מבנה (struct) הוא טיפוס אשר יכול להכיל מספר רב של נתונים מטיפוסים שונים. המבנה מורכב ממשתנים, שלכל אחד מהם קוראים שדה. ניתן לומר שמבנה דומה למערך בכך ששניהם יכולים לאגד מספר נתונים, אך מבנה נותן לנו גם חופש בבחירת טיפוסי הנתונים ,כלומר מבנה יכול להכיל גם float, int, double ועוד בעת ובעונה אחת תחת משתנה אחד. התבנית של מבנה: struct nameOfStruct { fields }; בהגדרת המבנה יש לכתוב את המילה השמורה struct ולאחר מכן את שם המבנה שבחרנו. חשוב ששמו של המבנה יהיה משמעותי בדיוק כמו בבחירת שמות למשתנים. בתוך הסוגריים יש לרשום את המשתנים ובסוף נקודה-פסיק.

34 structures לדוגמא: struct address { char city[20]; char street[20]; int houseNum; }; יצרנו מבנה של "כתובת מגורים" הכולל: שם עיר ורחוב - מחרוזות בעלות 20 תווים, ומספר בית - משתנה מסוג int. כעת נצהיר על משתנה מהטיפוס "כתובת מגורים": struct address addr;

35 structures אופרטור הנקודה: כשנרצה לגשת לשדות של המשתנה addr ולעדכן אותם, נוכל לעשות זאת על ידי שימוש באופרטור הנקודה (.). לדוגמא, נציב את המספר 5 בשדה של מספר הבית באופן הבא: addr.houseNum = 5; כך ניתן לעדכן ולשנות את השדות. ניתן להצהיר על מספר משתנים מטיפוס מבנה בשורה אחת כמו שהצהרנו על משתנים פשוטים, לדוגמא: struct address addr1, addr2, addr3; כמו כן ניתן לאתחל מבנים כפי שאתחלנו מערך: struct address addr = {"Tel Aviv", "Menachem Begin", 132}; ניתן גם לבצע השמה בין מבנים, בצורה הבאה : addr1=addr2; נסכם ונאמר כי ניתן לבצע את כל הפעולות שביצענו במשתנים פשוטים על מבנה באותו אופן (הצבה כארגומנט בפונקציה, הצהרה וכו').

36 structures אופרטור <- : האופרטור <- מאפשר גישה לשדה של מבנה כלשהו ממצביע למבנה. לדוגמא, נגדיר מצביע למבנה address, pAddress: struct address addr, *pAddr; pAddr = &addr; נוכל לגשת לשדה houseNum של המבנה ע"י כתיבת: addr.houseNum = 3; או: pAddr->houseNum = 3; (*pAddr).houseNum = 3;

37 structures מבנה כפרמטר של פונקציה: נראה שני סוגים של העברת מידע האגור במבנים אל פונקציה כפרמטר - האחד העברה לפי כתובת והשני לפי תוכן. תרגיל 1: כתוב תכנית אשר מכילה פונקציה שקולטת לתוך מבנה שם וגיל של אדם, ובאמצעות פונקציה נוספת מדפיסה אותם.

38 structures #include <stdio.h> // by reference void getDetails (struct person *p) { printf ("Enter name: "); gets (p->name); printf ("Enter age: "); scanf ("%d", &(p->age)); } //by value void printDetails (struct person p) printf("name: %s\n ", p.name); printf("age: %d\n ", p.age); void main() struct person pr; getDetails (&pr); printDetails (pr); הסבר: בפונקצית main() יש מבנה מסוג person בשם pr. כשנפעיל את הפונקציה getDetails, נרצה שהיא תוכל לשנות את המבנה, ולכן נעביר לפונקציה את הכתובת של המשתנה pr. לפיכך, הפרמטר של הפונקציה getDetails צריך להיות כתובת - כלומר מצביע.

39 structures מבנה כערך המוחזר על ידי פונקציה:
כאשר אנו מעוניינים לקלוט נתוני מבנה, לפעמים נעשה זאת בעזרת פונקציה המחזירה מבנה. בהצהרה על הפונקציה יש לרשום: struct nameOfStruct nameOfFunction(arguments); תרגיל 2: שנה את הפונקציה getDetails מהתכנית הקודמת כך שתחזיר מבנה, ועדכן את ה-main בהתאם.

40 structures struct person getDetails(){ struct person pers; printf ("Enter name: "); gets (pers.name); printf ("Enter age: "); scanf ("%d", &(pers.age)); return pers; } void main(){ struct person pr; pr=getDetails(); printDetails (pr);

41 structures מערך של מבנים: ניתן ליצור מערך של מבנים בדיוק כמו בהצהרת מערך רגיל. לדוגמא: struct person pr[3]; יוצר מערך של שלושה משתנים מטיפוס person . כדי לגשת לשדותיו יש לפנות קודם לאיבר במערך שבו אנו מעוניינים - לדוגמא, עבור השדה name באיבר השני של המערך, נרשום: pr[1].name תרגיל 3: שנה את התכנית הקודמת כך שתעבוד עם מערך של מבנים.

42 structures #include <stdio.h> void getDetails (struct person p[],int size){ int i; for (i=0; i<size; i++) { printf ("Enter name: "); gets (p[i].name); printf ("Enter age: "); scanf ("%d", &(p[i].age)); } void printDetails (struct person p[],int size){ for (i=0; i<size; i++) { printf("name: %s\n ", p[i].name); printf("age: %d\n ", p[i].age); void main(){ struct person pr[3]; getDetails (pr,3); printDetails (pr,3);


Download ppt "Introduction to Programming in C"

Similar presentations


Ads by Google