Presentation is loading. Please wait.

Presentation is loading. Please wait.

קבצים קרן כליף. © Keren Kalif 2 ביחידה זו נלמד:  מוטיבציה לעבודה עם קבצים  סוגי קבצים:  בינאריים  טקסט  פעולות על קבצים (עבור שני סוגי הקבצים): 

Similar presentations


Presentation on theme: "קבצים קרן כליף. © Keren Kalif 2 ביחידה זו נלמד:  מוטיבציה לעבודה עם קבצים  סוגי קבצים:  בינאריים  טקסט  פעולות על קבצים (עבור שני סוגי הקבצים): "— Presentation transcript:

1 קבצים קרן כליף

2 © Keren Kalif 2 ביחידה זו נלמד:  מוטיבציה לעבודה עם קבצים  סוגי קבצים:  בינאריים  טקסט  פעולות על קבצים (עבור שני סוגי הקבצים):  פתיחת קובץ  קריאה מקובץ  כתיבה לקובץ  סגירת קובץ  פעולות נוספות: fseek, ftell, rewind, ferror, fflush, feof

3 © Keren Kalif 3 קבצים - מוטיבציה  כאשר אנחנו כותבים תוכנה, המידע אשר אנחנו מכניסים בכל הרצה הולך לאיבוד עם סיומה, מאחר והתוכנה רצה בזיכרון ה- RAM של המחשב  היינו רוצים לשמור את המידע בין ההרצות בזיכרון הקבוע (Hard Disk) כדי:  ליצור תוכנה בעלת משמעות ורצף  להקל עלינו בעת בדיקות התוכנה  קריאת נתונים מקובץ מוכן מראש ולא מהמשתמש  שמירת נתונים לשימוש ע"י תוכניות אחרות  ניתן לשמור את המידע בכמה אופנים שונים:  DB (לא יילמד בקורס זה)  קבצים

4 © Keren Kalif 4 עבודה כללית עם קבצים - מוטיבציה  יתכן ותהייה לנו תוכנית שנרצה לשמור את הפלט שלה לקובץ  יתכן ותהייה לנו תוכנית שנרצה שהקלט שלה יהיה מקובץ, ולא מהמקלדת  דוגמא:  קריאת אוסף מספרים מקובץ בפורמט ידוע מראש והצגת סכום המספרים  כתיבת תוכנית המכינה דו"ח כלשהו ושומרת את הדוח בקובץ, בנוסף להצגתו על המסך

5 © Keren Kalif 5 סוגי קבצים  קובץ טקסט:  כתוב בשפה אותה אנו יכולים לקרוא ולהבין  קובץ בינארי:  לא ניתן להבין את התוכן

6 © Keren Kalif 6 מבנה עבודה כללי עם קבצים  קובץ הוא משתנה מטיפוס *FILE ומוגדר ב- stdio.h  בתחילת העבודה יש לפתוח קובץ לקריאה/לכתיבה תוך ציון האם זהו קובץ טקסט או בינארי  יש לבדוק האם פתיחה הצליחה  לבסוף יש לסגור את הקובץ 1. void main() 2. { 3. FILE* f = fopen(, ); 4. if (f == NULL) 5. { 6. printf("Failed opening the file. Exiting!\n"); 7. return; 8. } 9. // here some operation with the file fclose(f); 11. }

7 © Keren Kalif 7 פתיחת קובץ – פרמטרים לסוג הפתיחה FILE* fopen(char* fileName, char* mode);  פתיחת קובץ טקסט לקריאה: “r”  פתיחת קובץ טקסט לכתיבה:  “w” - במידה ויש נתונים בקובץ הם ידרסו  “a” – כותב לסוף קובץ (כלומר לא דורס את המידע, אם קיים). לא מאפשר כתיבה לתחילת הקובץ!  פתיחת קובץ טקסט לקריאה ולכתיבה:  “r+” – הקובץ חייב להיות קיים, יתקבל NULL אם לא  “w+” – אם הקובץ קיים, דורס אותו  “a+” – אם הקובץ קיים כותב לסופו, אחרת יוצר קובץ חדש. לא מאפשר כתיבה לתחילת הקובץ!  כדי לפתוח את הקובץ כבינארי נוסיף b בסוף הפרמטר לפתיחה. למשל: “rb”, “wb” וכו'. ברירת המחדל היא קובץ טקסט.  ניתן ב- mode הפתיחה לציין t, עבור קובץ טקסט. למשל: “wt”

8 © Keren Kalif 8 פתיחת קובץ – סיבות לכשלון  קובץ המוגדר לקריאה בלבד שמנסים לפתוח אותו לכתיבה  פתיחה ע"י "r" קובץ שאינו קיים

9 © Keren Kalif 9 סגירת קובץ  int fclose(FILE* file);  מקבלת מצביע לקובץ ומחזירה 0 אם הצליחה לסגור אותו, אחרת תחזיר 1- (הקבוע EOF)  תכשל למשל כאשר מנסים לסגור קובץ שאינו פתוח  int fcloseall();  סוגרת את כל הקבצים שפתחנו ומחזירה את מספר הקבצים שסגרה

10 © Keren Kalif 10 כתיבה לקובץ טקסט  פקודות הכתיבה לקובץ טקסט הן כמו הפקודות לכתיבה למסך, פרט לכך ש:  שמן מתחיל עם f  הן מקבלות פרמטר נוסף שהוא מצביע לקובץ אליו רוצים לכתוב  int fprintf(FILE*, char*,... );  int fputs(char*, FILE*);  int fputc(char, FILE*);

11 © Keren Kalif 11 כתיבה לקובץ טקסט – דוגמא (1) 1. #include void main() 4. { 5. FILE* f = fopen("myFile.txt", "w"); 6. int res; 7. if (f == NULL) 8. { 9. printf("Failed opening the file. Exiting!\n"); 10. return; 11. } fprintf(f, "%s %d %lf\n", "KerenK", 28, 99.8); 14. fputs("Hello World!", f); 15. fputc('A', f); fclose(f); 18. } דריסת הקובץ אם קיים

12 © Keren Kalif 12 כתיבה לקובץ טקסט – דוגמא (2) 1. #include void main() 4. { 5. FILE* f = fopen("myFile.txt", "w"); 6. int res; 7. if (f == NULL) 8. { 9. printf("Failed opening the file. Exiting!\n"); 10. return; 11. } 12. fputs("Hello World!\n", f); 13. fclose(f); f = fopen("myFile.txt", "a"); 16. fputs("And Good Morning!\n", f); 17. fclose(f); 18. } פתיחת הקובץ וכתיבה לסופו

13 © Keren Kalif 13 כתיבה לקובץ טקסט – דוגמא (3) 1. #include void main() 4. { 5. FILE* f = fopen("myFile.txt", "w"); 6. int res; 7. if (f == NULL) 8. { 9. printf("Failed opening the file. Exiting!\n"); 10. return; 11. } 12. fputs("Hello World!\n", f); 13. fclose(f); f = fopen("myFile.txt", “w"); 16. fputs("And Good Morning!\n", f); 17. fclose(f); 18. } דריסת הקובץ הקודם...

14 © Keren Kalif 14 קריאה מקובץ טקסט  פקודות הקריאה לקובץ טקסט הן כמו הפקודות הקריאה למסך, פרט לכך ש:  שמן מתחיל עם f  הן מקבלות פרמטר נוסף שהוא מצביע לקובץ אליו רוצים לכתוב  int fscanf(FILE*, char*,... );  char* fgets(char*, int n, FILE*); מחזירה את המחרוזת שקראה או NULL אם לא הצליחה (למשל הקובץ נגמר)  int fgetc(FILE*); מחזירה את ערך האסקיי של התו או את הקבוע EOF (שערכו 1-) אם לא הצליחה (למשל הקובץ נגמר) מקבלות גם את כמות התווים לקריאה. קוראת עד ‘\n’ או עד n-1 תווים

15 © Keren Kalif 15 שמירה וקריאה מקובץ - כללי  כאשר נשמור מידע לקובץ, אנו בוחרים לשמור את המידע בסדר מסוים  צריכה להיות התאמה בין סדר כתיבת הנתונים לקובץ לסדר קריאת הנתונים מהקובץ  למשל: אם כתבתי מידע על סטודנט בסדר הבא: שם, ת.ז. וגיל, גם סדר קריאת הנתונים יהיה זהה  כלומר, צריכה להיות הסכמה וידיעה בין מי שכותב לקובץ ומי שקורא ממנו לגבי סדר הנתונים בקובץ

16 © Keren Kalif 16 קריאה מקובץ טקסט – דוגמא 1. #define SIZE void main() 3. { 4. char str[]="Hi", sentence[]="Hello World!", str2[SIZE], sentence2[SIZE]; 5. int num1=6, num2=0; 6. float f1=4.5, f2=0; 7. FILE* f = fopen("myFile.txt", "w"); 8. // check if open file succeeded fputs(sentence, f); 11. fprintf(f, "\n%d %f %s\n", num1, f1, str); 12. fclose(f); printf("Before reading from file:\nnum2=%d f2=%f str=|%s| sentence2=|%s|\n", num2, f2, str2, sentence2); 15. f = fopen("myFile.txt", "r"); 16. // check if open file succeeded fgets(sentence2, SIZE, f); 19. fscanf(f, "%d %f %s", &num2, &f2, str2); printf("\nAfter reading from file:\nnum2=%d f2=%f str=|%s| sentence2=|%s|\n", num2, f2, str2, sentence2); 22. fclose(f); 23. }

17 © Keren Kalif 17 feof  int feof (FILE * stream);  פונקציה זו מקבלת קובץ פתוח ומחזירה 0 אם לא הגענו לסוף הקובץ, ו- 1- (EOF) במידה והגענו לסוף

18 © Keren Kalif 18 דוגמא – העתקת קובץ 1. void main() 2. { 3. char ch; 4. FILE* fSource, *fDest; 5. fSource = fopen("example.txt", "r"); 6. // check if open file succeeded fDest = fopen("exampleCopy.txt", "w"); 9. // check if open file succeeded ch = fgetc(fSource); 12. while (!feof(fSource)) // OR: (ch != EOF) 13. { 14. fputc(ch, fDest); 15. ch = fgetc(fSource); 16. } fclose(fSource); // returns 0 since close file succeed 19. fclose(fDest); // returns 0 since close file succeed 20. } fcloseall(); // returns 2 since closed 2 files

19 © Keren Kalif 19 קריאת מספרים מקובץ וחישוב הממוצע 1. #include 2. void main() 3. { 4. FILE* f; 5. int num, sum=0, counter=0, rc; f = fopen("numbers.txt", "r"); 8. // check if open succeed rc = fscanf(f, "%d", &num); 11. while (rc != EOF) //OR: (!feof(f)) 12. { 13. printf("The read numbers is %d\n", num); 14. sum += num; 15. counter++; 16. rc = fscanf(f, "%d", &num); 17. } 18. fclose(f); 19. printf("The average is %f\n", (float)sum/counter); 20. }

20 © Keren Kalif 20 שמירת וטעינת רשומות לקובץ טקסט  כאשר כותבים רשומה לתוך קובץ טקסט, יש לכתוב שדה-שדה  כאשר קוראים רשומה מקובץ טקסט, יש לקרוא שדה-שדה

21 © Keren Kalif 21 שמירת וטעינת רשומות מקובץ טקסט - דוגמא 1. #define SIZE struct Person 3. { 4. char name[SIZE]; 5. long id; 6. float age; 7. } typedef person_t; 8. void main() 9. { 10. person_t p1={"momo", 1111, 23.5}, p2 = {"gogo", 2222, 24.8}, p3, p4; 11. FILE* f = fopen("persons.txt", "w"); 12. fprintf(f, "%s %ld %.2f\n", p1.name, p1.id, p1.age); 13. fprintf(f, "%s %ld %.2f\n", p2.name, p2.id, p2.age); 14. fclose(f); 15. f = fopen("persons.txt", "r"); 16. fscanf(f, "%s %ld %f\n", p3.name, &p3.id, &p3.age); 17. fscanf(f, "%s %ld %f\n", p4.name, &p4.id, &p4.age); 18. fclose(f); 19. printf("p3: name: %s\t id: %ld\t age: %.2f\n", p3.name, p3.id, p3.age); 20. printf("p4: name: %s\t id: %ld\t age: %.2f\n", p4.name, p4.id, p4.age); 21. }

22 © Keren Kalif 22 שמירה וטעינת מערך של רשומות מקובץ טקסט  כאשר כותבים מערך לקובץ, השדה הראשון צריך להיות מספר הרשומות שאנו כותבים, כדי שקורא הקובץ ידע כמה רשומות יש בתוכו

23 © Keren Kalif 23 שמירה וטעינה - מערך רשומות (1) 1. struct Person 2. { 3. char name[SIZE]; 4. long id; 5. float age; 6. } typedef person_t; void main() 9. { 10. FILE* f; 11. person_t* personsSource, *personsDest; 12. int sizeSource, sizeDest, i; 13. printf("How many persons? "); 14. scanf("%d", &sizeSource); // allocating the persons array 17. personsSource = (person_t*)malloc(sizeSource*sizeof(person_t)); 18. // reading persons for (i=0 ; i < sizeSource ; i++) 20. { 21. printf("Enter name, id and age of person #%d: ", i+1); 22. scanf("%s %ld %f", personsSource[i].name, &personsSource[i].id, &personsSource[i].age); 23. } 24. }

24 © Keren Kalif f = fopen("persons.txt", "w"); 25. fprintf(f, "%d\n", sizeSource); // writing the size to the file 26. for (i=0 ; i < sizeSource ; i++) // writing each person to the file 27. fprintf(f, "%s %ld %f\n", personsSource[i].name, personsSource[i].id, personsSource[i].age); 28. fclose(f); free(personsSource); // don’t forget to free the array!! f = fopen("persons.txt", "r"); 33. fscanf(f, "%d\n", &sizeDest); // reading the size from the file 34. // allocating the new array 35. personsDest = (person_t*)malloc(sizeDest*sizeof(person_t)); 36. // reading each person from the file 37. for (i=0 ; i < sizeDest ; i++) 38. fscanf(f, "%s %ld %f\n", personsDest[i].name, &personsDest[i].id, &personsDest[i].age); 39. fclose(f); printf("There are %d persons in the file:\n", sizeDest); 42. for (i=0 ; i < sizeDest ; i++) 43. printf("Person #%d: Name=%s\t Id=%ld\t Age=%f\n", i+1, 44. personsDest[i].name, personsDest[i].id, personsDest[i].age); free(personsDest); // don’t forget to free the array!! 47. }

25 © Keren Kalif 25 כתיבה לקובץ בינארי  פקודת הכתיבה לקובץ בינארי:  int fwrite(const void * ptr, // address of variable to write int size, // size of type int count, // number of elements FILE * stream (; // pointer to the file  מחזירה את כמות האיברים שכתבה  כאשר כותבים לקובץ בינארי ניתן לכתוב בלוק של מידע  למשל: מערך או רשומה בפעולת כתיבה בודדת  יש להיזהר מכתיבת פוינטרים לקובץ!

26 © Keren Kalif 26 קריאה מקובץ בינארי  פקודת הקריאה מקובץ בינארי:  int fread(void* ptr, // address of variable to read into int size, // size of type int count, // number of elements FILE* stream (; // pointer to the file  מחזירה את כמות האיברים שקראה  כאשר קוראים מקובץ בינארי ניתן לקרוא בלוק של מידע  למשל: מערך או רשומה בפעולת קריאה בודדת

27 © Keren Kalif 27 שמירת וטעינת רשומות מקובץ בינארי - דוגמא 1. #define SIZE struct Person 3. { 4. char name[SIZE]; 5. long id; 6. float age; 7. } typedef person_t; void main() 10. { 11. person_t p1={"momo", 1111, 23.5}, p2 = {"gogo", 2222, 24.8}, p3, p4; 12. FILE* f = fopen("persons.bin", "wb"); 13. fwrite(&p1, sizeof(person_t), 1, f); 14. fwrite(&p2, sizeof(person_t), 1, f); 15. fclose(f); f = fopen("persons.bin", "rb"); 18. fread(&p3, sizeof(person_t), 1, f); 19. fread(&p4, sizeof(person_t), 1, f); 20. fclose(f); printf("p3: name: %s\t id: %ld\t age: %.2f\n", p3.name, p3.id, p3.age); 23. printf("p4: name: %s\t id: %ld\t age: %.2f\n", p4.name, p4.id, p4.age); 24. } ניתן לקרוא ולכתוב רשומה בפעולה אחת!

28 © Keren Kalif 28 שמירה וטעינה מערך רשומות מקובץ בינארי (1) 1. #define SIZE struct Person 3. { 4. char name[SIZE]; 5. long id; 6. float age; 7. } typedef person_t; void main() 10. { 11. FILE* f; 12. person_t* personsSource, *personsDest; 13. int sizeSource, sizeDest, i; 14. printf("How many persons? "); 15. scanf("%d", &sizeSource); // allocating the persons array 18. personsSource = (person_t*)malloc(sizeSource*sizeof(person_t)); 19. for (i=0 ; i < sizeSource ; i++) // reading persons { 21. printf("Enter name, id and age of person #%d: ", i+1); 22. scanf("%s %ld %f", personsSource[i].name, 23. &personsSource[i].id, &personsSource[i].age); 24. } 25. }

29 © Keren Kalif f = fopen("persons.bin", "wb"); 26. fwrite(&sizeSource, sizeof(int), 1, f); // writing the size to the file 27. // writing all persons to the file 28. fwrite(personsSource, sizeof(person_t), sizeSource, f); 29. fclose(f); 30. free(personsSource); // don’t forget to free the array!! f = fopen("persons.bin", "rb"); 33. // reading the size from the file 34. fread(&sizeDest, sizeof(int), 1, f); 35. // allocating the new array 36. personsDest = (person_t*)malloc(sizeDest*sizeof(person_t)); 37. // reading all persons from the file 38. fread(personsDest, sizeof(person_t), sizeDest, f); 39. fclose(f); printf("There are %d persons in the file:\n", sizeDest); 42. for (i=0 ; i < sizeDest ; i++) 43. printf("Person #%d: Name=%s\t Id=%ld\t Age=%f\n", 44. i+1, personsDest[i].name, personsDest[i].id, personsDest[i].age); // don’t forget to free the array!! 47. free(personsDest); 48. }

30 © Keren Kalif 30 כתיבת רשומות המכילות מצביעים  יש לשים לב לא לכתוב מצביעים לתוך קובץ, שכן אין הבטחה שבפעם הבאה שהתוכנית תרוץ יהיו ערכים בכתובות הנוכחיות שאנו שומרים  לכן, כאשר יש משתנה שהוא כתובת יש להקפיד לרשום את ערכו לקובץ  נשים לב: לא נוכל להשתמש בשיטה של לרשום רשומה ע"י fwrite, אלא נהיה חייבים לכתוב את הרשומה לקובץ שדה-שדה  בד"כ אם המצביע הוא למערך, נרשום כשדה נוסף את כמות האלמנטים במערך, ורק אח"כ את איבריו (כנ"ל עבור מחרוזת).

31 © Keren Kalif 31 דוגמא – שמירה וטעינה של רשומה עם מצביעים 1. #include 2. #include 3. #include 4. struct Student 5. { 6. char* name; 7. float average; 8. } typedef student_t; 9. void main() 10. { 11. student_t stud1 = {"yoyo", 91.8}, stud2; 12. FILE* f = fopen("students.bin", "wb"); 13. int len1, len2; 14. // check open succeed len1 = strlen(stud1.name)+1; 17. fwrite(&len1, sizeof(int), 1, f); 18. fwrite(stud1.name, sizeof(char), len1, f); 19. fwrite(&stud1.average, sizeof(float), 1, f); 20. fclose(f); f = fopen("students.bin", "rb"); 23. // check open succeed fread(&len2, sizeof(int), 1, f); 26. stud2.name = (char*)malloc(len2*sizeof(char)); 27. fread(stud2.name, sizeof(char), len2, f); 28. fread(&stud2.average, sizeof(float), 1, f); 29. fclose(f); 30. printf("stud2: name=%s, average=%.2f\n", 31. stud2.name, stud2.average); 32. free(stud2.name); 33. }

32 © Keren Kalif 32 פקודה fseek  מאפשר לטייל בקובץ בלי לקרוא חלק משדותיו int fseek(FILE* f, // the file long int offset, // how much int origin (; // from where  originיקבל אחד מהערכים הבאים:  SEEK_SET – לזוז מתחילת הקובץ  SEEK_END – לזוז לסוף הקובץ  SEEK_CUR – לזוז מהמיקום הנוכחי  הפונקציה תחזיר 0 אם הצליחה לזוז כמתבקש  לידע כללי: יש מערכות הפעלה בהן fseek לא עובדת טוב על קבצי טקסט

33 © Keren Kalif 33 fseek - דוגמא 1. #include int main () 4. { 5. FILE * f; 6. f = fopen("myfile.txt", "w"); 7. // check if open succeed fputs("This is an apple", f); 10. fseek (f, 9, SEEK_SET); 11. fputs(" sam", f); 12. fclose(f); 13. }

34 © Keren Kalif 34 fseek – דוגמא – החבר הכי טוב 1. #define MAX_LEN typedef struct Friend 3. } 4. char name[MAX_LEN]; 5. int numOfPresentsBoughtMe; 6. } Friend; void sortFriendByPresents(Friend friends[], int size) 9. } 10. Friend temp; 11. int i, j; for (i=0 ; i < size ; i++) 14. } 15. for (j=i+1 ; j < size ; j++) 16. } 17. if (friends[i].numOfPresentsBoughtMe > friends[j].numOfPresentsBoughtMe) 18. } 19. temp = friends[i]; 20. friends[i] = friends[j]; 21. friends[j] = temp; 22. { 23. } 24. { 25. {

35 © Keren Kalif 35 fseek – דוגמא – החבר הכי טוב (2) 1. void main() 2. } 3. FILE* f; 4. Friend bestFriend; 5. Friend myFriends[] = { {"momo", 5}, {"gogo", 2}, {"yoyo", 7} }; 6. int numOfFriends = sizeof(myFriends) / sizeof(myFriends[0]); sortFriendByPresents(myFriends, numOfFriends); f = fopen("myFriends.bin", "wb"); // check open file succeed fwrite(&numOfFriends, sizeof(int), 1, f); 12. fwrite(myFriends, sizeof(Friend), numOfFriends, f); 13. fclose(f); 14. numOfFriends = 0; // just reset to see correct value is read from file // get the friend that bought me most presents 16. f = fopen("myFriends.bin", "rb"); // check open file succeed fread(&numOfFriends, sizeof(int), 1, f); 18. fseek(f, sizeof(Friend)*(numOfFriends-1), SEEK_CUR); 19. //OR: fseek(f, sizeof(Friend)*-1, SEEK_END); 20. fread(&bestFriend, sizeof(Friend), 1, f); 21. fclose(f); 22. printf("The friend who bought me most presents: %s\n", bestFriend.name); 23. {

36 © Keren Kalif 36 הפקודה ftell  מחזירה את מרחק הסמן מתחילת הקובץ long ftell (FILE * f);  דוגמא: קריאת גודל של קובץ 1. #include int main () 4. { 5. FILE* f; 6. long size; f = fopen ("myFile.txt", "r"); 9. // check if open succeed fseek (f, 0, SEEK_END); 12. size = ftell(f); 13. fclose (f); 14. printf ("Size of myfile.txt: %ld bytes.\n",size); 15. }

37 © Keren Kalif 37 הפקודה rewind  מחזירה את הסמן לתחילת הקובץ: void rewind(FILE* f);  דוגמא: קריאת וכתיבת כל ה- ABC 1. int main () 2. { 3. int n; 4. FILE *f; 5. char buffer [27]; f = fopen ("allLetters.txt","w+"); 8. // check if open succeed for ( n='A' ; n<='Z' ; n++) 11. fputc ( n, f); 12. rewind (f); 13. fscanf(f, "%s", buffer); 14. fclose (f); 15. buffer[26]='\0'; 16. puts (buffer); 17. }

38 © Keren Kalif 38 הפקודה fflush  int fflush(FILE* f)  מרוקנת את ה- buffer של הקובץ. בדיוק כמו שמנקים את ה- buffer מהמקלדת ע"י fflsh(stdin). מחזירה 0 אם הצליחה.  int fflush()  מרוקנת את ה- buffer'ים של כל ה- stream הפתוחים (קבצים, stdin וכד'). מחזירה 0 אם הצליחה.

39 © Keren Kalif 39 הפקודה ferror  פקודה זו מחזירה 0 במידה והפעולות שבוצעו על הקובץ תקינות  דוגמא: כאשר ננסה לכתוב לקובץ שנפתח לקריאה בלבד 1. void main() 2. { 3. FILE* f = fopen("myfile.txt","r"); 4. if (f == NULL) 5. { 6. printf("Error opening file\n"); 7. return; 8. } fputc('x', f); 11. if (ferror(f)) 12. printf ("Error Writing to myfile.txt\n"); 13. fclose(f); 14. }

40 © Keren Kalif 40 דוגמא: ניהול קורסים וסטודנטים במכללה  דגשים לתוכנית:  שימוש בקבועים  פונקציות יעודיות להדפסה ולקבלת קלט  מודולריות  חלוקה לקבצים  יצירת פונקציה עבור לוגיקה ספציפית, עבור תחזוקה עתידית  למשל: getDepartmentCodeFromCourseCode

41 © Keren Kalif 41 קובץ אינדקסים - מוטיבציה  בהינתן קובץ טקסט עם שורות (ניתן להניח שאורך כל שורה הוא מקסימום 255 תווים, אבל לא בהכרח) נרצה לקרוא תו ספציפי בשורה מסוימת  הפתרון: נקרא שורה-שורה עד השורה המבוקשת, ובתוכה נזוז למיקום הרצוי  דוגמא: בהינתן הקובץ הבא, נרצה להגיע לתו ה- 7 בשורה 4

42 © Keren Kalif 42 הקוד 1.void main() 2.{ 3. int line, col, i; 4. char text[256], ch; 5. FILE* f = fopen("test.txt", "r"); printf("Enter line and col --> "); 8. scanf("%d%d", &line, &col); for (i=1 ; i < line ; i++) 11. fgets(text, 256, f); fseek(f, col-1, SEEK_CUR); 14. ch = fgetc(f); 15. printf("The char is '%c'\n", ch); fclose(f); 18.} דילוג על השורות הראשונות. לא ניתן לדלג באמצעות fseek כי אורך השורות שונה. כאשר הסמן נמצא בתחילת השורה המבוקשת, נקפוץ ישירות למיקום התו אותו רוצים לקרוא. פעולת הקריאה מקובץ היא פעולה יקרה ולכן נרצה מנגנון אחר שיחסוך זאת. כלומר, מנגנון שונה להגעה ישירה לשורה המבוקשת.

43 © Keren Kalif 43 קובץ אינדקסים - בפתרון  כאשר רוצים לבצע קריאות רבות ונקודתיות מקובץ בעל אורך שורות שונה שאינו משתנה, נשתמש במנגנון הנקרא "קובץ אינדקסים"  קובץ זה יכיל מספרים, כאשר המספר ה-i הוא מיקום התו הראשון בשורה ה- i בקובץ  דוגמא:  שימושים: למשל עבור ספר טלפונים (נתוניו קבועים), נרצה לקבל נתונים של רשומה אחת  כל שינוי בקובץ המקורי יגרור שינוי בקובץ האינדקס

44 © Keren Kalif 44 יצירת קובץ אינדקס קובץ האינדקס חייב להיות בינארי כדי שבקריאה נוכל לדלג כל פעם על int שלם פתיחת קובץ הטקסט לקריאה, וקובץ האינדקס בינארי לכתיבה נמצא את כמות התווים בקובץ הטקסט נמצא את מיקום הסמן בתחילת כל שורה, ונכתוב ערך זה לקובץ האינדקסים void main(int argc, char* argv[]) { char indexFileName[128], line[256]; FILE *textFile, *indexFile; int currentIndex, numOfChars; createIndexFileName(argv[1], indexFileName); textFile = fopen(argv[1], "r"); indexFile = fopen(indexFileName, "wb"); fseek(textFile, 0, SEEK_END); numOfChars = ftell(textFile); fseek(textFile, 0, SEEK_SET); currentIndex = 0; while (currentIndex < numOfChars) { fwrite(¤tIndex, sizeof(int), 1, indexFile); fgets(line, 256, textFile); currentIndex = ftell(textFile); } fclose(textFile); fclose(indexFile); }

45 © Keren Kalif 45 יצירת שם קובץ האינדקס  פונקציה זו יוצרת את שם קובץ האינדקס כך:  עבור קובץ.txt  שם קובץ האינדקס יהיה: _index.bin  דוגמא: עבור test.txt שם ובץ האינדקס יהיה test_index.bin void createIndexFileName(const char* origName, char indexName[]) { strcpy(indexName, origName); strtok(indexName, "."); strcat(indexName, "_index.bin"); }

46 © Keren Kalif 46 void main(int argc, char* argv[]) { FILE *textFile, *indexFile; int col, row, lineStartIndex; char ch; textFile = fopen(argv[1], "r"); indexFile = fopen(argv[2], "rb"); printf("Enter row and col --> "); scanf("%d%d", &row, &col); fseek(indexFile, (row-1)*sizeof(int), SEEK_SET); fread(&lineStartIndex, sizeof(int), 1, indexFile); fseek(textFile, lineStartIndex+col-1, SEEK_SET); fscanf(textFile, "%c", &ch); printf("The char is %c\n", ch); fclose(textFile); fclose(indexFile); } שימוש בקובץ אינדקס פתיחת קובץ הטקסט וקובץ האינדקס הבינארי לקריאה קריאה מקובץ האינדקס את מיקום תחילת השורה הזזת הסמן בקובץ הטקסט למיקום המבוקש וקריאה

47 © Keren Kalif 47 דוגמאת סיכום: קבצים, סיביות, variadic functions  כתוב פונקציה המקבלת שם של קובץ בינארי וכמות כלשהי של מספרים, שנתון שסכומם הוא 8 (המספר האחרון יהיה 0, ליצוג סיום הפרמטרים)  כל מספר מייצג כמות סיביות המייצגות מספר.  יש לקרוא את הקובץ הבינארי ולהציג את המספרים המקודדים בתוכו.  למשל, עבור המספרים 4,1,3 והבתים הבאים שנקראו מהזכרון (abc): יודפסו למסך המספרים הבאים:

48 © Keren Kalif #include 2. #include 3. #include 4. #include unsigned char createMask(int high, int low); 7. int getSubNumber(char ch, unsigned char mask, int high, int low); 8. void readNumbers(const char* fileName,...); void main() 11. { 12. char str[] = "abc"; // a: b: c: FILE* f = fopen("test.bin", "wb"); 14. fwrite(str, sizeof(char), strlen(str), f); 15. fclose(f); readNumbers("test.bin", 4, 1, 3, 0); 18. {

49 © Keren Kalif 49 /* This function receives higher and lower bounds of bit indexes, and creates a mask with 1 in this range, and 0 in all other places. I.E: high=5, low=3, the mask char would be: */ 19. unsigned char createMask(int high, int low) 20. { 21. return ( 1 << ( high + 1 ) ) - ( 1 << low ); 22. { 6 >> >> = מוזמנים לקרוא את ההסבר לפונקציה זו בדפים שבאתר!

50 © Keren Kalif void readNumbers(const char* fileName,...) 29. { 30. FILE* f; 31. va_list numbers; 32. int highBit, lowBit, i, numOfNumbers=0, arr[8]; 33. unsigned char ch; 34. unsigned char* masks; f = fopen(fileName, "rb"); 37. if (f == NULL) 38. exit(1); // get the numbers 41. va_start(numbers, fileName); 42. arr[numOfNumbers] = va_arg(numbers, int); 43. while (arr[numOfNumbers] != 0) 44. } 45. numOfNumbers++; 46. arr[numOfNumbers] = va_arg(numbers, int); 47. { // allocate the masks array 50. masks = (char*)malloc(numOfNumbers*sizeof(unsigned char));

51 © Keren Kalif // creates the masks 52. highBit=7; 53. for (i=0 ; i < numOfNumbers ; i++) 54. } 55. lowBit = highBit - arr[i] + 1; 56. masks[i] = createMask(highBit, lowBit); 57. highBit = lowBit - 1; 58. } 59. while (1) 60. } 61. fread(&ch, sizeof(char), 1, f); 62. if (feof(f))break; 63. printf("From char '%c' --> ", ch); 64. highBit=7; 65. for (i=0 ; i < numOfNumbers ; i++) 66. { 67. lowBit = highBit - arr[i] + 1; 68. printf("%d ", ((ch & masks[i]) >> lowBit)); 69. highBit = lowBit - 1; 70. } 71. printf("\n"); 72. { 73. fclose(f); 74. free(masks); 75. {

52 © Keren Kalif 52 דוגמא: יצירת קובץ בינארי המכיל קידוד תמונה  יש לייצר קובץ בינארי המכיל יצוג של תמונה.  תמונה מורכבת מ- M*N פיקסלים, כך שלכל פיקסל יש צבע (יש 16 צבעים אפשריים).  יש לכתוב לקובץ את מימדי התמונה ואח"כ את כל הפיקסלים לפי הסדר: הפיקסלים מהשורה הראשונה, השניה וכו'.  על מנת לשמור כל צבע, ניתן להסתפק ב- 4 סיביות  בכל byte ניתן לשמור נתונים עבור 2 פיקסלים  תמונה עם M*N פיקסלים תשמר ב- N*M/2 + 2 בתים 2 בתים בהתחלה לשמירת מימדי התמונה

53 © Keren Kalif 53 דוגמא 2: שינוי צבע לפיקסל מסוים בתמונה  יש לתת קאורדינטת x,y וצבע, ובגישה ישירה לעדכן את הפיקסל.  יש לשים לב האם הצבע עבור הקאורדינטה המבוקשת נמצא בצד הימני אא בצד השמאלי של ה- byte בו הוא נשמר

54 © Keren Kalif 54 ביחידה זו למדנו:  מוטיבציה  אופרטורים לעבודה עם סיביות:  &  |  ^  ~  >>  <<


Download ppt "קבצים קרן כליף. © Keren Kalif 2 ביחידה זו נלמד:  מוטיבציה לעבודה עם קבצים  סוגי קבצים:  בינאריים  טקסט  פעולות על קבצים (עבור שני סוגי הקבצים): "

Similar presentations


Ads by Google