תירגול 10: מבנים (structs) וקבצים

Slides:



Advertisements
מצגות קשורות
תכנות בשפת C תרגול 11 - קבצים.
Advertisements

© Keren Kalif JPA קרן כליף.
הרצאה 02 סוגי משתנים קרן כליף.
יצירת מקרו הפעלת מקרו יצירת לחצן / פקד דוגמה מסכמת
Computer Programming Fall 2012 תרגול 6 פונקציות
מבוא לתכנות ב-JAVA מעבדה 1
תוכנה 1 תרגול 13 – סיכום.
תרגול 11: רקורסיה ופיתוח טלסקופי
תרגול 1: סביבת העבודה ומבוא ל-Java
לולאות Department of Computer Science-BGU 19 יולי 19.
נערך ע"י אריק הוד, הגימנסיה העברית הרצליה
תרגול 5: לולאות ומערכים.
תרגול מס' 8 משתנים מיוחסים מבוא ל-C++ קלט/פלט ב-C++
מבוא למדעי המחשב מ' - תירגול 9
רמי כהן, מדעי המחשב, הטכניוןכל הזכויות שמורות ©
עבודה ב-T2 מבוא לתכנות מערכות.
Jump tables, review questions
הרצאה 3: משפטים, תנאים ולולאות
מבצעים: רועי מור טל מסרי
מבוא למדעי המחשב הרצאה מספר 12: רקורסיה
תכנות בשפת C תרגול 11 רשימות מקושרות מבנים
תרגול Introduction to C - Fall Amir Menczel.
פעולות אריתמטיות קרן כליף.
Computer Programming תרגול 1 Summer 2016
תירגול 11: מיונים וחיפוש בינארי
נערך ע"י אריק הוד הגימנסיה העברית הרצליה
Entity Relationship Diagram – ERD
תירגול 3: לולאות, קלט, וטיפוסים
תכנות בשפת C תרגול 8 רקורסיה
Engineering Programming A
תירגול 8:מצביעים והקצאה דינאמית
© המרכז להוראת המדעים האוניברסיטה העברית בירושלים
מבוא למדעי המחשב הרצאה 9: רקורסיה
תרגול 6: פונקציות, סוגי משתנים, top-down design
תירגול 2: מבוא לתיכנות ב-C
רובוטיקה תרגול שימוש בלולאות
מקורות שדה מגנטי קובץ זה נועד אך ורק לשימושם האישי של מורי הפיזיקה ולהוראה בכיתותיהם. אין לעשות שימוש כלשהו בקובץ זה לכל מטרה אחרת ובכלל זה שימוש מסחרי;
כל הזכויות שמורות לגבריאל אנקרי © 2017
© המרכז להוראת המדעים האוניברסיטה העברית בירושלים
מבוא לתכנות מונחה עצמים Object Oriented Programming
© המרכז להוראת המדעים האוניברסיטה העברית בירושלים
הרצאה 10: אלגוריתמי מיון רקורסיביים Merge sort ו-Quick sort
מבוא לתכנות למערכות מידע
Computer Architecture and System Programming Laboratory
אלגוריתמי מיון רקורסיביים
המשך תכנות מונחה עצמים תרגול מס' 9.
כל הזכויות שמורות לגבריאל אנקרי © 2017
תרגול 13 : חזרה נכתב על-ידי לימור ליבוביץ נערך ע"י ישראל גוטר
Marina Kogan Sadetsky –
מת"מ מעבדה 7-8 רשימות.
© המרכז להוראת המדעים האוניברסיטה העברית בירושלים
שימוש בעצם ממחלקה אחרת כמאפיין במחלקה הנוכחית
מבוא לתכנות ב- JAVA מעבדה 4
מבנה כללי של היררכיית הקבצים עבור המסלול /A/B.txt
מבוא למדעי המחשב סמסטר ב' – 2008 מרצה: יעל סיגל מתרגל: ענבל בודובסקי.
Introduction to Programming in C
תרגול 12: backtracking.
מצביעים Pointers – המשך...
מעבדה 2- עיצוב (עבור חלק ג)
מבנה מחשבים ספרתיים תרגול מס' 4: זכרון מטמון 2.
עקרונות תכנות מונחה עצמים תרגול 9:C++ - תרגילים
Java Programming רשימות מקושרות - המשך
הפונקציה מחזירה את מספר התווים במחרוזת נתונה.
Engineering Programming A
רשימות מקושרות עבודה עם קבצים דוגמה
תמליל מצגת:

תירגול 10: מבנים (structs) וקבצים

מבנים מבנה (structure) הוא טיפוס מורכב בשפת C . זהו טיפוס שמיועד לאיחוד קבוצת משתנים תחת שם אחד. מגדיר טיפוס חדש בשם “struct date” struct date { int day; int month; int year; }; שדות המבנה יש להסביר שהגדרה זו יוצרת טיפוס חדש בשם struct date, הכולל בתוכו שלושה משתנים מטיפוס int: day, month, year. הדרך לתת לטיפוס את השם הרצוי, date, היא באמצעות typedef, שלא נלמד הסמסטר. שימו לב: פקודה זו אינה מקצה זיכרון כלשהו, אלא רק מגדירה טיפוס חדש. טיפוס זה יוכל לשמש אותנו בהמשך להצהרה על משתנים.

שימוש במבנים נגדיר משתנים מטיפוס struct date: על מנת לגשת ל-int כלשהו בתוך yael_bd או ofer_bd עלינו להשתמש באופרטור נקודה ('.'): struct date yael_bd, ofer_bd; yael_bd.day = 1; yael_bd.month = 1; yael_bd.year = 1111; יש להדגיש כי תמיד מציינים במפורש את שם המבנה כדי לגשת למשתנה הפנימי. לדוגמה, השורה האחרונה תגרום לשגיאת קומפילציה, כי המשתנה day אינו מוגדר. printf("%d\n", ofer_bd.day); מה תדפיס השורה הבאה? printf("%d\n", day);

שימוש במבנים ניתן לבצע השמה של מבנה כלשהו למבנה אחר מאותו הטיפוס. פעולת ההשמה מעתיקה את התוכן של כל אברי המבנה לתוך אלו של המבנה השני. לדוגמה: פעולת ההשמה בשורה האחרונה מבצעת העתקה של שלושה int-ים, מהמבנה twin1_birthday למבנה twin2_birthday. struct date twin1_birthday; struct date twin2_birthday; twin1_birthday.day = 23; twin1_birthday.month = 12; twin1_birthday.year = 1983; twin2_birthday = twin1_birthday;

שימוש במבנים לא ניתן לבצע השוואה של מבנה כלשהו למבנה אחר מאותו הטיפוס. לדוגמה הקוד הבא אינו עובר קומפילציה: כדי להשוות בין מבנים נרשום פונקציה יעודית struct date twin1_birthday = { 23,12,1983 }; struct date twin2_birthday = twin1_birthday; if (twin2_birthday == twin1_birthday) printf("Twins\n");

תרגיל הגדירו משתנה מטיפוס צמח ששדותיו הם: שם, כמות מים ליום, כמות דשן ליום ואת התאריך בו התקבל. struct plant { char name[100]; double water_per_day; double fertilizer_per_day; struct date plant_date; }; הדגישו כי לאחר הגדרתו, גם date struct הוא טיפוס, ולכן גם הוא יוכל להופיע כשדה במבנה החדש.

שימושי מבנים כיוון שמבנים הם בוודאי טיפוסים, נוכל ליצור מהם מערכים כרגיל: struct date birthday_list[10]; כמו כן, נוכל ליצור משתנה plant_ptr מטיפוס מצביע שמכיל כתובות של משתנים מטיפוס struct plant. struct plant *plant_ptr = 0; יש להדגיש כי אתחלנו את המצביע ל-0 מכיוון שהוא לא מצביע לשום מקום בזיכרון. השימוש במצביע יתבצע כך: struct plant p; plant_ptr = &p; (*plant_ptr).water_per_day = 30.0;

שימושי מבנים נוכל להעביר מבנה כפרמטר לפונקציה by value (את המבנה עצמו): void print_plant_water(struct plant p) { printf("%f", p.water_per_day); } נוכל להעביר מבנה כפרמטר לפונקציה by address (מצביע למבנה): void print_plant_water(struct plant *p) { printf("%f", (*p).water_per_day); { יש להסביר כי כאשר מעבירים את המבנה כפרמטר, מתבצע copy by value וכאשר יש שדות רבים למבנה, העתקה זו מאוד יקרה, לכן בד"כ נעדיף להשתמש במצביע. מה עדיף?

האופרטור -> האופרטור -> (חץ) שמופעל על מצביע למבנה, מאפשר גישה ישירה לתוך השדות של המבנה המוצבע. למשל, נתבונן בהגדרה: struct plant my_plant; struct plant *plant_ptr = &my_plant; בעזרת המצביע plant_ptr, נוכל כעת לגשת לשדות הפנימיים של המבנה my_plant בשתי דרכים (שקולות לחלוטין): (*plant_ptr).name (*plant_ptr).water_per_day plant_ptr->name; plant_ptr->water_per_day;

תרגיל 1 – חורף תשע"ו מועד ב' בשאלה זו נפתור בעיות הקשורות להובלה. כדי לנהל הובלה, כל קופסא שצריכה להכנס למשאית מתוארת ע"י המבנה הבא: struct box{ double weight; int x, y, z; }; השדה weight מתאר את משקל הקופסא. השדות x, y, z מתארים את רוחב גובה ועומק הקופסא בס"מ, בהתאמה. מכיוון שבכל הובלה יש מספר קופסאות, נעבוד עם מערך של קופסאות. למשל המערך הבא: מתאר הובלה של 4 קופסאות. weight =50.0 x=100 y=200 z=60 weight =10.5 y=80 weight =2.5 x=10 y=50 z=20 weight =3.1 x=15 y=10

תרגיל 1 - המשך סעיף א' (15 נקודות) ממשו פונקציה רקורסיבית שחתימתה: double total_weight(struct box arr[], int n); הפונקציה מקבלת כקלט מערך של קופסאות ואת אורכו, ומחזירה את המשקל הכולל של הקופסאות יחד. שימו לב: אסור להשתמש במשתנים סטטיים אסור להשתמש בלולאות

תרגיל 1 - המשך סעיף ב' (5 נקודות) כדי להחליט איזו מבין 2 קופסאות גדולה יותר, נשווה את הרוחב (x) שלהן. אם לשתי קופסאות אותו רוחב, נשווה את הגובה שלהן (y), ואם גם הרוחב וגם הגובה שווים, נשווה את העומק שלהן (z). אם ל-2 קופסאות אותם רוחב, גובה ועומק נגיד שגודלן שווה. ממשו פונקציה שחתימתה: struct box* boxcmp(struct box* b1, struct box* b2); הפונקציה מקבלת כקלט2 מצביעים לקופסאות, ומחזירה מצביע לגדולה ביניהן. אם הקופסאות באותו גודל, היא תחזיר מצביע לאחת מהן.

מבוא למדעי המחשב מ' - תירגול 2 תרגיל 1 - המשך סעיף ג' (15 נקודות)   ממשו פונקציה שחתימתה: struct box* new_hovala(struct box arr1[], int n1, struct box arr2[], int n2); הפונקציה מקבלת שני מערכים של קופסאות, ממוינים מהקטנה לגדולה כפי שהוגדר בסעיף הקודם. הפונקציה מקצה מקום למערך חדש של קופסאות באורך n1+n2, ומעתיקה אליו את הקופסאות משני המערכים, כך שגם המערך החדש נותר ממוין. הפונקציה מחזירה מצביע למערך החדש. מבוא למדעי המחשב מ' - תירגול 2

מבוא למדעי המחשב מ' - תירגול 2 תרגיל 1 - פתרון #include <stdbool.h> struct box { double weight; int x, y, z; }; double total_weight(struct box arr[], int n) { if (n <= 0) return 0; return total_weight(arr + 1, n - 1) + arr[0].weight; { struct box* boxcmp(struct box* b1, struct box* b2) { if (b1->x != b2->x) return b1->x > b2->x ? b1 : b2; if (b1->y != b2->y) return b1->y > b2->y ? b1 : b2; if (b1->z != b2->z) return b1->z > b2->z ? b1 : b2; return b1; } מבוא למדעי המחשב מ' - תירגול 2

תרגיל 1- פתרון struct box* new_hovala(struct box arr1[], int n1, struct box arr2[], int n2) } struct box* arr3 = malloc((n1 + n2) * sizeof(struct box)); if (!arr3) return NULL; int i1 = 0, i2 = 0, i3 = 0; while (i1 < n1 || i2 < n2) { if (i1 == n1) arr3[i3++] = arr2[i2++]; else if (i2 == n2) arr3[i3++] = arr1[i1++]; else arr3[i3++] = is_smaller(arr1 + i1, arr2 + i2) ? arr1[i1++] : arr2[i2++]; { return arr3; bool is_smaller(struct box* b1, struct box* b2) { if (b1->x != b2->x) return b1->x < b2->x; if (b1->y != b2->y) return b1->y < b2->y; if (b1->z != b2->z) return b1->z < b2->z; return false; }

יש לוודא שהפתיחה הצליחה עבודה עם קבצים - פתיחה פתיחת קובץ - הפעולה המקשרת בין מצביע מיוחד בתוכנית (מטפוס FILE*) לקובץ פיסי על ההתקן. File path and name Mode (r/w/a) פתיחת קובץ טקסט לקריאה FILE* fid=fopen)"c:\\temp\\speed1.dat", "r"); FILE* fid=fopen("c:\\temp\\speed1.dat", "w"); פתיחת קובץ טקסט לכתיבה mode operation r read w write a append יש לוודא שהפתיחה הצליחה נכתב ע"י יעל ארז. © כל הזכויות שמורות.

עבודה עם קבצים – קריאה וכתיבה פעולות קריאה/כתיבה נוספות ימשיכו מהמקום בו עצרנו. while (1) { fscanf(fid1,”…”, &…); if (feof(fid)) break; fprintf(fid2, “…”, …); } בסוף הקובץ נדלק דגל eof. לא לשכוח לסגור את הקבצים בסוף fclose(fid1); fclose(fid2); נכתב ע"י יעל ארז. © כל הזכויות שמורות.

מבוא למדעי המחשב מ' - תירגול 2 תרגיל 2 נתון הקובץ טקסט story.txt אשר יש להכניסו לספרית הפרויקט (שם הפרויקט מתחת למיקום בו נמצא קובץ ה sln. כעת, כיתבו תוכנית אשר קוראת את הטקסט מתוך הקובץ ומדפיסה את: מספר התווים בקובץ. מספר המילים בקובץ. מספר השורות בקובץ. ניתן להניח שהמילים מופרדות ברווח יחיד ואין רווחים בתחילת ובסוף הקובץ. מבוא למדעי המחשב מ' - תירגול 2

תרגיל 2 - פתרון #include <stdio.h> #include <stdlib.h> int main() { FILE* fid = fopen("story.txt", "r"); if (!fid) { printf("cannot open file\n"); return 1; } int char_cnt = 0, word_cnt = 0, line_cnt = 0; while (1) { char c; fscanf(fid, "%c", &c); if (feof(fid)) break; char_cnt++; if (c == '\n') line_cnt++; if (c == ' ') word_cnt++; fclose(fid); printf("the story has %d lines, %d words and %d chars\n", line_cnt, word_cnt, char_cnt); return 0; {

תרגיל 3 כיתבו תוכנית אשר קולטת מהמשתמש את מספר הסטודנטים והפרטים שלהם לפי המבנה הבא (ניתן להניח ששם הסטודנט לא יעבור 100 תווים): struct student { char* name; int id; double avg; } ; התוכנית תשמור את הפרטים במערך, ולאחר מכן תכתוב אותו לקובץ בשם students.txt כיתבו תוכנית אשר קוראת את הקובץ למערך של סטודנטים

תרגיל 3 - פתרון struct student { char* name; int id; double avg; }; #define MAX_LEN 100 int main() { int num_students; struct student* arr = read_data(&num_students); if (!arr) return 1; serialize(arr, num_students); free_arr(arr, num_students); arr = deserialize(&num_students); print_arr(arr, num_students); return 0; }

תרגיל 3 - פתרון struct student* read_data(int *num_students) { printf("enter number of students\n"); scanf("%d", num_students); struct student* arr = malloc(sizeof(struct student)*(*num_students)); if (!arr) return NULL; memset(arr, 0, sizeof(struct student)*(*num_students)); for (int i = 0; i < (*num_students); i++) { arr[i].name = malloc(sizeof(char)*(MAX_LEN + 1)); if (arr[i].name == NULL) { free_arr(arr, *num_students); } printf("enter name id and average:\n"); scanf("%s%d%lf", arr[i].name, &arr[i].id, &arr[i].avg); return arr; {

תרגיל 3 - פתרון void serialize(struct student* arr, int n) { FILE* fid = fopen("students.txt", "w"); if (!fid) return 1; fprintf(fid, "%d\n", n); for (int i = 0; i < n; i++) { fprintf(fid, "%d ", strlen(arr[i].name)); fprintf(fid, "%s ", arr[i].name); fprintf(fid, "%d %f\n", arr[i].id, arr[i].avg); { fclose(fid); } void free_arr(struct student* arr, int n) { for (int i = 0; i < n; i++) free(arr[i].name); free(arr);

struct student. deserialize(int. n) { FILE. fid = fopen("students struct student* deserialize(int* n) { FILE* fid = fopen("students.txt", "r"); if (!fid) return 1; fscanf(fid, "%d", n); struct student *arr = malloc(sizeof(struct student)*(*n)); if (!arr) return NULL; memset(arr, 0, sizeof(struct student)*(*n)); for (int i = 0; i < (*n); i++) { int name_len; fscanf(fid, "%d", &name_len); arr[i].name = malloc(sizeof(char)*(name_len + 1)); if (arr[i].name == NULL) { free_arr(arr, (*n)); } fscanf(fid, "%s %d %lf", arr[i].name, &arr[i].id, &arr[i].avg); fclose(fid); return arr; תרגיל 3 - פתרון

תרגיל 3 - פתרון void print_arr(struct student* arr, int n) { for (int i = 0; i < n; i++) { printf("%d. ", i+1); printf("%d %s %f\n", arr[i].id, arr[i].name, arr[i].avg); } {